基础版本抖音(字节跳动青训)

news2024/11/14 5:32:25

抖音基础版(字节跳动青训项目)

一、项目介绍

  • 本抖音项目是基于grpc通讯协议开发的高性能微服务,不仅使用gin作为业务层框架,gorm框架作为持久层框架,还使用预编译sql防止sql注入,同时该项目结合连接池技术来构建连接工厂和复用grpc连接来提高系统的性能,这样可以有效的处理高并发场景下的挑战,还可以通过减少频繁创建和销毁grpc连接带来的性能开销
  • 项目服务地址:https://1024code.com/codecubes/jpyi9rm
  • 项目地址:https://github.com/fineCoderWithLove/douyin-base

二、项目实现

2.1技术选型

  • gin:提供grpc服务使用protobuf进行数据传输。

  • JWT:token生成和权限的校验

  • Gorm:对Mysql执行ORM操作,Go-redis:操作Redis对频繁更改的数据进行缓存以便更快的响应。

  • Redis:对点赞/取消赞,视频的喜欢量/评论量,用户的喜欢量,总点赞量缓存Redis中,设置定时任务,并且使数据同步到数据库中。

  • Zap:高性能日志打印

  • ffmpeg:进行视频取帧,作为视频的封面

  • 七牛云:使用七牛云做对象存储,用来存储视频,图片等静态资源。

  • pprof:使用pprof进行性能测试

    2.2架构设计

    由于项目的耦合度不高,所以采用微服务架构来缓解服务器的压力,项目分为api层,业务服务层,数据层

  • api层负责鉴权和分发请求调用远程服务来返回数据

  • 业务层负责与数据库进行交互和逻辑处理

在这里插入图片描述

2.3代码目录介绍

├─base-service # 基础服务
│  ├─cmd # 启动类  
│  ├─global # 定义全局信息
│  │  └─constant # 定义全局常量
│  ├─handler # 业务处理
│  ├─model # 定义常用结构体
│  │  └─video
│  ├─proto # proto文件
│  │  └─favorite
│  ├─test # 测试类
│  ├─util # 封装工具类
│  └─videoproto # 视频的proto文件
├─douyin-api # 外部网关
│  ├─api # grpc服务调用
│  ├─cmd # 启动类
│  ├─global # 定义全局变量
│  ├─globalinit # 定义全局日志信息
│  │  └─constant
│  ├─proto # proto文件
│  ├─redis # 封装redis工具类
│  ├─router # 加载路由信息
│  └─util # 封装工具类
├─interaction-service # 互动模块
│  ├─dao # gen代码生成器
│  │  └─gen
│  ├─global # 定义全局信息
│  │  └─constant
│  ├─handler # 处理业务信息
│  ├─model # 定义常用结构体
│  ├─proto # proto文件
│  │  ├─comment
│  │  ├─favorite
│  │  ├─user
│  │  └─video
│  └─server # grpc启动类
│      ├─comment
│      └─favorite
├─log # 输入的日志信息
│  └─info
└─social-service # 社交模块
    ├─cmd # 启动类
    ├─global # 定义全局变量
    ├─handler # 处理业务
    ├─proto   # proto文件
    │  ├─favorite
    │  ├─message
    │  ├─relation
    │  └─user
    └─util # 封装的工具类

接口文档地址: https://apifox.com/apidoc/shared-09d88f32-0b6c-4157-9d07-a36d32d7a75c/api-50717106

三、测试结果

3.1功能测试

功能项接口名称测试点模块结果
基础接口视频流接口不限制登录状态,返回按投稿时间倒序的视频列表base-service测试通过
基础接口用户注册新用户注册时提供用户名,密码即可,用户名需要保证唯一。创建成功后返回用户 id 和权限tokenbase-service测试通过
基础接口用户登录通过用户名和密码进行登录,登录成功后返回用户 id 和权限 tokenbase-service测试通过
基础接口用户信息获取用户的 id、昵称,如果实现社交部分的功能,还会返回关注数和粉丝数base-service测试通过
基础接口投稿列表登录用户选择视频上传base-service测试通过
基础接口发布列表用户的视频发布列表,直接列出用户所有投稿过的视频base-service测试通过
互动接口赞操作登录用户对视频的点赞和取消点赞操作interaction-servic测试通过
互动接口喜欢列表用户的所有点赞视频interaction-service测试通过
互动接口评论操作登录用户对视频进行评论interaction-service测试通过
互动接口评论列表查看视频的所有评论,按发布时间倒序interaction-service测试通过
社交接口关注操作已登录的用户对其他用户进行关注social-service测试通过
社交接口关注列表已登录的用户查询其他用户的关注列表social-service测试通过
社交接口粉丝列表已登录的用户查询用户的粉丝列表social-service测试通过
社交接口好友列表已登录的用户查询好友列表social-service测试通过
社交接口发送消息已登录的用户给其他用户发送消息social-service测试通过
社交接口聊天记录已登录的用户查询与其他用户的聊天记录social-service测试通过

用户测试样例

用户鉴权失败样例


3.2性能测试

  1. 我们使用pprof进行性能监测,因为每次请求grpc都会产生连接和销毁连接造成服务的性能消耗,思考后我把grpc的连接设置成一个全局变量,后来发现这个全局变量有一个问题,在并发情况下,用同一个全局变量会导致读写错误。
  2. 经过思考,我设置了互斥锁的全局变量,但是性能提升不是很明显。
  3. 经过搜索引擎查询资料,最后利用线程池技术,简单工厂设计模式设计出了一个GrpcFactory工厂,每次只需要调用工厂就可以返回连接配合利用grpc的keep-alive使得grpc的连接开销变小。性能测试图如下:

优化前

在这里插入图片描述

优化后

在这里插入图片描述

四、项目总结与反思

4.1目前存在的问题

  1. 聊天记录存储到mysql中可能导致查询聊天记录mysql压力过大
  2. 敏感词过滤要耗费大量内存。

4.2已经识别的优化项

  1. 判断user和video是否存在的时候,可以直接从redis中判断增加速度
  2. 应该将聊天记录缓存到redis中{token:create_time}的形式,因为前端需要不断获取到最晚消息的发布时间
  3. 上传视频进行异步发送,减少用户等待时间优化用户体验。
  4. 因为迭代次数过多,代码冗余过多,代码内容不清晰,应该进行适当的封装和复用。

4.3架构演进的可能性

  1. 分库分表
  2. 做到数据库的读写分离
  3. 我们会在第七届青训营使用Hertz和Kitex重构代码
  4. 使用Minio做对象存储而不是使用七牛云
  5. 准备用机器学习训练模型加快强感词的过滤效果和速度而不是使用普通算法

4.4项目中的反思和总结

  • 代码应该尽可能优雅的写法,让以后的改动是方便的,应该满足开放封闭原则。
  • 一个优秀的程序员应该让别的程序员更好的工作,我的队友给我提供了很多的工具,让我工作更加高效。
  • 测试是一个项目的重点,没有测试的软件是不合格的,而测试的关键则是边界点的问题。
  • 每一个同步的位置都是并发情况下容易发生错误的地方,都要加上互斥锁。
  • 一个项目应该敢为极致,在自己力所能及的地方做到最好,应该尝试多种可能性,寻找最好的解决办法!

五、部署

  1. 安装ffmpeg环境
  2. 改变每个模块中global的mysql连接和redis连接
  3. 改变base-service下的video中的七牛云密匙和仓库名称
  4. Linux下执行命令./run.sh

六、演示视频

【消失的token作品视频】https://www.bilibili.com/video/BV1634y1T71p?vd_source=04ce138fbcd8dc0d65299e3dccf2b3f1


后续迭代

数据库索引的建立

  1. 用户登录接口索引设置
    用户登录接口,要验证用户名和密码的正确性,所以我们给user表的name和password字段加上了联合索引,避免了回表查询。
  2. 视频流接口索引设置
    视频流接口需要查询晚于某一个时间的视频,所以我们在视频的发布时间需要创建索引,同时考虑到了索引失效的问题,对已经有的sql进行优化。
  3. 关注列表索引设计
    我们的关注表是attention,其中字段只有user_id和touser_id,我们在获取关注列表的时候需要对这两个字段进行查询。
  4. 用户的喜欢列表索引
    用户喜欢的列表需要查询favorites表,我们在user_id,video_id创建了idx_favorites_user_video联合索引。
  5. 软删除评论的索引
  • 我们一开始设置软删除的时候是bool类型,但是这样使得索引效率不高,因为字段只有true和false,区分度低。
  • 最后我们设置一个删除的时间,提高了区分度,使得idx_delete_comment索引使用更高效。
  1. 查询评论的索引
    查询评论是根据视频的id查询的,我们在comments表的video_id创建了idx_select_comment_list 索引。

字典树算法实现敏感词过滤

在第七届,我们会使用机器学习训练模型来处理敏感词。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JDK9特性——模块化REPL工具

文章目录 前言模块化模块化案例 可交互的REPL工具 前言 谈到Java9大家往往第一个想到的就是Jigsaw项目(后改名为Modularity)。众所周知,Java已经发展超过20年(95年最初发布),Java和相关生态在不断丰富的同时也越来越暴露出一些问…

ubuntu(20.04)下截图贴图软件——flameshot(带设快捷键)

ubuntu(20.04)下截图贴图软件——flameshot 一、 安装二、打开Flameshot三、截图快捷键设置 windows习惯了用Snipaste的截图和贴图功能,在ubuntu中也有替代品Flameshot。 一、 安装 首先我们进入官网,并点击download。 在这里可…

轻松鲨-AI文案写作 人工智能聊天

轻松鲨AI助手使用地址:http://www.qingsongsha.com?utm_sourcenavigation_website 或前往苹果App Store下载“轻松鲨APP” 支持AI连续对话聊天,帮你解答各种疑问... 让AI帮你画思维导图写文案,提升工作效率... 内置多场景专业模板&#xff0…

[SQL Server]在应使用条件的上下文(在 ‘)‘ 附近)中指定了非布尔类型的表达式,查询时间大于某个数值时

这种条件查询条件里面不要有空格&#xff0c;一个也不要有 这种条件查询条件里面不要有空格&#xff0c;一个也不要有 $giftsDb::table(drawgot)->where(disabtime,<,"2030-01-03")->select();

安卓判断是否是模拟器,适配主流雷电,MUMU,夜神,逍遥

前言 最近游戏项目组又有新的要求&#xff0c;对于数据上报和数据统计接口&#xff0c;尽可能的具体化&#xff0c;比如是否是模拟器&#xff0c;模拟器的型号&#xff0c;品牌等&#xff0c;都要求统计&#xff0c;后续模拟器玩家在活动发放&#xff0c;安全风控等方面也易于…

Linux Spug自动化运维平台公网远程访问---内网穿透

文章目录 前言1. Docker安装Spug2 . 本地访问测试3. Linux 安装cpolar4. 配置Spug公网访问地址5. 公网远程访问Spug管理界面6. 固定Spug公网地址 前言 Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台&#xff0c;整合了主机管理、主机批量执行、主机在线终端、文件…

脚本:用python实现五子棋

文章目录 1. 语言2. 效果3. 脚本4. 解读5. FutureReference 1. 语言 Python 无环境配置、无库安装。 2. 效果 以第一回合为例 玩家X 玩家0 3. 脚本 class GomokuGame:def __init__(self, board_size15):self.board_size board_sizeself.board [[ for _ in range(board_…

InfiniBand vs 光纤通道,存储协议的选择

数字时代&#xff0c;数据量爆发增长&#xff0c;企业越来越迫切地追求高吞吐量、低延迟和更高性能的网络基础设施&#xff0c;存储协议的选择变得愈发至关重要。在众多存储协议中&#xff0c;InfiniBand和光纤通道备受关注。本文旨在深入探讨InfiniBand和光纤通道作为存储协议…

python之有限体积法求解一维热传导问题

1、问题描述 考虑均匀发热无限大平板的稳定导热问题&#xff0c;上图中&#xff0c;A、B两面恒温&#xff0c;控制方程为如下形式&#xff1a; 为扩散系数&#xff0c;为材料传热系数&#xff0c;给定厚度&#xff0c;&#xff0c;和分别为100℃和400℃&#xff0c;发热量q为50…

【C++】红黑树插入操作实现以及验证红黑树是否正确

文章目录 前言一、红黑树的插入操作1.红黑树结点的定义2.红黑树的插入1.uncle存在且为红2.uncle不存在3.uncle存在且为黑 3.完整代码 二、是否为红黑树的验证1.IsBlance函数2.CheckColor函数 三、红黑树与AVL树的比较 前言 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在…

气传导耳机什么意思?备受好评的气传导耳机推荐

​气传导耳机是近年来备受关注的一种新型耳机&#xff0c;它采用了独特的设计&#xff0c;将声音通过空气传递到耳朵&#xff0c;从而实现听音乐的效果。与传统的入耳式耳机相比&#xff0c;气传导耳机在听音乐的同时还能听到周围环境声音&#xff0c;提高了安全性和舒适性。如…

开学什么牌子的电容笔质量好耐用?精选4款好用的电容笔

随着新学期开始&#xff0c;我们该准备些什么&#xff1f;随着技术的发展&#xff0c;ipad上出现了各种各样的电容笔。一支好的电容笔&#xff0c;不但可以极大地提升我们的学习效率&#xff0c;也可以极大地提升我们的工作效率。国内厂商生产的这支平替电容笔&#xff0c;无论…

「网页开发|后端开发|Flask」08 python接口开发快速入门:技术选型写一个HelloWorld接口

本文主要介绍为网站搭建后端时的技术选型考虑&#xff0c;以及通过写一个简单的HelloWorld接口快速了解前端和后端交互的流程。 文章目录 本系列前文传送门一、场景说明二、后端语言技术选型三、后端框架技术选型Django 特点Flask 特点FastAPI 特点Tarnado 特点 四、用Flask先…

Gin 打包vue或react项目输出文件到程序二进制文件

Gin 打包vue或react项目输出文件到程序二进制文件 背景解决方案1. 示例目录结构2. 有如下问题要解决:3. 方案探索 效果 背景 前后端分离已成为行业主流&#xff0c;vue或react等项目生成的文件独立在一个单独目录&#xff0c;与后端项目无关。 实际部署中&#xff0c;通常前面套…

Scrum敏捷开发端到端管理流程

Leangoo领歌是Scrum中文网&#xff08;scrum.cn&#xff09;旗下的一款永久免费的敏捷研发管理工具。 Leangoo领歌覆盖了敏捷研发全流程&#xff0c;它提供端到端敏捷研发管理解决方案&#xff0c;包括小型团队敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scrum of Scrums…

父子进程区别与GDB多进程调试

父子进程之间的关系&#xff1a; 区别&#xff1a; 1.fork()函数的返回值不同&#xff0c;父进程中&#xff1a;>0 返回的子进程ID 子进程中&#xff1a;ID0 2.pcb中的数据有区别&#xff0c;当前进程的id pid &#xff0c;当前父进程的id ppid&#xff0c;信号集 共同点…

黑马头条 后端项目部署_持续集成 Jenkins配置

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从检出…

如何在RK3568开发板上实现USBNET?——飞凌嵌入式/USB Gadget/USB-NET/网络

本文将借助飞凌嵌入式OK3568-C开发板为大家介绍实现USBNET模式的方法&#xff0c;在这之前需要先知道什么是USB Gadget——USB Gadget是指所开发的电子设备以USB从设备的模式通过USB连接到主机。举个例子&#xff1a;将手机通过USB线插入PC后&#xff0c;手机就是USB Gadget。同…

【IP数据报】IP地址和MAC地址的区别

1、用IP地址来标识Internet的主机 在每个IP数据报中&#xff0c;都会携带源IP地址和目标IP地址来标识该IP数据报的源和目的主机。IP数据报在传输过程中&#xff0c;每个中间节点(IP 网关)还需要为其选择从源主机到目的主机的合适的转发路径(即路由)。IP协议可以根据路由选择协…

Android Update Engine 分析(十九)Extent 到底是个什么鬼?

文章目录 0. 导读1. 什么是 Extent?1. 什么是 Extent?2. Wikipedia 中的解释3. Ext4 中的 Extent2. Android OTA 中的 Extent2.1 update_metadata.proto 中的 Extent2.2 update engine 代码中的 Extentpayload_consumer 中的 Extentpayload_generator 中的 Extent2.3 OTA 中的…