├── .gitignore ├── LICENSE ├── README.md ├── api-gateway ├── go.mod ├── main.go ├── pkg │ ├── logging │ │ ├── file.go │ │ └── log.go │ └── utils │ │ └── jwt.go ├── runtime │ └── logs │ │ └── log20230213.log ├── services │ ├── comment │ │ ├── comment.pb.go │ │ └── comment.pb.micro.go │ ├── fav │ │ ├── fav.pb.go │ │ └── fav.pb.micro.go │ ├── feed │ │ ├── feed.pb.go │ │ └── feed.pb.micro.go │ ├── message │ │ ├── message.pb.go │ │ └── message.pb.micro.go │ ├── proto │ │ ├── fav.proto │ │ ├── publish.proto │ │ └── user.proto │ ├── publish │ │ ├── publish.pb.go │ │ └── publish.pb.micro.go │ ├── relation │ │ ├── relation.pb.go │ │ └── relation.pb.micro.go │ └── user │ │ ├── user.pb.go │ │ └── user.pb.micro.go ├── weblib │ ├── handlers │ │ ├── comment.go │ │ ├── errors.go │ │ ├── favorite.go │ │ ├── feed.go │ │ ├── message.go │ │ ├── publish.go │ │ ├── relation.go │ │ └── user.go │ ├── middleware │ │ └── init.go │ └── router.go └── wrappers │ ├── commentWrapper.go │ ├── favoriteWrapper.go │ ├── feedWrapper.go │ ├── messageWrapper.go │ ├── publishWrapper.go │ ├── relationWrapper.go │ └── userWrapper.go ├── comment ├── conf │ ├── conf.go │ └── config.ini ├── core │ └── commentService.go ├── go.mod ├── main.go ├── model │ ├── comment.go │ └── init.go ├── rpc_server │ ├── TokenRpc.go │ ├── etcd │ │ └── etcdInit.go │ ├── publishRpc.go │ └── userRpc.go ├── service │ ├── comment.pb.go │ ├── comment.pb.micro.go │ ├── frompublish │ │ ├── to_comment.pb.go │ │ └── to_comment.pb.micro.go │ ├── proto │ │ └── comment.proto │ ├── to_relation │ │ ├── to_relation.pb.go │ │ └── to_relation.pb.micro.go │ ├── token │ │ ├── token_utils.pb.go │ │ └── token_utils.pb.micro.go │ ├── tokenproto │ │ ├── token_utils.pb.go │ │ └── token_utils.pb.micro.go │ └── userproto │ │ ├── user.pb.go │ │ └── user.pb.micro.go └── utils │ └── redis │ └── redis.go ├── favorite ├── conf │ ├── conf.go │ └── config.ini ├── core │ ├── favoriteService.go │ └── tovideo │ │ └── toVideoService.go ├── etcd │ └── etcdInit.go ├── go.mod ├── go.sum ├── main.go ├── mapper │ └── favoriteMapper.go ├── model │ ├── favorite.go │ └── init.go ├── service │ ├── fav.pb.go │ ├── fav.pb.micro.go │ ├── from_user │ │ ├── to_favorite.pb.go │ │ └── to_favorite.pb.micro.go │ ├── frompublish │ │ ├── to_favorite.pb.go │ │ └── to_favorite.pb.micro.go │ ├── proto │ │ ├── fav.proto │ │ ├── to_video │ │ │ └── to_video.proto │ │ ├── token_utils.proto │ │ └── video_favorite.proto │ ├── to_video.pb.go │ ├── to_video.pb.micro.go │ ├── token_utils.pb.go │ └── token_utils.pb.micro.go └── utils │ ├── GetIdByToken.go │ ├── rabbitmq │ └── rabbitMQ.go │ └── redis │ └── redis.go ├── feed ├── conf │ ├── conf.go │ └── config.ini ├── core │ └── feedService.go ├── go.mod ├── main.go ├── model │ ├── init.go │ └── video.go ├── rpc_server │ ├── FavoriteRpc.go │ ├── TokenRpc.go │ ├── etcd │ │ └── etcdInit.go │ └── userRpc.go ├── services │ ├── favorite_to_video_proto │ │ ├── to_video.pb.go │ │ └── to_video.pb.micro.go │ ├── feed.pb.go │ ├── feed.pb.micro.go │ ├── protos │ │ └── feed.proto │ ├── to_relation │ │ ├── to_relation.pb.go │ │ └── to_relation.pb.micro.go │ ├── tokenproto │ │ ├── token_utils.pb.go │ │ └── token_utils.pb.micro.go │ └── userproto │ │ ├── user.pb.go │ │ └── user.pb.micro.go └── utils │ └── redis.go ├── message ├── conf │ ├── conf.go │ └── config.ini ├── core │ ├── MessageService.go │ └── to_relation │ │ └── ToRelationService.go ├── go.mod ├── main.go ├── model │ ├── init.go │ └── message.go ├── rpc_server │ ├── TokenRpc.go │ └── etcd │ │ └── etcdInit.go └── service │ ├── proto │ ├── message.proto │ └── to_relation │ │ └── to_relation.proto │ └── tokenproto │ ├── token_utils.pb.go │ └── token_utils.pb.micro.go ├── publish ├── conf │ ├── conf.go │ └── config.ini ├── core │ ├── publishService.go │ ├── to_comment │ │ └── toCommentService.go │ └── tofavorite │ │ └── toFavoriteService.go ├── go.mod ├── main.go ├── model │ ├── init.go │ └── video.go ├── rpc_server │ ├── FavoriteRpc.go │ ├── FavoriteRpc_test.go │ ├── TokenRpc.go │ ├── etcd │ │ └── etcdInit.go │ ├── userRpc.go │ └── userRpc_test.go ├── services │ ├── favorite_to_video_proto │ │ ├── to_video.pb.go │ │ └── to_video.pb.micro.go │ ├── from_user │ │ ├── to_publish.pb.go │ │ └── to_publish.pb.micro.go │ ├── protos │ │ ├── publish.proto │ │ ├── to_comment │ │ │ └── to_comment.proto │ │ └── to_favorite │ │ │ └── to_favorite.proto │ ├── publish.pb.go │ ├── publish.pb.micro.go │ ├── to_comment │ │ ├── to_comment.pb.go │ │ └── to_comment.pb.micro.go │ ├── to_favorite │ │ ├── to_favorite.pb.go │ │ └── to_favorite.pb.micro.go │ ├── to_relation │ │ ├── to_relation.pb.go │ │ └── to_relation.pb.micro.go │ ├── tokenproto │ │ ├── token_utils.pb.go │ │ └── token_utils.pb.micro.go │ └── userproto │ │ ├── user.pb.go │ │ └── user.pb.micro.go └── utils │ ├── ffmpeg.go │ ├── oss.go │ └── redis.go ├── relation ├── conf │ ├── conf.go │ └── config.ini ├── core │ └── RelationService.go ├── go.mod ├── go.sum ├── main.go ├── model │ ├── init.go │ └── relation.go ├── rpc_server │ ├── TokenRpc.go │ ├── etcd │ │ └── etcdInit.go │ ├── messageRpc.go │ └── userRpc.go └── service │ ├── from_message │ ├── to_relation.pb.go │ └── to_relation.pb.micro.go │ ├── proto │ └── relation.proto │ ├── relation.pb.go │ ├── relation.pb.micro.go │ ├── to_relation │ ├── to_relation.pb.go │ └── to_relation.pb.micro.go │ ├── tokenproto │ ├── token_utils.pb.go │ └── token_utils.pb.micro.go │ └── userproto │ ├── user.pb.go │ └── user.pb.micro.go ├── tokenutils ├── core │ └── tokenService.go ├── go.mod ├── go.sum ├── main.go └── service │ ├── peoto │ └── token_utils.proto │ ├── token_utils.pb.go │ └── token_utils.pb.micro.go └── user ├── conf ├── conf.go └── config.ini ├── core ├── to_favorite │ └── toFavoriteService.go ├── to_publish │ └── toPublishService.go ├── to_relation │ ├── toRelationService.go │ └── toRelationService_test.go └── userService.go ├── go.mod ├── main.go ├── model ├── init.go ├── relation.go └── user.go ├── rpc_server ├── TokenRpc.go └── etcd │ └── etcdInit.go ├── services ├── from_relation │ ├── to_user.pb.go │ └── to_user.pb.micro.go ├── protos │ ├── from_relation │ │ └── to_user.proto │ ├── to_favorite │ │ └── to_favorite.proto │ ├── to_publish │ │ └── to_publish.proto │ ├── to_relation │ │ └── to_relation.proto │ └── user.proto ├── to_favorite │ ├── to_favorite.pb.go │ └── to_favorite.pb.micro.go ├── to_relation │ ├── to_relation.pb.go │ └── to_relation.pb.micro.go ├── tokenproto │ ├── token_utils.pb.go │ └── token_utils.pb.micro.go ├── user.pb.go └── user.pb.micro.go └── utils ├── redis └── redis.go └── sha256 └── sha256.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | user/go.sum 17 | api-gateway/go.sum 18 | publish/go.sum 19 | feed/go.sum 20 | message/go.sum 21 | favorite/go.sum 22 | relation/go.sum 23 | tokenutils/go.sum 24 | comment/go.sum 25 | runtime/logs/log20230131.log 26 | .idea 27 | handlers/runtime -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 anapple929 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simple-douyin 2 | 3 | **简介:** gorm+gin+go-micro+mysql+redis 极简版抖音,实现了基础功能,互动功能和社交功能。侧重于互动功能。 4 | 5 | **队号:** 1122233 6 | 7 | **开发接口文档:** https://bytedance.feishu.cn/docs/doccnKrCsU5Iac6eftnFBdsXTof#6QCRJV 8 | 9 | **项目答辩文档:** https://dzs47lqpfu.feishu.cn/docx/Q48XdJaBxosEwSxCtWNc2pCLnQc 10 | 11 | **线上演示视频:** https://www.bilibili.com/video/BV16D4y1G7Ca/?vd_source=140298c09a850b3c5413933606102807 12 | 13 | **项目地址:** 43.138.51.56:4000 14 | 15 | --- 16 | ### 运行 17 | 1. `git clone https://github.com/anapple929/simple-douyin` 18 | 2. 进入每个微服务`go mod tidy`, 19 | 3. 将 `etcd` 运行起来 20 | 4. 运行每个微服务的`main.go` 21 | 5. `postman`或前端项目测试,网关端口:`4000` 22 | 23 | --- 24 | ### 微服务 25 | 26 | | 微服务 | 对网关暴露的接口 | 为其他微服务提供的接口 | 27 | |:--------:|:---------------------------------------|:------------| 28 | | **user** | 注册
登录
根据用户id查询用户信息 | 通过批量用户id查询批量user
修改关注数
修改粉丝数
修改发布数
修改获赞数
修改点赞数 | 29 | | **publish** | 视频发布
视频列表 | 通过批量视频id查询视频信息
修改点赞数
修改评论数 | 30 | | **feed** | 视频流 | | 31 | | **favorite** | 点赞
取消点赞
点赞列表 | 根据 用户id 和 视频id 判断是否有点赞关系
根据 用户id 视频id 点赞关系 构成的结构体,批量查询点赞关系
| 32 | | **comment** | 评论
删除评论
评论列表 | | 33 | | **relation** | 关注
取消关注
关注列表
粉丝列表
好友列表 | 根据 用户id 和 用户id 判断是否有关注关系
根据 用户id1 用户id2 关注关系 构成的结构体,批量查询关注关系 | 34 | | **message** | 聊天记录
发消息 | 根据用户id1和用户id2,查找二人聊天最新一条消息实体 | 35 | 36 | 37 | --- 38 | ### mysql 39 | 40 | | 表 | 拥有权限的微服务 | 41 | |:--------:|:------------:| 42 | | user | user | 43 | | comment | comment | 44 | | favorite | favorite | 45 | | relation | relation | 46 | | video | publish,feed | 47 | | message | message | 48 | 49 | --- 50 | ### redis 51 | 52 | 热点数据 53 | 54 | * db0: userid -> user 55 | * db1: videoid -> video 56 | * db2: userid+videoid -> bool 是否点赞 57 | 58 | --- 59 | ### 实现的接口 60 | 61 | 基础接口,互动接口,社交接口 62 | 63 | * /douyin/user/login/ 64 | * /douyin/user/register/ 65 | * /douyin/user/ 66 | 67 | 68 | * /douyin/publish/action/ 69 | * /douyin/publish/list/ 70 | * /douyin/feed/ 71 | 72 | 73 | * /douyin/favorite/action/ 74 | * /douyin/favorite/list/ 75 | 76 | 77 | * /douyin/comment/action/ 78 | * /douyin/comment/list/ 79 | 80 | 81 | * /douyin/relation/action/ 82 | * /douyin/relation/follow/list/ 83 | * /douyin/relation/follower/list/ 84 | * /douyin/relation/friend/list/ 85 | 86 | 87 | * /douyin/message/chat/ 88 | * /douyin/message/action/ 89 | 90 | -------------------------------------------------------------------------------- /api-gateway/go.mod: -------------------------------------------------------------------------------- 1 | module api-gateway 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 7 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 8 | github.com/gin-gonic/gin v1.8.2 9 | github.com/golang/protobuf v1.5.0 10 | github.com/micro/go-micro/v2 v2.9.1 11 | google.golang.org/protobuf v1.28.1 12 | ) 13 | 14 | require ( 15 | github.com/BurntSushi/toml v0.3.1 // indirect 16 | github.com/bitly/go-simplejson v0.5.0 // indirect 17 | github.com/coreos/etcd v3.3.18+incompatible // indirect 18 | github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect 19 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect 20 | github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect 21 | github.com/emirpasic/gods v1.12.0 // indirect 22 | github.com/fsnotify/fsnotify v1.4.7 // indirect 23 | github.com/ghodss/yaml v1.0.0 // indirect 24 | github.com/gin-contrib/sse v0.1.0 // indirect 25 | github.com/go-git/gcfg v1.5.0 // indirect 26 | github.com/go-git/go-billy/v5 v5.0.0 // indirect 27 | github.com/go-git/go-git/v5 v5.1.0 // indirect 28 | github.com/go-playground/locales v0.14.0 // indirect 29 | github.com/go-playground/universal-translator v0.18.0 // indirect 30 | github.com/go-playground/validator/v10 v10.11.1 // indirect 31 | github.com/goccy/go-json v0.9.11 // indirect 32 | github.com/gogo/protobuf v1.2.1 // indirect 33 | github.com/google/uuid v1.1.1 // indirect 34 | github.com/hashicorp/hcl v1.0.0 // indirect 35 | github.com/hpcloud/tail v1.0.0 // indirect 36 | github.com/imdario/mergo v0.3.9 // indirect 37 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 38 | github.com/json-iterator/go v1.1.12 // indirect 39 | github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect 40 | github.com/leodido/go-urn v1.2.1 // indirect 41 | github.com/mattn/go-isatty v0.0.16 // indirect 42 | github.com/micro/cli/v2 v2.1.2 // indirect 43 | github.com/miekg/dns v1.1.27 // indirect 44 | github.com/mitchellh/go-homedir v1.1.0 // indirect 45 | github.com/mitchellh/hashstructure v1.0.0 // indirect 46 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 47 | github.com/modern-go/reflect2 v1.0.2 // indirect 48 | github.com/nats-io/jwt v0.3.2 // indirect 49 | github.com/nats-io/nats.go v1.9.2 // indirect 50 | github.com/nats-io/nkeys v0.1.4 // indirect 51 | github.com/nats-io/nuid v1.0.1 // indirect 52 | github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect 53 | github.com/patrickmn/go-cache v2.1.0+incompatible // indirect 54 | github.com/pelletier/go-toml/v2 v2.0.6 // indirect 55 | github.com/pkg/errors v0.9.1 // indirect 56 | github.com/russross/blackfriday/v2 v2.0.1 // indirect 57 | github.com/sergi/go-diff v1.1.0 // indirect 58 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect 59 | github.com/ugorji/go/codec v1.2.7 // indirect 60 | github.com/xanzy/ssh-agent v0.2.1 // indirect 61 | go.uber.org/atomic v1.5.0 // indirect 62 | go.uber.org/multierr v1.3.0 // indirect 63 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect 64 | go.uber.org/zap v1.13.0 // indirect 65 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect 66 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect 67 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect 68 | golang.org/x/net v0.4.0 // indirect 69 | golang.org/x/sys v0.3.0 // indirect 70 | golang.org/x/text v0.5.0 // indirect 71 | golang.org/x/tools v0.1.12 // indirect 72 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1 // indirect 73 | google.golang.org/grpc v1.26.0 // indirect 74 | gopkg.in/fsnotify.v1 v1.4.7 // indirect 75 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 76 | gopkg.in/warnings.v0 v0.1.2 // indirect 77 | gopkg.in/yaml.v2 v2.4.0 // indirect 78 | honnef.co/go/tools v0.0.1-2019.2.3 // indirect 79 | ) 80 | 81 | replace github.com/golang/protobuf => github.com/golang/protobuf v1.4.3 82 | 83 | replace google.golang.org/protobuf => google.golang.org/protobuf v1.22.0 84 | -------------------------------------------------------------------------------- /api-gateway/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "api-gateway/services/comment" 5 | "api-gateway/services/fav" 6 | "api-gateway/services/feed" 7 | message "api-gateway/services/message" 8 | "api-gateway/services/publish" 9 | "api-gateway/services/relation" 10 | "api-gateway/services/user" 11 | "api-gateway/weblib" 12 | "api-gateway/wrappers" 13 | "github.com/micro/go-micro/v2" 14 | "github.com/micro/go-micro/v2/registry" 15 | "github.com/micro/go-micro/v2/registry/etcd" 16 | "github.com/micro/go-micro/v2/web" 17 | 18 | "time" 19 | ) 20 | 21 | func main() { 22 | etcdReg := etcd.NewRegistry( 23 | registry.Addrs("127.0.0.1:2379"), 24 | ) 25 | // 用户 26 | userMicroService := micro.NewService( 27 | micro.Name("userService.client"), 28 | micro.WrapClient(wrappers.NewUserWrapper), 29 | ) 30 | // 用户服务调用实例 31 | userService := user.NewUserService("rpcUserService", userMicroService.Client()) 32 | 33 | // publish 34 | publishMicroService := micro.NewService( 35 | micro.Name("publishService.client"), 36 | micro.WrapClient(wrappers.NewPublishWrapper), 37 | ) 38 | // publish服务调用实例 39 | publishService := publish.NewPublishService("rpcPublishService", publishMicroService.Client()) 40 | //点赞 41 | favoriteMicroService := micro.NewService( 42 | micro.Name("favoriteMicroService.client"), 43 | micro.WrapClient(wrappers.NewFavoriteWrapper), 44 | ) 45 | //点赞服务实例 46 | favoriteService := fav.NewFavoriteService("rpcFavoriteService", favoriteMicroService.Client()) 47 | // feed视频流 48 | feedMicroService := micro.NewService( 49 | micro.Name("feedService.client"), 50 | micro.WrapClient(wrappers.NewFeedWrapper), 51 | ) 52 | // 视频流服务调用实例 53 | feedService := feed.NewFeedService("rpcFeedService", feedMicroService.Client()) 54 | 55 | // comment 56 | commentMicroService := micro.NewService( 57 | micro.Name("commentService.client"), 58 | micro.WrapClient(wrappers.NewCommentWrapper), 59 | ) 60 | // comment 61 | commentService := comment.NewCommentService("rpcCommentService", commentMicroService.Client()) 62 | 63 | // relation 64 | relationMicroService := micro.NewService( 65 | micro.Name("relationService.client"), 66 | micro.WrapClient(wrappers.NewRelationWrapper), 67 | ) 68 | // relation 69 | relationService := relation.NewRelationService("rpcRelationService", relationMicroService.Client()) 70 | 71 | //message 72 | messageMicroService := micro.NewService( 73 | micro.Name("messageService.client"), 74 | micro.WrapClient(wrappers.NewMessageWrapper), 75 | ) 76 | //message 77 | messageService := message.NewMessageService("rpcMessageService", messageMicroService.Client()) 78 | 79 | serviceMap := make(map[string]interface{}) 80 | serviceMap["userService"] = userService 81 | serviceMap["publishService"] = publishService 82 | serviceMap["feedService"] = feedService 83 | serviceMap["favoriteService"] = favoriteService 84 | serviceMap["commentService"] = commentService 85 | serviceMap["relationService"] = relationService 86 | serviceMap["messageService"] = messageService 87 | 88 | //创建微服务实例,使用gin暴露http接口并注册到etcd 89 | server := web.NewService( 90 | web.Name("httpService"), 91 | web.Address("127.0.0.1:4000"), 92 | //将服务调用实例使用gin处理 93 | web.Handler(weblib.NewRouter(serviceMap)), 94 | web.Registry(etcdReg), 95 | web.RegisterTTL(time.Second*300), 96 | web.RegisterInterval(time.Second*150), 97 | web.Metadata(map[string]string{"protocol": "http"}), 98 | ) 99 | //接收命令行参数 100 | _ = server.Init() 101 | _ = server.Run() 102 | } 103 | -------------------------------------------------------------------------------- /api-gateway/pkg/logging/file.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "time" 8 | ) 9 | 10 | var ( 11 | LogSavePath = "runtime/logs/" 12 | LogSaveName = "log" 13 | LogFileExt = "log" 14 | TimeFormat = "20060102" 15 | ) 16 | 17 | func getLogFilePath() string { 18 | return fmt.Sprintf("%s", LogSavePath) 19 | } 20 | 21 | func getLogFileFullPath() string { 22 | prefixPath := getLogFilePath() 23 | suffixPath := fmt.Sprintf("%s%s.%s", LogSaveName, time.Now().Format(TimeFormat), LogFileExt) 24 | 25 | return fmt.Sprintf("%s%s", prefixPath, suffixPath) 26 | } 27 | 28 | func openLogFile(filePath string) *os.File { 29 | _, err := os.Stat(filePath) 30 | switch { 31 | case os.IsNotExist(err): 32 | mkDir() 33 | case os.IsPermission(err): 34 | log.Fatalf("Permission :%v", err) 35 | } 36 | 37 | handle, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 38 | if err != nil { 39 | log.Fatalf("Fail to OpenFile :%v", err) 40 | } 41 | 42 | return handle 43 | } 44 | 45 | func mkDir() { 46 | dir, _ := os.Getwd() 47 | err := os.MkdirAll(dir+"/"+getLogFilePath(), os.ModePerm) 48 | if err != nil { 49 | panic(err) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /api-gateway/pkg/logging/log.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "path/filepath" 8 | "runtime" 9 | ) 10 | 11 | type Level int 12 | 13 | var ( 14 | F *os.File 15 | 16 | DefaultPrefix = "" 17 | DefaultCallerDepth = 2 18 | 19 | logger *log.Logger 20 | logPrefix = "" 21 | levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"} 22 | ) 23 | 24 | const ( 25 | DEBUG Level = iota 26 | INFO 27 | WARNING 28 | ERROR 29 | FATAL 30 | ) 31 | 32 | func init() { 33 | filePath := getLogFileFullPath() 34 | F = openLogFile(filePath) 35 | 36 | logger = log.New(F, DefaultPrefix, log.LstdFlags) 37 | } 38 | 39 | func Debug(v ...interface{}) { 40 | setPrefix(DEBUG) 41 | logger.Println(v...) 42 | } 43 | 44 | func Info(v ...interface{}) { 45 | setPrefix(INFO) 46 | logger.Println(v...) 47 | } 48 | 49 | func Warn(v ...interface{}) { 50 | setPrefix(WARNING) 51 | logger.Println(v...) 52 | } 53 | 54 | func Error(v ...interface{}) { 55 | setPrefix(ERROR) 56 | logger.Println(v...) 57 | } 58 | 59 | func Fatal(v ...interface{}) { 60 | setPrefix(FATAL) 61 | logger.Fatalln(v...) 62 | } 63 | 64 | func setPrefix(level Level) { 65 | _, file, line, ok := runtime.Caller(DefaultCallerDepth) 66 | if ok { 67 | logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line) 68 | } else { 69 | logPrefix = fmt.Sprintf("[%s]", levelFlags[level]) 70 | } 71 | 72 | logger.SetPrefix(logPrefix) 73 | } 74 | -------------------------------------------------------------------------------- /api-gateway/pkg/utils/jwt.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/dgrijalva/jwt-go" 5 | "time" 6 | ) 7 | 8 | var jwtSecret = []byte("1122233") 9 | 10 | type Claims struct { 11 | Id int64 `json:"id"` 12 | jwt.StandardClaims 13 | } 14 | 15 | // 签发用户token 16 | func GenerateToken(id int64) (string, error) { 17 | nowTime := time.Now() 18 | expireTime := nowTime.Add(2 * time.Hour) 19 | claims := Claims{ 20 | Id: id, 21 | StandardClaims: jwt.StandardClaims{ 22 | ExpiresAt: expireTime.Unix(), 23 | Issuer: "1122233", 24 | }, 25 | } 26 | tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 27 | token, err := tokenClaims.SignedString(jwtSecret) 28 | return token, err 29 | } 30 | 31 | // 验证用户token 32 | func ParseToken(token string) (*Claims, error) { 33 | tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (i interface{}, e error) { return jwtSecret, nil }) 34 | if tokenClaims != nil { 35 | if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { 36 | 37 | return claims, nil 38 | } 39 | } 40 | return nil, err 41 | } 42 | -------------------------------------------------------------------------------- /api-gateway/runtime/logs/log20230213.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anapple929/simple-douyin/4dfbc2e94f84548fbb6f5602fb3a70cd2b811d74/api-gateway/runtime/logs/log20230213.log -------------------------------------------------------------------------------- /api-gateway/services/feed/feed.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: feed.proto 3 | 4 | package feed 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for FeedService service 37 | 38 | func NewFeedServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for FeedService service 43 | 44 | type FeedService interface { 45 | Feed(ctx context.Context, in *DouyinFeedRequest, opts ...client.CallOption) (*DouyinFeedResponse, error) 46 | } 47 | 48 | type feedService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewFeedService(name string, c client.Client) FeedService { 54 | return &feedService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *feedService) Feed(ctx context.Context, in *DouyinFeedRequest, opts ...client.CallOption) (*DouyinFeedResponse, error) { 61 | req := c.c.NewRequest(c.name, "FeedService.Feed", in) 62 | out := new(DouyinFeedResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for FeedService service 71 | 72 | type FeedServiceHandler interface { 73 | Feed(context.Context, *DouyinFeedRequest, *DouyinFeedResponse) error 74 | } 75 | 76 | func RegisterFeedServiceHandler(s server.Server, hdlr FeedServiceHandler, opts ...server.HandlerOption) error { 77 | type feedService interface { 78 | Feed(ctx context.Context, in *DouyinFeedRequest, out *DouyinFeedResponse) error 79 | } 80 | type FeedService struct { 81 | feedService 82 | } 83 | h := &feedServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&FeedService{h}, opts...)) 85 | } 86 | 87 | type feedServiceHandler struct { 88 | FeedServiceHandler 89 | } 90 | 91 | func (h *feedServiceHandler) Feed(ctx context.Context, in *DouyinFeedRequest, out *DouyinFeedResponse) error { 92 | return h.FeedServiceHandler.Feed(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /api-gateway/services/proto/fav.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message douyin_favorite_action_request { 6 | string token = 1; // 用户鉴权token 7 | int64 video_id = 2; // 视频id 8 | int32 action_type = 3; // 1-点赞,2-取消点赞 9 | } 10 | 11 | message douyin_favorite_action_response { 12 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 13 | string status_msg = 2; // 返回状态描述 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | message douyin_favorite_list_request { 22 | int64 user_id = 1; // 用户id 23 | string token = 2; // 用户鉴权token 24 | } 25 | 26 | message douyin_favorite_list_response { 27 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 28 | string status_msg = 2; // 返回状态描述 29 | repeated Video video_list = 3; // 用户点赞视频列表 30 | } 31 | 32 | message Video { 33 | int64 id = 1; // 视频唯一标识 34 | User author = 2; // 视频作者信息 35 | string play_url = 3; // 视频播放地址 36 | string cover_url = 4; // 视频封面地址 37 | int64 favorite_count = 5; // 视频的点赞总数 38 | int64 comment_count = 6; // 视频的评论总数 39 | bool is_favorite = 7; // true-已点赞,false-未点赞 40 | string title = 8; // 视频标题 41 | } 42 | 43 | message User { 44 | int64 id = 1; // 用户id 45 | string name = 2; // 用户名称 46 | int64 follow_count = 3; // 关注总数 47 | int64 follower_count = 4; // 粉丝总数 48 | bool is_follow = 5; // true-已关注,false-未关注 49 | } 50 | service FavoriteService{ 51 | rpc FavoriteAction(douyin_favorite_action_request) returns (douyin_favorite_action_response); 52 | rpc FavoriteList(douyin_favorite_list_request) returns(douyin_favorite_list_response); 53 | 54 | } -------------------------------------------------------------------------------- /api-gateway/services/proto/publish.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../publish;publish"; 4 | 5 | message DouyinPublishListRequest { 6 | // @gotags: json:"user_id" 7 | int64 UserId = 1; // 用户id 8 | // @gotags: json:"token" 9 | string Token = 2; // 用户鉴权token 10 | } 11 | 12 | message DouyinPublishListResponse { 13 | // @gotags: json:"status_code" 14 | int32 StatusCode = 1; // 状态码,0-成功,其他值-失败 15 | // @gotags: json:"status_msg" 16 | string StatusMsg = 2; // 返回状态描述 17 | // @gotags: json:"video_list" 18 | repeated Video VideoList = 3; // 用户发布的视频列表 19 | } 20 | 21 | message Video { 22 | // @gotags: json:"id" 23 | int64 Id = 1; // 视频唯一标识 24 | // @gotags: json:"author" 25 | User Author = 2; // 视频作者信息 26 | // @gotags: json:"play_url" 27 | string PlayUrl = 3; // 视频播放地址 28 | // @gotags: json:"cover_url" 29 | string CoverUrl = 4; // 视频封面地址 30 | // @gotags: json:"favorite_count" 31 | int64 FavoriteCount = 5; // 视频的点赞总数 32 | // @gotags: json:"comment_count" 33 | int64 CommentCount = 6; // 视频的评论总数 34 | // @gotags: json:"is_favorite" 35 | bool IsFavorite = 7; // true-已点赞,false-未点赞 36 | // @gotags: json:"title" 37 | string Title = 8; // 视频标题 38 | } 39 | 40 | message User { 41 | // @gotags: json:"id" 42 | int64 Id = 1; // 用户id 43 | // @gotags: json:"name" 44 | string Name = 2; // 用户名称 45 | // @gotags: json:"follow_count" 46 | int64 FollowCount = 3; // 关注总数 47 | // @gotags: json:"follower_count" 48 | int64 FollowerCount = 4; // 粉丝总数 49 | // @gotags: json:"is_follow" 50 | bool IsFollow = 5; // true-已关注,false-未关注 51 | } 52 | 53 | message DouyinPublishActionRequest { 54 | // @gotags: json:"token" 55 | string Token = 1; // 用户鉴权token 56 | // @gotags: json:"data" 57 | bytes Data = 2; // 视频数据 58 | // @gotags: json:"title" 59 | string Title = 3; // 视频标题 60 | } 61 | 62 | message DouyinPublishActionResponse { 63 | // @gotags: json:"status_code" 64 | int32 StatusCode = 1; // 状态码,0-成功,其他值-失败 65 | // @gotags: json:"status_msg" 66 | string StatusMsg = 2; // 返回状态描述 67 | } 68 | 69 | 70 | 71 | service PublishService{ 72 | rpc PublishList(DouyinPublishListRequest) returns (DouyinPublishListResponse); 73 | rpc Publish(DouyinPublishActionRequest) returns(DouyinPublishActionResponse); 74 | } 75 | -------------------------------------------------------------------------------- /api-gateway/services/proto/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../user;user"; 4 | 5 | message DouyinUserRegisterRequest { 6 | // @gotags: json:"username" 7 | string Username = 1; //注册用户名,最长32个字符 8 | // @gotags: json:"password" 9 | string Password = 2; //密码,最长32个字符 10 | } 11 | 12 | message DouyinUserRegisterResponse { 13 | // @gotags: json:"status_code" 14 | int32 StatusCode = 1; //状态码 0-成功 其他值-失败 15 | // @gotags: json:"status_msg" 16 | string StatusMsg = 2; //返回状态描述 17 | // @gotags: json:"user_id" 18 | int64 UserId = 3; //用户id 19 | // @gotags: json:"token" 20 | string Token = 4; //用户鉴权token 21 | } 22 | 23 | message DouyinUserLoginRequest { 24 | // @gotags: json:"username" 25 | string Username = 1; //注册用户名,最长32个字符 26 | // @gotags: json:"password" 27 | string Password = 2; //密码,最长32个字符 28 | } 29 | 30 | message DouyinUserLoginResponse { 31 | // @gotags: json:"status_code" 32 | int32 StatusCode = 1; //状态码 0-成功 其他值-失败 33 | // @gotags: json:"status_msg" 34 | string StatusMsg = 2; //返回状态描述 35 | // @gotags: json:"user_id" 36 | int64 UserId = 3; //用户id 37 | // @gotags: json:"token" 38 | string Token = 4; //用户鉴权token 39 | } 40 | 41 | message User { 42 | // @gotags: json:"id" 43 | int64 Id = 1; //用户id 44 | // @gotags: json:"name" 45 | string Name = 2; //用户名称 46 | // @gotags: json:"follow_count" 47 | int64 FollowCount = 3; //关注总数 48 | // @gotags: json:"follower_count" 49 | int64 FollowerCount = 4; //粉丝总数 50 | // @gotags: json:"is_follow" 51 | bool IsFollow = 5; //true-已关注,false-未关注 52 | } 53 | 54 | message DouyinUserRequest { 55 | // @gotags: json:"user_id" 56 | int64 UserId = 1; //用户id 57 | // @gotags: json:"token" 58 | string Token = 2; //用户鉴权token 59 | } 60 | 61 | message DouyinUserResponse { 62 | // @gotags: json:"status_code" 63 | int32 StatusCode = 1; //状态码 0-成功,其他值-失败 64 | // @gotags: json:"status_msg" 65 | string StatusMsg = 2; //返回状态描述 66 | // @gotags: json:"user" 67 | User User = 3; //用户信息 68 | } 69 | 70 | service UserService{ 71 | rpc Login(DouyinUserLoginRequest) returns (DouyinUserLoginResponse); 72 | rpc Register(DouyinUserRegisterRequest) returns(DouyinUserRegisterResponse); 73 | rpc UserInfo(DouyinUserRequest) returns(DouyinUserResponse); 74 | } 75 | -------------------------------------------------------------------------------- /api-gateway/services/publish/publish.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: publish.proto 3 | 4 | package publish 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for PublishService service 37 | 38 | func NewPublishServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for PublishService service 43 | 44 | type PublishService interface { 45 | PublishList(ctx context.Context, in *DouyinPublishListRequest, opts ...client.CallOption) (*DouyinPublishListResponse, error) 46 | Publish(ctx context.Context, in *DouyinPublishActionRequest, opts ...client.CallOption) (*DouyinPublishActionResponse, error) 47 | } 48 | 49 | type publishService struct { 50 | c client.Client 51 | name string 52 | } 53 | 54 | func NewPublishService(name string, c client.Client) PublishService { 55 | return &publishService{ 56 | c: c, 57 | name: name, 58 | } 59 | } 60 | 61 | func (c *publishService) PublishList(ctx context.Context, in *DouyinPublishListRequest, opts ...client.CallOption) (*DouyinPublishListResponse, error) { 62 | req := c.c.NewRequest(c.name, "PublishService.PublishList", in) 63 | out := new(DouyinPublishListResponse) 64 | err := c.c.Call(ctx, req, out, opts...) 65 | if err != nil { 66 | return nil, err 67 | } 68 | return out, nil 69 | } 70 | 71 | func (c *publishService) Publish(ctx context.Context, in *DouyinPublishActionRequest, opts ...client.CallOption) (*DouyinPublishActionResponse, error) { 72 | req := c.c.NewRequest(c.name, "PublishService.Publish", in) 73 | out := new(DouyinPublishActionResponse) 74 | err := c.c.Call(ctx, req, out, opts...) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return out, nil 79 | } 80 | 81 | // Server API for PublishService service 82 | 83 | type PublishServiceHandler interface { 84 | PublishList(context.Context, *DouyinPublishListRequest, *DouyinPublishListResponse) error 85 | Publish(context.Context, *DouyinPublishActionRequest, *DouyinPublishActionResponse) error 86 | } 87 | 88 | func RegisterPublishServiceHandler(s server.Server, hdlr PublishServiceHandler, opts ...server.HandlerOption) error { 89 | type publishService interface { 90 | PublishList(ctx context.Context, in *DouyinPublishListRequest, out *DouyinPublishListResponse) error 91 | Publish(ctx context.Context, in *DouyinPublishActionRequest, out *DouyinPublishActionResponse) error 92 | } 93 | type PublishService struct { 94 | publishService 95 | } 96 | h := &publishServiceHandler{hdlr} 97 | return s.Handle(s.NewHandler(&PublishService{h}, opts...)) 98 | } 99 | 100 | type publishServiceHandler struct { 101 | PublishServiceHandler 102 | } 103 | 104 | func (h *publishServiceHandler) PublishList(ctx context.Context, in *DouyinPublishListRequest, out *DouyinPublishListResponse) error { 105 | return h.PublishServiceHandler.PublishList(ctx, in, out) 106 | } 107 | 108 | func (h *publishServiceHandler) Publish(ctx context.Context, in *DouyinPublishActionRequest, out *DouyinPublishActionResponse) error { 109 | return h.PublishServiceHandler.Publish(ctx, in, out) 110 | } 111 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/comment.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/services/comment" 5 | "context" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | "strconv" 9 | ) 10 | 11 | func CommentAction(ginCtx *gin.Context) { 12 | var commentReq comment.DouyinCommentActionRequest 13 | //获取request的信息 14 | commentReq.CommentId, _ = strconv.ParseInt(ginCtx.Query("comment_id"), 10, 64) 15 | commentReq.CommentText = ginCtx.Query("comment_text") 16 | actionType, _ := strconv.Atoi(ginCtx.Query("action_type")) 17 | commentReq.ActionType = int32(actionType) 18 | commentReq.Token = ginCtx.Query("token") 19 | commentReq.VideoId, _ = strconv.ParseInt(ginCtx.Query("video_id"), 10, 64) 20 | //if actionType != 1 && actionType != 2 { 21 | // ginCtx.JSON(http.StatusOK, comment.DouyinCommentActionResponse{ 22 | // StatusCode: -1, 23 | // StatusMsg: "action_type有问题", 24 | // }) 25 | //} 26 | //if commentReq.CommentText == "" { 27 | // ginCtx.JSON(http.StatusOK, comment.DouyinCommentActionResponse{ 28 | // StatusCode: -1, 29 | // StatusMsg: "comment_text有问题", 30 | // }) 31 | //} 32 | //if commentReq.VideoId <= 0 { 33 | // ginCtx.JSON(http.StatusOK, comment.DouyinCommentActionResponse{ 34 | // StatusCode: -1, 35 | // StatusMsg: "video_id有问题", 36 | // }) 37 | //} 38 | //if commentReq.ActionType == 2 && commentReq.CommentId <= 0 { 39 | // ginCtx.JSON(http.StatusOK, comment.DouyinCommentActionResponse{ 40 | // StatusCode: -1, 41 | // StatusMsg: "删除评论必须携带正确的id", 42 | // }) 43 | //} 44 | 45 | // 从gin.Key中取出服务实例 46 | commentService := ginCtx.Keys["commentService"].(comment.CommentService) 47 | //调用comment微服务,将context的上下文传入 48 | commentResp, _ := commentService.CommentAction(context.Background(), &commentReq) 49 | 50 | //返回 51 | ginCtx.JSON(http.StatusOK, comment.DouyinCommentActionResponse{ 52 | StatusCode: commentResp.StatusCode, 53 | StatusMsg: commentResp.StatusMsg, 54 | Comment: commentResp.Comment, 55 | }) 56 | 57 | } 58 | func CommentList(ginCtx *gin.Context) { 59 | var commentReq comment.DouyinCommentListRequest 60 | 61 | commentReq.Token = ginCtx.Query("token") 62 | commentReq.VideoId, _ = strconv.ParseInt(ginCtx.Query("video_id"), 10, 64) 63 | 64 | //if commentReq.VideoId <= 0 { 65 | // ginCtx.JSON(http.StatusOK, comment.DouyinCommentListResponse{ 66 | // StatusCode: -1, 67 | // StatusMsg: "video_id有问题", 68 | // }) 69 | //} 70 | 71 | commentService := ginCtx.Keys["commentService"].(comment.CommentService) 72 | commentResp, _ := commentService.CommentList(context.Background(), &commentReq) 73 | 74 | ginCtx.JSON(http.StatusOK, comment.DouyinCommentListResponse{ 75 | StatusCode: commentResp.StatusCode, 76 | StatusMsg: commentResp.StatusMsg, 77 | CommentList: commentResp.CommentList, 78 | }) 79 | 80 | } 81 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/errors.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/pkg/logging" 5 | "errors" 6 | ) 7 | 8 | // user包装错误 9 | func PanicIfUserError(err error) { 10 | if err != nil { 11 | err = errors.New("userService--" + err.Error()) 12 | logging.Info(err) 13 | panic(err) 14 | } 15 | } 16 | 17 | // feed包装错误 18 | func PanicIfFeedError(err error) { 19 | if err != nil { 20 | err = errors.New("feedService--" + err.Error()) 21 | logging.Info(err) 22 | panic(err) 23 | } 24 | } 25 | 26 | // publish包装错误 27 | func PanicIfPublishError(err error) { 28 | if err != nil { 29 | err = errors.New("publishService--" + err.Error()) 30 | logging.Info(err) 31 | panic(err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/favorite.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/services/fav" 5 | "github.com/gin-gonic/gin" 6 | "net/http" 7 | 8 | "strconv" 9 | ) 10 | 11 | func FavoriteAction(ginCtx *gin.Context) { 12 | actionType, _ := strconv.Atoi(ginCtx.Query("action_type")) 13 | token := ginCtx.Query("token") 14 | vid, _ := strconv.ParseInt(ginCtx.Query("video_id"), 10, 64) 15 | 16 | //if token == "" { 17 | // ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteActionResponse{ 18 | // StatusCode: -1, 19 | // StatusMsg: "登录失效,重新登录", 20 | // }) 21 | //} 22 | //if vid <= 0 { 23 | // ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteActionResponse{ 24 | // StatusCode: -1, 25 | // StatusMsg: "视频id有问题", 26 | // }) 27 | //} 28 | //if actionType != 1 && actionType != 2 { 29 | // ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteActionResponse{ 30 | // StatusCode: -1, 31 | // StatusMsg: "actionType有问题", 32 | // }) 33 | //} 34 | 35 | favService := ginCtx.Keys["favoriteService"].(fav.FavoriteService) 36 | var req fav.DouyinFavoriteActionRequest 37 | req.ActionType = int32(actionType) 38 | req.Token = token 39 | req.VideoId = vid 40 | action, _ := favService.FavoriteAction(ginCtx, &req) 41 | 42 | ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteActionResponse{ 43 | StatusCode: action.StatusCode, 44 | StatusMsg: action.StatusMsg, 45 | }) 46 | 47 | } 48 | func FavoriteList(ginCtx *gin.Context) { 49 | 50 | token := ginCtx.Query("token") 51 | 52 | uid, _ := strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 53 | 54 | favService := ginCtx.Keys["favoriteService"].(fav.FavoriteService) 55 | 56 | var req fav.DouyinFavoriteListRequest 57 | 58 | req.Token = token 59 | req.UserId = uid 60 | action, _ := favService.FavoriteList(ginCtx, &req) 61 | 62 | //if token == "" { 63 | // ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteListResponse{ 64 | // StatusCode: -1, 65 | // StatusMsg: "登录失效,重新登录", 66 | // }) 67 | // return 68 | //} 69 | //if uid <= 0 { 70 | // ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteListResponse{ 71 | // StatusCode: -1, 72 | // StatusMsg: "被查询的user_id有问题", 73 | // }) 74 | // return 75 | //} 76 | ginCtx.JSON(http.StatusOK, fav.DouyinFavoriteListResponse{ 77 | StatusCode: action.StatusCode, 78 | StatusMsg: action.StatusMsg, 79 | VideoList: action.VideoList, 80 | }) 81 | 82 | } 83 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/feed.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/services/feed" 5 | "context" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | "strconv" 9 | "time" 10 | ) 11 | 12 | //视频流 13 | func Feed(ginCtx *gin.Context) { 14 | //数据绑定 15 | var feedReq feed.DouyinFeedRequest 16 | lastTime, err := strconv.ParseInt(ginCtx.Query("latest_time"), 10, 64) 17 | PanicIfFeedError(err) 18 | feedReq.LatestTime = lastTime 19 | feedReq.Token = ginCtx.Query("token") 20 | 21 | //设置最长响应时长 22 | ctx, _ := context.WithTimeout(ginCtx, time.Minute*1) 23 | 24 | // 从gin.Key中取出服务实例 25 | feedService := ginCtx.Keys["feedService"].(feed.FeedService) 26 | // 调用 27 | feedResp, err := feedService.Feed(ctx, &feedReq) 28 | PanicIfFeedError(err) 29 | //返回 30 | ginCtx.JSON(http.StatusOK, feed.DouyinFeedResponse{ 31 | StatusCode: feedResp.StatusCode, 32 | StatusMsg: feedResp.StatusMsg, 33 | VideoList: feedResp.VideoList, 34 | NextTime: time.Now().Unix(), 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/message.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | message "api-gateway/services/message" 5 | "context" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | "strconv" 9 | ) 10 | 11 | /** 12 | 聊天记录 13 | */ 14 | func MessageList(ginCtx *gin.Context) { 15 | var messageReq message.DouyinMessageChatRequest 16 | 17 | messageReq.Token = ginCtx.Query("token") 18 | messageReq.ToUserId, _ = strconv.ParseInt(ginCtx.Query("to_user_id"), 10, 64) 19 | messageReq.PreMsgTime, _ = strconv.ParseInt(ginCtx.Query("pre_msg_time"), 10, 64) 20 | //if messageReq.ToUserId <= 0 { 21 | // ginCtx.JSON(http.StatusOK, message.DouyinMessageChatResponse{ 22 | // StatusCode: -1, 23 | // StatusMsg: "to_user_id有问题", 24 | // }) 25 | //} 26 | messageService := ginCtx.Keys["messageService"].(message.MessageService) 27 | resp, _ := messageService.MessageList(context.Background(), &messageReq) 28 | //for _, message := range resp.MessageList { 29 | // fmt.Println(message) 30 | //} 31 | ginCtx.JSON(http.StatusOK, message.DouyinMessageChatResponse{ 32 | StatusCode: resp.StatusCode, 33 | StatusMsg: resp.StatusMsg, 34 | MessageList: resp.MessageList, 35 | }) 36 | } 37 | 38 | /** 39 | 发送消息 40 | */ 41 | func MessageAction(ginCtx *gin.Context) { 42 | var messageReq message.DouyinMessageActionRequest 43 | 44 | messageReq.Token = ginCtx.Query("token") 45 | messageReq.ToUserId, _ = strconv.ParseInt(ginCtx.Query("to_user_id"), 10, 64) 46 | actionType, _ := strconv.Atoi(ginCtx.Query("action_type")) 47 | messageReq.ActionType = int32(actionType) 48 | messageReq.Content = ginCtx.Query("content") 49 | 50 | messageService := ginCtx.Keys["messageService"].(message.MessageService) 51 | resp, _ := messageService.MessageAction(context.Background(), &messageReq) 52 | 53 | ginCtx.JSON(http.StatusOK, message.DouyinMessageActionResponse{ 54 | StatusCode: resp.StatusCode, 55 | StatusMsg: resp.StatusMsg, 56 | }) 57 | } 58 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/publish.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/services/publish" 5 | "bytes" 6 | "context" 7 | "github.com/gin-gonic/gin" 8 | "io" 9 | "net/http" 10 | "strconv" 11 | "time" 12 | ) 13 | 14 | //上传视频 15 | func Publish(ginCtx *gin.Context) { 16 | var publishReq publish.DouyinPublishActionRequest 17 | 18 | publishReq.Title = ginCtx.PostForm("title") 19 | publishReq.Token = ginCtx.PostForm("token") 20 | fileHeader, _ := ginCtx.FormFile("data") 21 | 22 | //if publishReq.Title == "" { 23 | // ginCtx.JSON(http.StatusOK, publish.DouyinPublishActionResponse{ 24 | // StatusCode: -1, 25 | // StatusMsg: "题目不能为空", 26 | // }) 27 | //} 28 | //if publishReq.Token == "" { 29 | // ginCtx.JSON(http.StatusOK, publish.DouyinPublishActionResponse{ 30 | // StatusCode: -1, 31 | // StatusMsg: "登录失效,重新登录", 32 | // }) 33 | //} 34 | //if fileHeader == nil { 35 | // ginCtx.JSON(http.StatusOK, publish.DouyinPublishActionResponse{ 36 | // StatusCode: -1, 37 | // StatusMsg: "文件不能为空", 38 | // }) 39 | //} 40 | 41 | file, err := fileHeader.Open() 42 | if err != nil { 43 | PanicIfPublishError(err) 44 | return 45 | } 46 | defer file.Close() 47 | 48 | buf := bytes.NewBuffer(nil) 49 | if _, err = io.Copy(buf, file); err != nil { 50 | PanicIfPublishError(err) 51 | return 52 | } 53 | 54 | publishReq.Data = buf.Bytes() 55 | 56 | ctx, _ := context.WithTimeout(ginCtx, time.Minute*1) 57 | // 从gin.Key中取出服务实例 58 | publishService := ginCtx.Keys["publishService"].(publish.PublishService) 59 | publishResp, err := publishService.Publish(ctx, &publishReq) 60 | PanicIfPublishError(err) 61 | 62 | ginCtx.JSON(http.StatusOK, publish.DouyinPublishActionResponse{ 63 | StatusCode: publishResp.StatusCode, 64 | StatusMsg: publishResp.StatusMsg, 65 | }) 66 | } 67 | 68 | //发布列表 69 | func PublishList(ginCtx *gin.Context) { 70 | var publishReq publish.DouyinPublishListRequest 71 | publishReq.Token = ginCtx.Query("token") 72 | ctx, _ := context.WithTimeout(ginCtx, time.Minute*1) 73 | 74 | //user_id绑定req.userId 75 | userId, err := strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 76 | PanicIfPublishError(err) 77 | publishReq.UserId = userId 78 | 79 | // 从gin.Key中取出服务实例 80 | publishService := ginCtx.Keys["publishService"].(publish.PublishService) 81 | publishResp, err := publishService.PublishList(ctx, &publishReq) 82 | PanicIfPublishError(err) 83 | 84 | ginCtx.JSON(http.StatusOK, publish.DouyinPublishListResponse{ 85 | StatusCode: publishResp.StatusCode, 86 | StatusMsg: publishResp.StatusMsg, 87 | VideoList: publishResp.VideoList, 88 | }) 89 | } 90 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/relation.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/services/relation" 5 | "context" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | "strconv" 9 | ) 10 | 11 | //关注 12 | func RelationAction(ginCtx *gin.Context) { 13 | var relationReq relation.DouyinRelationActionRequest 14 | //获取request的信息 15 | relationReq.ToUserId, _ = strconv.ParseInt(ginCtx.Query("to_user_id"), 10, 64) 16 | actionType, _ := strconv.Atoi(ginCtx.Query("action_type")) 17 | relationReq.ActionType = int32(actionType) 18 | relationReq.Token = ginCtx.Query("token") 19 | 20 | // 从gin.Key中取出服务实例 21 | relationService := ginCtx.Keys["relationService"].(relation.RelationService) 22 | //调用comment微服务,将context的上下文传入 23 | relationResp, _ := relationService.RelationAction(context.Background(), &relationReq) 24 | 25 | //返回 26 | ginCtx.JSON(http.StatusOK, relation.DouyinRelationActionResponse{ 27 | StatusCode: relationResp.StatusCode, 28 | StatusMsg: relationResp.StatusMsg, 29 | }) 30 | } 31 | 32 | //粉丝列表 33 | func FollowerList(ginCtx *gin.Context) { 34 | var relationReq relation.DouyinRelationFollowerListRequest 35 | 36 | relationReq.Token = ginCtx.Query("token") 37 | relationReq.UserId, _ = strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 38 | 39 | relationService := ginCtx.Keys["relationService"].(relation.RelationService) 40 | resp, _ := relationService.FollowerList(context.Background(), &relationReq) 41 | 42 | ginCtx.JSON(http.StatusOK, relation.DouyinRelationFollowerListResponse{ 43 | StatusCode: resp.StatusCode, 44 | StatusMsg: resp.StatusMsg, 45 | UserList: resp.UserList, 46 | }) 47 | } 48 | 49 | //关注列表 50 | func FollowList(ginCtx *gin.Context) { 51 | var relationReq relation.DouyinRelationFollowListRequest 52 | 53 | relationReq.Token = ginCtx.Query("token") 54 | relationReq.UserId, _ = strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 55 | 56 | relationService := ginCtx.Keys["relationService"].(relation.RelationService) 57 | resp, _ := relationService.FollowList(context.Background(), &relationReq) 58 | 59 | ginCtx.JSON(http.StatusOK, relation.DouyinRelationFollowListResponse{ 60 | StatusCode: resp.StatusCode, 61 | StatusMsg: resp.StatusMsg, 62 | UserList: resp.UserList, 63 | }) 64 | } 65 | 66 | //好友列表 67 | func FriendList(ginCtx *gin.Context) { 68 | var relationReq relation.DouyinRelationFriendListRequest 69 | 70 | relationReq.Token = ginCtx.Query("token") 71 | relationReq.UserId, _ = strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 72 | 73 | relationService := ginCtx.Keys["relationService"].(relation.RelationService) 74 | resp, _ := relationService.FriendList(context.Background(), &relationReq) 75 | 76 | ginCtx.JSON(http.StatusOK, relation.DouyinRelationFriendListResponse{ 77 | StatusCode: resp.StatusCode, 78 | StatusMsg: resp.StatusMsg, 79 | UserList: resp.UserList, 80 | }) 81 | } 82 | -------------------------------------------------------------------------------- /api-gateway/weblib/handlers/user.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "api-gateway/pkg/utils" 5 | user "api-gateway/services/user" 6 | "context" 7 | "fmt" 8 | "github.com/gin-gonic/gin" 9 | "net/http" 10 | "strconv" 11 | ) 12 | 13 | // 用户注册 14 | func Register(ginCtx *gin.Context) { 15 | var userReq user.DouyinUserRegisterRequest 16 | //获取用户名和密码 17 | userReq.Username = ginCtx.Query("username") 18 | userReq.Password = ginCtx.Query("password") 19 | 20 | // 从gin.Key中取出服务实例 21 | userService := ginCtx.Keys["userService"].(user.UserService) 22 | 23 | //调用user微服务,将context的上下文传入 24 | userResp, err := userService.Register(context.Background(), &userReq) 25 | PanicIfUserError(err) 26 | 27 | //生成token 28 | var token string 29 | if userResp.UserId > 0 { //做一下保护,返回的UserId应该大于0,可能用户名已存在的情况,没有报错,也不该生成token 30 | token, err = utils.GenerateToken(userResp.UserId) 31 | PanicIfUserError(err) 32 | } 33 | 34 | //返回 35 | ginCtx.JSON(http.StatusOK, user.DouyinUserRegisterResponse{ 36 | StatusCode: userResp.StatusCode, 37 | StatusMsg: userResp.StatusMsg, 38 | UserId: userResp.UserId, 39 | Token: token, 40 | }) 41 | } 42 | 43 | // 用户登录 44 | func Login(ginCtx *gin.Context) { 45 | var userReq user.DouyinUserLoginRequest 46 | userReq.Username = ginCtx.Query("username") 47 | userReq.Password = ginCtx.Query("password") 48 | 49 | // 从gin.Key中取出服务实例 50 | userService := ginCtx.Keys["userService"].(user.UserService) 51 | userResp, err := userService.Login(context.Background(), &userReq) 52 | PanicIfUserError(err) 53 | 54 | //生成token 55 | var token string 56 | if userResp != nil && userResp.UserId > 0 { 57 | token, err = utils.GenerateToken(userResp.UserId) 58 | PanicIfUserError(err) 59 | } 60 | 61 | fmt.Println("登录的token是:" + token) 62 | 63 | ginCtx.JSON(http.StatusOK, user.DouyinUserLoginResponse{ 64 | StatusCode: userResp.StatusCode, 65 | StatusMsg: userResp.StatusMsg, 66 | UserId: userResp.UserId, 67 | Token: token, 68 | }) 69 | } 70 | 71 | //获取用户的详细信息 72 | func UserInfo(ginCtx *gin.Context) { 73 | var userReq user.DouyinUserRequest 74 | //将获取到的user_id转换成int类型 75 | user_id, err := strconv.ParseInt(ginCtx.Query("user_id"), 10, 64) 76 | PanicIfUserError(err) 77 | 78 | userReq.UserId = user_id 79 | userReq.Token = ginCtx.Query("token") 80 | 81 | userService := ginCtx.Keys["userService"].(user.UserService) 82 | userResp, err := userService.UserInfo(context.Background(), &userReq) 83 | PanicIfUserError(err) 84 | 85 | ginCtx.JSON(http.StatusOK, user.DouyinUserResponse{ 86 | StatusCode: userResp.StatusCode, 87 | StatusMsg: userResp.StatusMsg, 88 | User: userResp.User, 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /api-gateway/weblib/middleware/init.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | // 接受服务实例,并存到gin.Key中 8 | func InitMiddleware(serviceMap map[string]interface{}) gin.HandlerFunc { 9 | return func(context *gin.Context) { 10 | // 将实例存在gin.Keys中 11 | context.Keys = make(map[string]interface{}) 12 | context.Keys = serviceMap 13 | context.Next() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /api-gateway/weblib/router.go: -------------------------------------------------------------------------------- 1 | package weblib 2 | 3 | import ( 4 | "api-gateway/weblib/handlers" 5 | "api-gateway/weblib/middleware" 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func NewRouter(service map[string]interface{}) *gin.Engine { 10 | ginRouter := gin.Default() 11 | ginRouter.Use(middleware.InitMiddleware(service)) 12 | 13 | v1 := ginRouter.Group("/douyin") 14 | { 15 | //user 16 | user := v1.Group("/user") 17 | { 18 | user.POST("/register/", handlers.Register) 19 | user.POST("/login/", handlers.Login) 20 | user.GET("/", handlers.UserInfo) 21 | } 22 | 23 | //publish 24 | publish := v1.Group("/publish") 25 | { 26 | publish.POST("/action/", handlers.Publish) 27 | publish.GET("/list/", handlers.PublishList) 28 | } 29 | 30 | //feed 31 | feed := v1.Group("/feed") 32 | { 33 | feed.GET("/", handlers.Feed) 34 | } 35 | 36 | //favorite 37 | fav := v1.Group("/favorite") 38 | { 39 | fav.POST("/action/", handlers.FavoriteAction) 40 | fav.GET("/list/", handlers.FavoriteList) 41 | } 42 | 43 | //comment 44 | comment := v1.Group("/comment") 45 | { 46 | comment.POST("/action/", handlers.CommentAction) 47 | comment.GET("/list/", handlers.CommentList) 48 | } 49 | 50 | //relation 51 | relation := v1.Group("/relation") 52 | { 53 | relation.POST("/action/", handlers.RelationAction) 54 | relation.GET("/follow/list/", handlers.FollowList) 55 | relation.GET("/follower/list/", handlers.FollowerList) 56 | relation.GET("/friend/list/", handlers.FriendList) 57 | } 58 | 59 | //message 60 | message := v1.Group("/message") 61 | { 62 | message.POST("/action/", handlers.MessageAction) 63 | message.GET("/chat/", handlers.MessageList) 64 | } 65 | } 66 | return ginRouter 67 | } 68 | -------------------------------------------------------------------------------- /api-gateway/wrappers/commentWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type commentWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *commentWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewCommentWrapper 初始化Wrapper 30 | func NewCommentWrapper(c client.Client) client.Client { 31 | return &commentWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/favoriteWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type favoriteWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *favoriteWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | // NewUserWrapper 初始化Wrapper 30 | func NewFavoriteWrapper(c client.Client) client.Client { 31 | return &favoriteWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/feedWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type feedWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *feedWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewFeedWrapper 初始化Wrapper 30 | func NewFeedWrapper(c client.Client) client.Client { 31 | return &feedWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/messageWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type messageWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *messageWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewMessageWrapper 初始化Wrapper 30 | func NewMessageWrapper(c client.Client) client.Client { 31 | return &messageWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/publishWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type publishWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *publishWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewPublishWrapper 初始化Wrapper 30 | func NewPublishWrapper(c client.Client) client.Client { 31 | return &publishWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/relationWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type relationWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *relationWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewRelationWrapper 初始化Wrapper 30 | func NewRelationWrapper(c client.Client) client.Client { 31 | return &relationWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /api-gateway/wrappers/userWrapper.go: -------------------------------------------------------------------------------- 1 | package wrappers 2 | 3 | import ( 4 | "context" 5 | "github.com/afex/hystrix-go/hystrix" 6 | "github.com/micro/go-micro/v2/client" 7 | ) 8 | 9 | type userWrapper struct { 10 | client.Client 11 | } 12 | 13 | func (wrapper *userWrapper) Call(ctx context.Context, req client.Request, resp interface{}, opts ...client.CallOption) error { 14 | cmdName := req.Service() + "." + req.Endpoint() 15 | config := hystrix.CommandConfig{ 16 | Timeout: 30000, 17 | RequestVolumeThreshold: 20, //熔断器请求阈值,默认20,意思是有20个请求才能进行错误百分比计算 18 | ErrorPercentThreshold: 50, //错误百分比,当错误超过百分比时,直接进行降级处理,直至熔断器再次 开启,默认50% 19 | SleepWindow: 5000, //过多长时间,熔断器再次检测是否开启,单位毫秒ms(默认5秒) 20 | } 21 | hystrix.ConfigureCommand(cmdName, config) 22 | return hystrix.Do(cmdName, func() error { 23 | return wrapper.Client.Call(ctx, req, resp) 24 | }, func(err error) error { 25 | return err 26 | }) 27 | } 28 | 29 | //NewUserWrapper 初始化Wrapper 30 | func NewUserWrapper(c client.Client) client.Client { 31 | return &userWrapper{c} 32 | } 33 | -------------------------------------------------------------------------------- /comment/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "comment/model" 5 | "fmt" 6 | "github.com/go-ini/ini" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /comment/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /comment/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "comment/core" 5 | proto "comment/service" 6 | "github.com/micro/go-micro/v2" 7 | "github.com/micro/go-micro/v2/registry" 8 | "github.com/micro/go-micro/v2/registry/etcd" 9 | ) 10 | 11 | func main() { 12 | 13 | // etcd注册件 14 | etcdReg := etcd.NewRegistry( 15 | registry.Addrs("127.0.0.1:2379"), 16 | ) 17 | // 得到一个微服务实例 18 | microService := micro.NewService( 19 | micro.Name("rpcCommentService"), // 微服务名字 20 | micro.Address("127.0.0.1:8087"), 21 | micro.Registry(etcdReg), // etcd注册件 22 | micro.Metadata(map[string]string{"protocol": "http"}), 23 | ) 24 | 25 | // 结构命令行参数,初始化 26 | microService.Init() 27 | // 服务注册 28 | _ = proto.RegisterCommentServiceHandler(microService.Server(), new(core.CommentService)) 29 | // 启动微服务 30 | 31 | _ = microService.Run() 32 | 33 | } 34 | -------------------------------------------------------------------------------- /comment/model/comment.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "gorm.io/gorm" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | type Comment struct { 11 | CommentId int64 `gorm:"primary_key"` 12 | UserId int64 `gorm:"default:(-)"` 13 | VideoId int64 `gorm:"default:(-)"` 14 | Content string `gorm:"default:(-)"` 15 | CreateAt time.Time 16 | DeletedAt gorm.DeletedAt 17 | } 18 | 19 | func (Comment) TableName() string { 20 | return "comment" 21 | } 22 | 23 | type CommentDao struct { 24 | } 25 | 26 | /* 27 | * 28 | 根据commentId删除信息,软删除,因为有deleteat字段,返回这个操作有错误吗 29 | */ 30 | func (*CommentDao) DeleteCommentById(commentId int64) error { 31 | 32 | err := DB.Where("comment_id = ?", commentId).Delete(&Comment{}).Error 33 | 34 | /*err := DB.Delete(commentId).Error*/ 35 | 36 | if err != nil { 37 | fmt.Printf("删除失败", err) 38 | } 39 | 40 | return nil 41 | } 42 | 43 | /* 44 | * 45 | 创建一条Comment,返回创建的comment和error信息 46 | */ 47 | func (*CommentDao) CreateComment(comment *Comment) (*Comment, error) { 48 | //和数据库进行操作 49 | result := DB.Create(&comment) 50 | 51 | if result.Error != nil { 52 | return nil, result.Error 53 | } 54 | 55 | fmt.Println("model层的输出") 56 | //fmt.Println(comment.ID) 57 | return comment, nil 58 | } 59 | 60 | /* 61 | * 62 | 传入videoId,查出comments 63 | */ 64 | func (*CommentDao) QueryComment(videoId int64) ([]*Comment, error) { 65 | var comment []*Comment 66 | 67 | err := DB.Where("video_id = ?", videoId).Find(&comment).Error 68 | 69 | if err != nil { 70 | fmt.Println("查询Video列表失败") 71 | return nil, err 72 | } 73 | 74 | return comment, nil 75 | } 76 | 77 | /** 78 | 通过commentId拿到comment实体,从实体中拿到userId 79 | */ 80 | func (*CommentDao) GetUserIdByCommentId(id int64) (int64, error) { 81 | comment := Comment{CommentId: id} 82 | result := DB.Where("comment_id = ?", id).First(&comment).Error 83 | return comment.UserId, result 84 | } 85 | 86 | var commentDao *CommentDao 87 | var commentOnce sync.Once //单例模式,只生成一个commentDao实例,提高性能 88 | 89 | func NewCommentDaoInstance() *CommentDao { 90 | commentOnce.Do( 91 | func() { 92 | commentDao = &CommentDao{} 93 | }) 94 | return commentDao 95 | } 96 | -------------------------------------------------------------------------------- /comment/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | func init() { 14 | DB, _ = gorm.Open("mysql", "root:jhr292023@tcp(43.138.51.56:3306)/simple-douyin?charset=utf8&parseTime=True&loc=Local") 15 | } 16 | 17 | // Database 在中间件中初始化mysql链接 18 | func Database(connString string) { 19 | db, err := gorm.Open("mysql", connString) 20 | if err != nil { 21 | panic(err) 22 | } 23 | db.LogMode(true) 24 | if gin.Mode() == "release" { 25 | db.LogMode(false) 26 | } 27 | //默认不加复数 28 | db.SingularTable(true) 29 | //设置连接池 30 | //空闲 31 | db.DB().SetMaxIdleConns(20) 32 | //打开 33 | db.DB().SetMaxOpenConns(100) 34 | //超时 35 | db.DB().SetConnMaxLifetime(time.Second * 30) 36 | DB = db 37 | //migration() 38 | } 39 | -------------------------------------------------------------------------------- /comment/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "comment/rpc_server/etcd" 5 | tokenproto "comment/service/tokenproto" 6 | "context" 7 | "fmt" 8 | "github.com/micro/go-micro/v2" 9 | ) 10 | 11 | /** 12 | 调用token解析 13 | */ 14 | func GetIdByToken(token string) (int64, error) { 15 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 16 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) 17 | 18 | var req tokenproto.GetIdByTokenRequest 19 | 20 | req.UserToken = token 21 | 22 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 23 | if err != nil { 24 | fmt.Println(err) 25 | } 26 | return int64(resp.UserId), err 27 | } 28 | -------------------------------------------------------------------------------- /comment/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /comment/rpc_server/publishRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | etcdInit "comment/rpc_server/etcd" 5 | publishproto "comment/service/frompublish" 6 | "context" 7 | "fmt" 8 | "github.com/micro/go-micro/v2" 9 | ) 10 | 11 | func CountAction(vid int64, count int32, actionType int32) bool { 12 | toCommentMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 13 | toCommentService := publishproto.NewToCommentService("rpcPublishService", toCommentMicroService.Client()) 14 | var req publishproto.UpdateCommentCountRequest 15 | req.VideoId = vid 16 | req.Count = count 17 | req.Type = actionType 18 | publishCount, err := toCommentService.UpdateCommentCount(context.TODO(), &req) 19 | if err != nil || publishCount.StatusCode != 0 { 20 | fmt.Println("commentCount维护失败:", err) 21 | return false 22 | } 23 | return true 24 | 25 | } 26 | -------------------------------------------------------------------------------- /comment/rpc_server/userRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "comment/rpc_server/etcd" 5 | usersproto "comment/service/to_relation" 6 | userproto "comment/service/userproto" 7 | "context" 8 | "fmt" 9 | "github.com/micro/go-micro/v2" 10 | ) 11 | 12 | /** 13 | 调用user查询用户信息 14 | */ 15 | func GetUserInfo(userId int64, token string) (*userproto.User, error) { 16 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 17 | userService := userproto.NewUserService("rpcUserService", userMicroService.Client()) 18 | 19 | var req userproto.DouyinUserRequest 20 | 21 | req.UserId = userId 22 | req.Token = token 23 | 24 | resp, err := userService.UserInfo(context.TODO(), &req) 25 | if err != nil { 26 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 27 | fmt.Println(err) 28 | } 29 | 30 | user := &userproto.User{ 31 | Id: resp.User.Id, 32 | Name: resp.User.Name, 33 | FollowCount: resp.User.FollowCount, 34 | FollowerCount: resp.User.FollowerCount, 35 | IsFollow: resp.User.IsFollow, 36 | } 37 | return user, err 38 | } 39 | 40 | /** 41 | 输入userId列表,查询User实体列表 42 | */ 43 | func GetUsersInfo(userId []int64, token string) ([]*usersproto.User, error) { 44 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 45 | usersService := usersproto.NewToRelationService("rpcUserService", userMicroService.Client()) 46 | 47 | var req usersproto.GetUsersByIdsRequest 48 | 49 | req.UserId = userId 50 | req.Token = token 51 | 52 | resp, err := usersService.GetUsersByIds(context.TODO(), &req) 53 | if err != nil { 54 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 55 | fmt.Println(err) 56 | } 57 | fmt.Println("调用回来了") 58 | fmt.Println(resp.UserList) 59 | 60 | return resp.UserList, err 61 | } 62 | -------------------------------------------------------------------------------- /comment/service/comment.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: comment.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for CommentService service 37 | 38 | func NewCommentServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for CommentService service 43 | 44 | type CommentService interface { 45 | CommentAction(ctx context.Context, in *DouyinCommentActionRequest, opts ...client.CallOption) (*DouyinCommentActionResponse, error) 46 | CommentList(ctx context.Context, in *DouyinCommentListRequest, opts ...client.CallOption) (*DouyinCommentListResponse, error) 47 | } 48 | 49 | type commentService struct { 50 | c client.Client 51 | name string 52 | } 53 | 54 | func NewCommentService(name string, c client.Client) CommentService { 55 | return &commentService{ 56 | c: c, 57 | name: name, 58 | } 59 | } 60 | 61 | func (c *commentService) CommentAction(ctx context.Context, in *DouyinCommentActionRequest, opts ...client.CallOption) (*DouyinCommentActionResponse, error) { 62 | req := c.c.NewRequest(c.name, "CommentService.CommentAction", in) 63 | out := new(DouyinCommentActionResponse) 64 | err := c.c.Call(ctx, req, out, opts...) 65 | if err != nil { 66 | return nil, err 67 | } 68 | return out, nil 69 | } 70 | 71 | func (c *commentService) CommentList(ctx context.Context, in *DouyinCommentListRequest, opts ...client.CallOption) (*DouyinCommentListResponse, error) { 72 | req := c.c.NewRequest(c.name, "CommentService.CommentList", in) 73 | out := new(DouyinCommentListResponse) 74 | err := c.c.Call(ctx, req, out, opts...) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return out, nil 79 | } 80 | 81 | // Server API for CommentService service 82 | 83 | type CommentServiceHandler interface { 84 | CommentAction(context.Context, *DouyinCommentActionRequest, *DouyinCommentActionResponse) error 85 | CommentList(context.Context, *DouyinCommentListRequest, *DouyinCommentListResponse) error 86 | } 87 | 88 | func RegisterCommentServiceHandler(s server.Server, hdlr CommentServiceHandler, opts ...server.HandlerOption) error { 89 | type commentService interface { 90 | CommentAction(ctx context.Context, in *DouyinCommentActionRequest, out *DouyinCommentActionResponse) error 91 | CommentList(ctx context.Context, in *DouyinCommentListRequest, out *DouyinCommentListResponse) error 92 | } 93 | type CommentService struct { 94 | commentService 95 | } 96 | h := &commentServiceHandler{hdlr} 97 | return s.Handle(s.NewHandler(&CommentService{h}, opts...)) 98 | } 99 | 100 | type commentServiceHandler struct { 101 | CommentServiceHandler 102 | } 103 | 104 | func (h *commentServiceHandler) CommentAction(ctx context.Context, in *DouyinCommentActionRequest, out *DouyinCommentActionResponse) error { 105 | return h.CommentServiceHandler.CommentAction(ctx, in, out) 106 | } 107 | 108 | func (h *commentServiceHandler) CommentList(ctx context.Context, in *DouyinCommentListRequest, out *DouyinCommentListResponse) error { 109 | return h.CommentServiceHandler.CommentList(ctx, in, out) 110 | } 111 | -------------------------------------------------------------------------------- /comment/service/frompublish/to_comment.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: to_comment.proto 3 | 4 | package frompublish 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for ToCommentService service 37 | 38 | func NewToCommentServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for ToCommentService service 43 | 44 | type ToCommentService interface { 45 | UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, opts ...client.CallOption) (*UpdateCommentCountResponse, error) 46 | } 47 | 48 | type toCommentService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewToCommentService(name string, c client.Client) ToCommentService { 54 | return &toCommentService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *toCommentService) UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, opts ...client.CallOption) (*UpdateCommentCountResponse, error) { 61 | req := c.c.NewRequest(c.name, "ToCommentService.UpdateCommentCount", in) 62 | out := new(UpdateCommentCountResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for ToCommentService service 71 | 72 | type ToCommentServiceHandler interface { 73 | UpdateCommentCount(context.Context, *UpdateCommentCountRequest, *UpdateCommentCountResponse) error 74 | } 75 | 76 | func RegisterToCommentServiceHandler(s server.Server, hdlr ToCommentServiceHandler, opts ...server.HandlerOption) error { 77 | type toCommentService interface { 78 | UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, out *UpdateCommentCountResponse) error 79 | } 80 | type ToCommentService struct { 81 | toCommentService 82 | } 83 | h := &toCommentServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&ToCommentService{h}, opts...)) 85 | } 86 | 87 | type toCommentServiceHandler struct { 88 | ToCommentServiceHandler 89 | } 90 | 91 | func (h *toCommentServiceHandler) UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, out *UpdateCommentCountResponse) error { 92 | return h.ToCommentServiceHandler.UpdateCommentCount(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /comment/service/proto/comment.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message douyin_comment_action_request { 6 | string token = 1; // 用户鉴权token 7 | int64 video_id = 2; // 视频id 8 | int32 action_type = 3; // 1-发布评论,2-删除评论 9 | string comment_text = 4; // 用户填写的评论内容,在action_type=1的时候使用 10 | int64 comment_id = 5; // 要删除的评论id,在action_type=2的时候使用 11 | } 12 | 13 | message douyin_comment_action_response { 14 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 15 | string status_msg = 2; // 返回状态描述 16 | Comment comment = 3; // 评论成功返回评论内容,不需要重新拉取整个列表 17 | } 18 | 19 | message Comment { 20 | int64 id = 1; // 视频评论id 21 | User user =2; // 评论用户信息 22 | string content = 3; // 评论内容 23 | string create_date = 4; // 评论发布日期,格式 mm-dd 24 | } 25 | 26 | message douyin_comment_list_request { 27 | string token = 1; // 用户鉴权token 28 | int64 video_id = 2; // 视频id 29 | } 30 | 31 | message douyin_comment_list_response { 32 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 33 | string status_msg = 2; // 返回状态描述 34 | repeated Comment comment_list = 3; // 评论列表 35 | } 36 | 37 | message User { 38 | int64 id = 1; // 用户id 39 | string name = 2; // 用户名称 40 | int64 follow_count = 3; // 关注总数 41 | int64 follower_count = 4; // 粉丝总数 42 | bool is_follow = 5; // true-已关注,false-未关注 43 | } 44 | 45 | service CommentService{ 46 | rpc CommentAction(douyin_comment_action_request) returns (douyin_comment_action_response); 47 | rpc CommentList(douyin_comment_list_request) returns(douyin_comment_list_response); 48 | } -------------------------------------------------------------------------------- /comment/service/token/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package proto 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /comment/service/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /comment/utils/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "context" 5 | "github.com/go-redis/redis/v8" 6 | ) 7 | 8 | var Ctx = context.Background() 9 | var RdbUserVideo *redis.Client 10 | var RdbVideoId *redis.Client 11 | var RdbUserId *redis.Client 12 | 13 | // InitRedis 初始化Redis连接。 14 | func InitRedis() { 15 | RdbUserVideo = redis.NewClient(&redis.Options{ 16 | Addr: "43.138.51.56:6379", 17 | Password: "292023", 18 | DB: 2, // 是否点赞信息存入 DB2. 19 | }) 20 | RdbVideoId = redis.NewClient(&redis.Options{ 21 | Addr: "43.138.51.56:6379", 22 | Password: "292023", 23 | DB: 1, // 视频信息存入 DB1. 24 | }) 25 | RdbUserId = redis.NewClient(&redis.Options{ 26 | Addr: "43.138.51.56:6379", 27 | Password: "292023", 28 | DB: 0, // 用户信息存入 DB0. 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /favorite/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "favorite/model" 5 | "fmt" 6 | "github.com/go-ini/ini" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /favorite/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /favorite/core/favoriteService.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | etcdInit "favorite/etcd" 6 | "favorite/mapper" 7 | proto "favorite/service" 8 | "favorite/utils" 9 | "fmt" 10 | ) 11 | 12 | type FavoriteService struct { 13 | } 14 | 15 | var favmapper *mapper.FavoriteMapper 16 | 17 | func init() { 18 | favmapper = mapper.FavoriteMapperInstance() 19 | } 20 | func (*FavoriteService) FavoriteAction(ctx context.Context, in *proto.DouyinFavoriteActionRequest, out *proto.DouyinFavoriteActionResponse) error { 21 | actionType := in.ActionType //1点赞 2取消 22 | vid := in.VideoId 23 | token := in.Token 24 | uid, err := utils.GetIdByToken(token) 25 | if err != nil { 26 | out.StatusCode = 500 27 | out.StatusMsg = "登录失效" 28 | return err 29 | } 30 | err = favmapper.FavoriteAction(uid, vid, actionType, token) 31 | if err != nil { 32 | out.StatusCode = 500 33 | out.StatusMsg = "操作失败" 34 | return err 35 | } 36 | out.StatusMsg = "操作成功" 37 | out.StatusCode = 0 38 | return nil 39 | 40 | } 41 | 42 | func (*FavoriteService) FavoriteList(ctx context.Context, in *proto.DouyinFavoriteListRequest, out *proto.DouyinFavoriteListResponse) error { 43 | fmt.Println("====进入====") 44 | _, err := utils.GetIdByToken(in.Token) 45 | if err != nil { 46 | out.StatusCode = 500 47 | out.StatusMsg = "登录失效" 48 | return err 49 | } 50 | id := in.UserId 51 | var videoIds []int64 52 | videoIds = favmapper.GetVideoIds(id) 53 | fmt.Println("videoIds==", videoIds) 54 | resp, err := etcdInit.GetVideosByIds(videoIds, in.Token) 55 | if err != nil { 56 | fmt.Println("出错了,....") 57 | out.StatusCode = 500 58 | out.StatusMsg = "获取视频失败" 59 | return err 60 | } 61 | 62 | out.VideoList = resp 63 | out.StatusCode = 0 64 | out.StatusMsg = "查询成功" 65 | 66 | return nil 67 | } 68 | -------------------------------------------------------------------------------- /favorite/core/tovideo/toVideoService.go: -------------------------------------------------------------------------------- 1 | package tovideo 2 | 3 | import ( 4 | "context" 5 | "favorite/mapper" 6 | proto "favorite/service" 7 | redis "favorite/utils/redis" 8 | "fmt" 9 | "log" 10 | "strconv" 11 | ) 12 | 13 | type ToVideoService struct { 14 | } 15 | 16 | func (*ToVideoService) GetFavoriteStatus(ctx context.Context, in *proto.GetFavoriteStatus_Request, out *proto.GetFavoriteStatus_Response) error { 17 | vid := in.VideoId 18 | uid := in.UserId 19 | status, err := mapper.FavoriteMapper{}.GetFavoriteStatus(vid, uid) 20 | if err != nil { 21 | return err 22 | } 23 | out.IsFavorite = status 24 | return nil 25 | } 26 | 27 | /** 28 | 根据传进来的{userId,videoId,isFavorite}集合,查询数据库的isFavorite后,返回{userId,videoId,isFavorite}集合 29 | */ 30 | func (*ToVideoService) GetFavoritesStatus(ctx context.Context, in *proto.GetFavoritesStatus_Request, out *proto.GetFavoritesStatus_Response) error { 31 | var result []*proto.FavoriteStatus 32 | for _, favoriteStatus := range in.FavoriteStatus { 33 | //查询一下redis有这个点赞关系记录吗? 34 | //构造key userid+videoid 35 | key := strconv.FormatInt(favoriteStatus.UserId, 10) + "+" + strconv.FormatInt(favoriteStatus.VideoId, 10) 36 | count, err := redis.RdbUserVideo.Exists(redis.Ctx, key).Result() 37 | if err != nil { 38 | log.Println(err) 39 | } 40 | if count > 0 { //缓存里有 41 | //redis,从redis中查是否有点赞关系 42 | isFavoriteRedis, err := redis.RdbUserVideo.Get(redis.Ctx, key).Result() 43 | if err != nil { //若查询缓存出错,则打印log 44 | //return 0, err 45 | log.Println("调用redis查询userId对应的信息出错", err) 46 | } 47 | status, _ := strconv.ParseBool(isFavoriteRedis) 48 | result = append(result, &proto.FavoriteStatus{UserId: favoriteStatus.UserId, VideoId: favoriteStatus.VideoId, IsFavorite: status}) 49 | } else { 50 | fmt.Println("查数据库") 51 | status, _ := mapper.FavoriteMapper{}.GetFavoriteStatus(favoriteStatus.VideoId, favoriteStatus.UserId) 52 | res := &proto.FavoriteStatus{UserId: favoriteStatus.UserId, VideoId: favoriteStatus.VideoId, IsFavorite: status} 53 | result = append(result, res) 54 | //把查到的数据放入redis 55 | _ = redis.RdbUserVideo.Set(redis.Ctx, key, strconv.FormatBool(status), 0).Err() 56 | } 57 | } 58 | fmt.Println(result) 59 | out.IsFavorite = result 60 | out.StatusCode = 0 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /favorite/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "context" 5 | proto "favorite/service" 6 | from_user_proto "favorite/service/from_user" 7 | "favorite/service/frompublish" 8 | "fmt" 9 | "github.com/micro/go-micro/v2" 10 | "github.com/micro/go-micro/v2/registry" 11 | "github.com/micro/go-micro/v2/registry/etcd" 12 | ) 13 | 14 | var EtcdReg registry.Registry 15 | 16 | func init() { 17 | EtcdReg = etcd.NewRegistry( 18 | registry.Addrs("127.0.0.1:2379"), 19 | ) 20 | 21 | } 22 | func CountAction(vid int64, count int32, actionType int32) bool { 23 | MicroService := micro.NewService(micro.Registry(EtcdReg)) 24 | Service := frompublish.NewToFavoriteService("rpcPublishService", MicroService.Client()) 25 | var req frompublish.UpdateFavoriteCountRequest 26 | req.VideoId = vid 27 | req.Count = count 28 | req.Type = actionType 29 | favoriteCount, err := Service.UpdateFavoriteCount(context.TODO(), &req) 30 | if err != nil || favoriteCount.StatusCode != 0 { 31 | fmt.Println("favoriteCount维护失败:", err) 32 | return false 33 | } 34 | return true 35 | 36 | } 37 | 38 | func UpdateFavoriteCount(uid int64, count int32, actionType int32) bool { 39 | toFavoriteMicroService := micro.NewService(micro.Registry(EtcdReg)) 40 | toFavoriteService := from_user_proto.NewToFavoriteService("rpcUserService", toFavoriteMicroService.Client()) 41 | 42 | var req from_user_proto.UpdateFavoriteCountRequest 43 | req.UserId = uid 44 | req.Count = count 45 | req.Type = actionType 46 | resp, err := toFavoriteService.UpdateFavoriteCount(context.TODO(), &req) 47 | if err != nil || resp.StatusCode != 0 { 48 | fmt.Println("favorite_count维护失败:", err) 49 | return false 50 | } 51 | return true 52 | 53 | } 54 | 55 | func UpdateTotalFavorited(vid int64, count int32, actionType int32, token string) bool { 56 | toFavoriteMicroService := micro.NewService(micro.Registry(EtcdReg)) 57 | toFavoriteService := from_user_proto.NewToFavoriteService("rpcUserService", toFavoriteMicroService.Client()) 58 | 59 | //根据vid查找uid 60 | var videoId []int64 61 | videoId = append(videoId, vid) 62 | videos, err := GetVideosByIds(videoId, token) 63 | fmt.Println(videos) 64 | uid := videos[0].Author.Id 65 | 66 | var req from_user_proto.UpdateTotalFavoritedRequest 67 | req.UserId = uid 68 | req.Count = count 69 | req.Type = actionType 70 | resp, err := toFavoriteService.UpdateTotalFavorited(context.TODO(), &req) 71 | if err != nil || resp.StatusCode != 0 { 72 | fmt.Println("total_favorited 维护失败:", err) 73 | return false 74 | } 75 | return true 76 | 77 | } 78 | 79 | func GetVideosByIds(vids []int64, token string) ([]*proto.Video, error) { 80 | //// 服务调用实例 81 | 82 | MicroService := micro.NewService(micro.Registry(EtcdReg)) 83 | Service := frompublish.NewToFavoriteService("rpcPublishService", MicroService.Client()) //client.DefaultClient 84 | 85 | var req frompublish.GetVideosByIdsRequest 86 | 87 | req.VideoId = vids 88 | req.Token = token 89 | resp, err := Service.GetVideosByIds(context.TODO(), &req) 90 | if err != nil { 91 | fmt.Println("远程调用错误", err) 92 | return nil, err 93 | } 94 | 95 | return changeVideo(resp.VideoList), nil 96 | 97 | } 98 | func changeVideo(videos []*frompublish.Video) []*proto.Video { 99 | var res []*proto.Video 100 | 101 | for i := 0; i < len(videos); i++ { 102 | video := videos[i] 103 | one := proto.Video{ 104 | Id: video.Id, 105 | Author: changeUser(video.Author), 106 | PlayUrl: video.PlayUrl, 107 | CoverUrl: video.CoverUrl, 108 | FavoriteCount: video.FavoriteCount, 109 | CommentCount: video.CommentCount, 110 | IsFavorite: video.IsFavorite, 111 | Title: video.Title, 112 | } 113 | res = append(res, &one) 114 | } 115 | return res 116 | } 117 | 118 | func changeUser(fuser *frompublish.User) *proto.User { 119 | return &proto.User{ 120 | Id: fuser.Id, 121 | Name: fuser.Name, 122 | FollowCount: fuser.FollowCount, 123 | FollowerCount: fuser.FollowerCount, 124 | IsFollow: fuser.IsFollow, 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /favorite/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "favorite/core" 5 | "favorite/core/tovideo" 6 | etcdInit "favorite/etcd" 7 | proto "favorite/service" 8 | utils "favorite/utils/redis" 9 | "github.com/micro/go-micro/v2" 10 | ) 11 | 12 | func main() { 13 | //redis 14 | utils.InitRedis() 15 | etcdReg := etcdInit.EtcdReg 16 | // 得到一个微服务实例 17 | microService := micro.NewService( 18 | micro.Name("rpcFavoriteService"), // 微服务名字 19 | micro.Address("127.0.0.1:8086"), 20 | micro.Registry(etcdReg), // etcd注册件 21 | micro.Metadata(map[string]string{"protocol": "http"}), 22 | ) 23 | 24 | // 结构命令行参数,初始化 25 | microService.Init() 26 | // 服务注册 27 | _ = proto.RegisterToVideoServiceHandler(microService.Server(), new(tovideo.ToVideoService)) 28 | _ = proto.RegisterFavoriteServiceHandler(microService.Server(), new(core.FavoriteService)) 29 | // 启动微服务 30 | 31 | _ = microService.Run() 32 | 33 | } 34 | -------------------------------------------------------------------------------- /favorite/model/favorite.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Favorite struct { 8 | UserId int64 9 | VideoId int64 10 | CreatedAt time.Time 11 | } 12 | 13 | func (Favorite) TableName() string { 14 | return "favorite" 15 | } 16 | -------------------------------------------------------------------------------- /favorite/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | func init() { 14 | DB, _ = gorm.Open("mysql", "root:jhr292023@tcp(43.138.51.56:3306)/simple-douyin?charset=utf8&parseTime=True&loc=Local") 15 | } 16 | 17 | // Database 在中间件中初始化mysql链接 18 | func Database(connString string) { 19 | db, err := gorm.Open("mysql", connString) 20 | if err != nil { 21 | panic(err) 22 | } 23 | db.LogMode(true) 24 | if gin.Mode() == "release" { 25 | db.LogMode(false) 26 | } 27 | //默认不加复数 28 | db.SingularTable(true) 29 | //设置连接池 30 | //空闲 31 | db.DB().SetMaxIdleConns(20) 32 | //打开 33 | db.DB().SetMaxOpenConns(100) 34 | //超时 35 | db.DB().SetConnMaxLifetime(time.Second * 30) 36 | DB = db 37 | //migration() 38 | } 39 | -------------------------------------------------------------------------------- /favorite/service/proto/fav.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message douyin_favorite_action_request { 6 | string token = 1; // 用户鉴权token 7 | int64 video_id = 2; // 视频id 8 | int32 action_type = 3; // 1-点赞,2-取消点赞 9 | } 10 | 11 | message douyin_favorite_action_response { 12 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 13 | string status_msg = 2; // 返回状态描述 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | message douyin_favorite_list_request { 22 | int64 user_id = 1; // 用户id 23 | string token = 2; // 用户鉴权token 24 | } 25 | 26 | message douyin_favorite_list_response { 27 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 28 | string status_msg = 2; // 返回状态描述 29 | repeated Video video_list = 3; // 用户点赞视频列表 30 | } 31 | 32 | message Video { 33 | int64 id = 1; // 视频唯一标识 34 | User author = 2; // 视频作者信息 35 | string play_url = 3; // 视频播放地址 36 | string cover_url = 4; // 视频封面地址 37 | int64 favorite_count = 5; // 视频的点赞总数 38 | int64 comment_count = 6; // 视频的评论总数 39 | bool is_favorite = 7; // true-已点赞,false-未点赞 40 | string title = 8; // 视频标题 41 | } 42 | 43 | message User { 44 | int64 id = 1; // 用户id 45 | string name = 2; // 用户名称 46 | int64 follow_count = 3; // 关注总数 47 | int64 follower_count = 4; // 粉丝总数 48 | bool is_follow = 5; // true-已关注,false-未关注 49 | } 50 | service FavoriteService{ 51 | rpc FavoriteAction(douyin_favorite_action_request) returns (douyin_favorite_action_response); 52 | rpc FavoriteList(douyin_favorite_list_request) returns(douyin_favorite_list_response); 53 | 54 | } -------------------------------------------------------------------------------- /favorite/service/proto/to_video/to_video.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | message GetFavoriteStatus_Request{ 5 | int64 user_id=1; 6 | int64 video_id=2; 7 | } 8 | 9 | message GetFavoriteStatus_Response{ 10 | bool isFavorite=1; 11 | } 12 | 13 | message GetFavoritesStatus_Request{ 14 | repeated FavoriteStatus favoriteStatus = 1; 15 | string token = 2; 16 | } 17 | 18 | message GetFavoritesStatus_Response{ 19 | int64 status_code = 1; 20 | repeated FavoriteStatus isFavorite=2; 21 | } 22 | 23 | message FavoriteStatus { 24 | int64 user_id=1; //发起关注的人 25 | int64 video_id=2; //被关注的人 26 | bool isFavorite=3; //是否关注 27 | } 28 | 29 | service ToVideoService{ 30 | rpc GetFavoriteStatus(GetFavoriteStatus_Request)returns(GetFavoriteStatus_Response); 31 | rpc GetFavoritesStatus(GetFavoritesStatus_Request) returns (GetFavoritesStatus_Response); 32 | } -------------------------------------------------------------------------------- /favorite/service/proto/token_utils.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;service"; 4 | message GetIdByToken_request { 5 | string user_token = 1; // token 6 | 7 | } 8 | 9 | message GetIdByToken_response { 10 | int32 user_id = 1; // 用户id 11 | 12 | } 13 | service TokenService{ 14 | rpc GetIdByToken(GetIdByToken_request) returns (GetIdByToken_response); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /favorite/service/proto/video_favorite.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;service"; 4 | 5 | message UpdateFavoriteCount_request { 6 | int64 video_id = 1; // 视频id 7 | int32 count = 2;// 增加的数量 8 | int32 type = 3;// 1是增加,2是减少 9 | } 10 | 11 | message UpdateFavoriteCount_response { 12 | int32 status_code = 1; //响应,成功是0,失败是其他值 13 | } 14 | 15 | message GetVideoById_request { 16 | int64 video_id = 1; // 视频id 17 | } 18 | 19 | message GetVideoById_response { 20 | int64 video_id = 1;//视频id 21 | repeated Video VideoList = 3; //视频集合 22 | } 23 | 24 | message Video { 25 | // @gotags: json:"id" 26 | int64 Id = 1; // 视频唯一标识 27 | // @gotags: json:"author" 28 | User Author = 2; // 视频作者信息 29 | // @gotags: json:"play_url" 30 | string PlayUrl = 3; // 视频播放地址 31 | // @gotags: json:"cover_url" 32 | string CoverUrl = 4; // 视频封面地址 33 | // @gotags: json:"favorite_count" 34 | int64 FavoriteCount = 5; // 视频的点赞总数 35 | // @gotags: json:"comment_count" 36 | int64 CommentCount = 6; // 视频的评论总数 37 | // @gotags: json:"is_favorite" 38 | bool IsFavorite = 7; // true-已点赞,false-未点赞 39 | // @gotags: json:"title" 40 | string Title = 8; // 视频标题 41 | } 42 | 43 | message User { 44 | // @gotags: json:"id" 45 | int64 Id = 1; // 用户id 46 | // @gotags: json:"name" 47 | string Name = 2; // 用户名称 48 | // @gotags: json:"follow_count" 49 | int64 FollowCount = 3; // 关注总数 50 | // @gotags: json:"follower_count" 51 | int64 FollowerCount = 4; // 粉丝总数 52 | // @gotags: json:"is_follow" 53 | bool IsFollow = 5; // true-已关注,false-未关注 54 | } 55 | 56 | service TokenService{ 57 | rpc UpdateFavoriteCount(UpdateFavoriteCount_request) returns (UpdateFavoriteCount_response);//给视频点赞 58 | rpc GetVideoById(GetVideoById_request) returns (GetVideoById_response);//根据视频id获取视频集合 59 | } 60 | 61 | -------------------------------------------------------------------------------- /favorite/service/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package proto 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /favorite/utils/GetIdByToken.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "favorite/etcd" 6 | proto "favorite/service" 7 | "fmt" 8 | "github.com/micro/go-micro/v2" 9 | ) 10 | 11 | func GetIdByToken(token string) (int64, error) { 12 | if "" == token { 13 | return -1, nil 14 | } 15 | 16 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 17 | 18 | tokenService := proto.NewTokenService("rpcTokenService", tokenMicroService.Client()) //client.DefaultClient 19 | 20 | var req proto.GetIdByTokenRequest 21 | 22 | req.UserToken = token 23 | 24 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 25 | if err != nil { 26 | fmt.Println(err) 27 | return -1, err 28 | } 29 | return int64(resp.UserId), nil 30 | } 31 | -------------------------------------------------------------------------------- /favorite/utils/rabbitmq/rabbitMQ.go: -------------------------------------------------------------------------------- 1 | package rabbitmq 2 | 3 | import ( 4 | "fmt" 5 | "github.com/streadway/amqp" 6 | "log" 7 | ) 8 | 9 | const MQURL = "amqp://admin:admin@43.138.51.56:5672/" 10 | 11 | type RabbitMQ struct { 12 | conn *amqp.Connection 13 | mqurl string 14 | } 15 | 16 | var Rmq *RabbitMQ 17 | 18 | // InitRabbitMQ 初始化RabbitMQ的连接和通道。 19 | func InitRabbitMQ() { 20 | 21 | Rmq = &RabbitMQ{ 22 | mqurl: MQURL, 23 | } 24 | dial, err := amqp.Dial(Rmq.mqurl) 25 | Rmq.failOnErr(err, "创建连接失败") 26 | Rmq.conn = dial 27 | 28 | } 29 | 30 | // 连接出错时,输出错误信息。 31 | func (r *RabbitMQ) failOnErr(err error, message string) { 32 | if err != nil { 33 | log.Fatalf("%s:%s\n", err, message) 34 | panic(fmt.Sprintf("%s:%s\n", err, message)) 35 | } 36 | } 37 | 38 | // 关闭mq通道和mq的连接。 39 | func (r *RabbitMQ) destroy() { 40 | r.conn.Close() 41 | } 42 | -------------------------------------------------------------------------------- /favorite/utils/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "context" 5 | "github.com/go-redis/redis/v8" 6 | ) 7 | 8 | var Ctx = context.Background() 9 | var RdbUserVideo *redis.Client 10 | var RdbVideoId *redis.Client 11 | var RdbUserId *redis.Client 12 | 13 | // InitRedis 初始化Redis连接。 14 | func InitRedis() { 15 | RdbUserVideo = redis.NewClient(&redis.Options{ 16 | Addr: "43.138.51.56:6379", 17 | Password: "292023", 18 | DB: 2, // 是否点赞信息存入 DB2. 19 | }) 20 | RdbVideoId = redis.NewClient(&redis.Options{ 21 | Addr: "43.138.51.56:6379", 22 | Password: "292023", 23 | DB: 1, // 视频信息存入 DB1. 24 | }) 25 | RdbUserId = redis.NewClient(&redis.Options{ 26 | Addr: "43.138.51.56:6379", 27 | Password: "292023", 28 | DB: 0, // 用户信息存入 DB0. 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /feed/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "feed/model" 5 | "fmt" 6 | "gopkg.in/ini.v1" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /feed/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /feed/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "feed/conf" 5 | "feed/core" 6 | service "feed/services" 7 | redis "feed/utils" 8 | "github.com/micro/go-micro/v2" 9 | "github.com/micro/go-micro/v2/registry" 10 | "github.com/micro/go-micro/v2/registry/etcd" 11 | ) 12 | 13 | func main() { 14 | //redis 15 | redis.InitRedis() 16 | conf.Init() 17 | etcdReg := etcd.NewRegistry( 18 | registry.Addrs("127.0.0.1:2379"), 19 | ) 20 | // 得到一个微服务实例 21 | microService := micro.NewService( 22 | micro.Name("rpcFeedService"), // 微服务名字 23 | micro.Address("127.0.0.1:8084"), 24 | micro.Registry(etcdReg), // etcd注册件 25 | micro.Metadata(map[string]string{"protocol": "http"}), 26 | ) 27 | // 结构命令行参数,初始化 28 | microService.Init() 29 | // 服务注册 30 | _ = service.RegisterFeedServiceHandler(microService.Server(), new(core.FeedService)) 31 | // 启动微服务 32 | _ = microService.Run() 33 | 34 | } 35 | -------------------------------------------------------------------------------- /feed/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | // Database 在中间件中初始化mysql链接 14 | func Database(connString string) { 15 | db, err := gorm.Open("mysql", connString) 16 | if err != nil { 17 | panic(err) 18 | } 19 | db.LogMode(true) 20 | if gin.Mode() == "release" { 21 | db.LogMode(false) 22 | } 23 | //默认不加复数 24 | db.SingularTable(true) 25 | //设置连接池 26 | //空闲 27 | db.DB().SetMaxIdleConns(20) 28 | //打开 29 | db.DB().SetMaxOpenConns(100) 30 | //超时 31 | db.DB().SetConnMaxLifetime(time.Second * 30) 32 | DB = db 33 | //migration() 34 | } 35 | -------------------------------------------------------------------------------- /feed/model/video.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | type Video struct { 10 | VideoId int64 `gorm:"primaryKey"` 11 | UserId int64 `gorm:"default:(-)"` 12 | PlayUrl string `gorm:"default:(-)"` 13 | CoverUrl string `gorm:"default:(-)"` 14 | FavoriteCount int64 `gorm:"default:(-)"` 15 | CommentCount int64 `gorm:"default:(-)"` 16 | Title string `gorm:"default:(-)"` 17 | CreateAt time.Time 18 | UpdateAt time.Time 19 | DeleteAt time.Time 20 | } 21 | 22 | func (Video) TableName() string { 23 | return "video" 24 | } 25 | 26 | type VideoDao struct { 27 | } 28 | 29 | var videoDao *VideoDao 30 | var videoOnce sync.Once //单例模式,只生成一个VideoDao实例,提高性能 31 | 32 | func NewVideoDaoInstance() *VideoDao { 33 | videoOnce.Do( 34 | func() { 35 | videoDao = &VideoDao{} 36 | }) 37 | return videoDao 38 | } 39 | 40 | /** 41 | 根据videoid,查找video实体 42 | */ 43 | func (d *VideoDao) FindVideoById(id int64) (*Video, error) { 44 | video := Video{VideoId: id} 45 | 46 | result := DB.Where("Video_id = ?", id).First(&video) 47 | err := result.Error 48 | if err != nil { 49 | return nil, err 50 | } 51 | return &video, err 52 | } 53 | 54 | //根据UserId,查出Video列表 55 | func (*VideoDao) QueryVideoByUserId(userId int64) ([]*Video, error) { 56 | var videos []*Video 57 | err := DB.Where("user_id = ?", userId).Find(&videos).Error 58 | if err != nil { 59 | fmt.Println("查询Video列表失败") 60 | return nil, err 61 | } 62 | return videos, nil 63 | } 64 | 65 | //根据时间和需要查询的条数,获取video列表 66 | func (*VideoDao) QueryVideo(date *string, limit int) []*Video { 67 | fmt.Println(*date) 68 | var VideoList []*Video 69 | DB.Where("create_at < ?", *date).Order("create_at desc").Find(&VideoList) 70 | if len(VideoList) <= limit { 71 | fmt.Println(VideoList) 72 | return VideoList 73 | } 74 | fmt.Println(VideoList) 75 | return VideoList[0:limit] 76 | } 77 | -------------------------------------------------------------------------------- /feed/rpc_server/FavoriteRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "feed/rpc_server/etcd" 6 | services "feed/services/favorite_to_video_proto" 7 | "fmt" 8 | "github.com/micro/go-micro/v2" 9 | ) 10 | 11 | func GetFavoriteStatus(videoId int64, userId int64) (bool, error) { 12 | //// 服务调用实例 13 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 14 | Service := services.NewToVideoService("rpcFavoriteService", MicroService.Client()) 15 | 16 | var req services.GetFavoriteStatus_Request 17 | req.VideoId = videoId 18 | req.UserId = userId 19 | 20 | resp, err := Service.GetFavoriteStatus(context.TODO(), &req) 21 | 22 | if err != nil { 23 | fmt.Println(err) 24 | } 25 | return resp.IsFavorite, err 26 | } 27 | 28 | /** 29 | 调用favorite服务,批量查询是否点赞接口 30 | */ 31 | func GetFavoritesStatus(isFavorites []*services.FavoriteStatus) ([]*services.FavoriteStatus, error) { 32 | //// 服务调用实例 33 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 34 | Service := services.NewToVideoService("rpcFavoriteService", MicroService.Client()) 35 | 36 | var req services.GetFavoritesStatus_Request 37 | 38 | req.FavoriteStatus = isFavorites 39 | //req.Token = token 40 | 41 | resp, err := Service.GetFavoritesStatus(context.TODO(), &req) 42 | if err != nil { 43 | fmt.Println(err) 44 | } 45 | return resp.IsFavorite, err 46 | } 47 | -------------------------------------------------------------------------------- /feed/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "feed/rpc_server/etcd" 6 | tokenproto "feed/services/tokenproto" 7 | "fmt" 8 | "github.com/micro/go-micro/v2" 9 | ) 10 | 11 | func GetIdByToken(token string) (int64, error) { 12 | //etcdReg := etcd.NewRegistry( 13 | // registry.Addrs("127.0.0.1:2379"), 14 | //) 15 | //// 服务调用实例 16 | 17 | //tokenMicroService := micro.NewService(micro.Name("tokenService.client"), micro.Registry(etcdReg)) 18 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 19 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) //client.DefaultClient 20 | 21 | var req tokenproto.GetIdByTokenRequest 22 | 23 | req.UserToken = token 24 | 25 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 26 | if err != nil { 27 | fmt.Println(err) 28 | } 29 | return int64(resp.UserId), err 30 | } 31 | -------------------------------------------------------------------------------- /feed/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /feed/rpc_server/userRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "feed/rpc_server/etcd" 6 | usersproto "feed/services/to_relation" 7 | userproto "feed/services/userproto" 8 | "fmt" 9 | "github.com/micro/go-micro/v2" 10 | ) 11 | 12 | func GetUserInfo(userId int64, token string) (*userproto.User, error) { 13 | 14 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 15 | userService := userproto.NewUserService("rpcUserService", userMicroService.Client()) 16 | 17 | var req userproto.DouyinUserRequest 18 | req.UserId = userId 19 | req.Token = token 20 | 21 | resp, err := userService.UserInfo(context.TODO(), &req) 22 | if err != nil { 23 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 24 | fmt.Println(err) 25 | } 26 | 27 | user := &userproto.User{ 28 | Id: resp.User.Id, 29 | Name: resp.User.Name, 30 | FollowCount: resp.User.FollowCount, 31 | FollowerCount: resp.User.FollowerCount, 32 | IsFollow: resp.User.IsFollow, 33 | } 34 | return user, err 35 | } 36 | 37 | /** 38 | 输入userId列表,查询User实体列表 39 | */ 40 | func GetUsersInfo(userId []int64, token string) ([]*usersproto.User, error) { 41 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 42 | usersService := usersproto.NewToRelationService("rpcUserService", userMicroService.Client()) 43 | 44 | var req usersproto.GetUsersByIdsRequest 45 | 46 | req.UserId = userId 47 | req.Token = token 48 | 49 | resp, err := usersService.GetUsersByIds(context.TODO(), &req) 50 | if err != nil { 51 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 52 | fmt.Println(err) 53 | } 54 | 55 | return resp.UserList, err 56 | } 57 | -------------------------------------------------------------------------------- /feed/services/feed.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: feed.proto 3 | 4 | package services 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for FeedService service 37 | 38 | func NewFeedServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for FeedService service 43 | 44 | type FeedService interface { 45 | Feed(ctx context.Context, in *DouyinFeedRequest, opts ...client.CallOption) (*DouyinFeedResponse, error) 46 | } 47 | 48 | type feedService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewFeedService(name string, c client.Client) FeedService { 54 | return &feedService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *feedService) Feed(ctx context.Context, in *DouyinFeedRequest, opts ...client.CallOption) (*DouyinFeedResponse, error) { 61 | req := c.c.NewRequest(c.name, "FeedService.Feed", in) 62 | out := new(DouyinFeedResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for FeedService service 71 | 72 | type FeedServiceHandler interface { 73 | Feed(context.Context, *DouyinFeedRequest, *DouyinFeedResponse) error 74 | } 75 | 76 | func RegisterFeedServiceHandler(s server.Server, hdlr FeedServiceHandler, opts ...server.HandlerOption) error { 77 | type feedService interface { 78 | Feed(ctx context.Context, in *DouyinFeedRequest, out *DouyinFeedResponse) error 79 | } 80 | type FeedService struct { 81 | feedService 82 | } 83 | h := &feedServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&FeedService{h}, opts...)) 85 | } 86 | 87 | type feedServiceHandler struct { 88 | FeedServiceHandler 89 | } 90 | 91 | func (h *feedServiceHandler) Feed(ctx context.Context, in *DouyinFeedRequest, out *DouyinFeedResponse) error { 92 | return h.FeedServiceHandler.Feed(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /feed/services/protos/feed.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;feed"; 4 | 5 | message DouyinFeedRequest { 6 | // @gotags: json:"latest_time" 7 | int64 LatestTime = 1; // 可选参数,限制返回视频的最新投稿时间戳,精确到秒,不填表示当前时间 8 | // @gotags: json:"token" 9 | string Token = 2; // 可选参数,登录用户设置 10 | } 11 | 12 | message DouyinFeedResponse { 13 | // @gotags: json:"status_code" 14 | int32 StatusCode = 1; // 状态码,0-成功,其他值-失败 15 | // @gotags: json:"status_msg" 16 | string StatusMsg = 2; // 返回状态描述 17 | // @gotags: json:"video_list" 18 | repeated Video VideoList = 3; // 视频列表 19 | // @gotags: json:"next_time" 20 | int64 NextTime = 4; // 本次返回的视频中,发布最早的时间,作为下次请求时的latest_time 21 | } 22 | 23 | message Video { 24 | // @gotags: json:"id" 25 | int64 Id = 1; // 视频唯一标识 26 | // @gotags: json:"author" 27 | User Author = 2; // 视频作者信息 28 | // @gotags: json:"play_url" 29 | string PlayUrl = 3; // 视频播放地址 30 | // @gotags: json:"cover_url" 31 | string CoverUrl = 4; // 视频封面地址 32 | // @gotags: json:"favorite_count" 33 | int64 FavoriteCount = 5; // 视频的点赞总数 34 | // @gotags: json:"comment_count" 35 | int64 CommentCount = 6; // 视频的评论总数 36 | // @gotags: json:"is_favorite" 37 | bool IsFavorite = 7; // true-已点赞,false-未点赞 38 | // @gotags: json:"title" 39 | string Title = 8; // 视频标题 40 | } 41 | 42 | message User { 43 | // @gotags: json:"id" 44 | int64 Id = 1; // 用户id 45 | // @gotags: json:"name" 46 | string Name = 2; // 用户名称 47 | // @gotags: json:"follow_count" 48 | int64 FollowCount = 3; // 关注总数 49 | // @gotags: json:"follower_count" 50 | int64 FollowerCount = 4; // 粉丝总数 51 | // @gotags: json:"is_follow" 52 | bool IsFollow = 5; // true-已关注,false-未关注 53 | // @gotags: json:"avatar" 54 | string Avatar = 6; //用户头像 55 | // @gotags: json:"background_image" 56 | string BackgroundImage = 7; //用户个人页顶部大图 57 | // @gotags: json:"signature" 58 | string Signature = 8; //个人简介 59 | // @gotags: json:"total_favorited" 60 | int64 TotalFavorited = 9; //获赞数量 61 | // @gotags: json:"work_count" 62 | int64 WorkCount = 10; //作品数量 63 | // @gotags: json:"favorite_count" 64 | int64 FavoriteCount = 11; //点赞数量 65 | } 66 | 67 | service FeedService{ 68 | rpc Feed(DouyinFeedRequest) returns (DouyinFeedResponse); 69 | } -------------------------------------------------------------------------------- /feed/services/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /feed/utils/redis.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "github.com/go-redis/redis/v8" 6 | ) 7 | 8 | var Ctx = context.Background() 9 | var RdbVideoId *redis.Client 10 | 11 | // InitRedis 初始化Redis连接。 12 | func InitRedis() { 13 | 14 | RdbVideoId = redis.NewClient(&redis.Options{ 15 | Addr: "43.138.51.56:6379", 16 | Password: "292023", 17 | DB: 1, // 视频信息存入 DB1. 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /message/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "fmt" 5 | "github.com/go-ini/ini" 6 | "message/model" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /message/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /message/core/MessageService.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "message/model" 7 | "message/rpc_server" 8 | proto "message/service" 9 | "strconv" 10 | "time" 11 | ) 12 | 13 | type MessageService struct { 14 | } 15 | 16 | /** 17 | 消息列表 18 | */ 19 | func (*MessageService) MessageList(ctx context.Context, in *proto.DouyinMessageChatRequest, out *proto.DouyinMessageChatResponse) error { 20 | fmt.Println("调用了消息列表功能") 21 | //1.判断一下token失效了吗,调用rpc_server的 GetIdByToken 方法,从token中解析出userId 22 | //解析token 23 | if in.Token == "" { 24 | out.StatusCode = -1 25 | out.StatusMsg = "登录失效,请重新登录" 26 | return nil 27 | } 28 | userId, err := rpc_server.GetIdByToken(in.Token) //当前用户id 29 | if err != nil { 30 | out.StatusCode = -1 31 | out.StatusMsg = "登录失效,请重新登录" 32 | return nil 33 | } 34 | 35 | toUserId := in.ToUserId //对方用户id 36 | lastTime := in.PreMsgTime //上次最新消息时间,毫秒。 37 | format := "2006-01-02 15:04:05" 38 | t := time.Unix(lastTime/1000, 0) 39 | searchTime := t.Format(format) //转化完的时间,可以去数据库查的数据 40 | 41 | var messageList []*model.Message //查出来的数据库列表 42 | var resultList []*proto.Message 43 | messageList = model.NewMessageDaoInstance().QueryMessageList(&searchTime, userId, toUserId) 44 | for _, message := range messageList { 45 | resultList = append(resultList, BuildProtoMessage(message)) 46 | } 47 | 48 | out.MessageList = resultList 49 | out.StatusMsg = "查询消息成功" 50 | out.StatusCode = 0 51 | return nil 52 | } 53 | 54 | /** 55 | 发送消息 56 | */ 57 | func (*MessageService) MessageAction(ctx context.Context, in *proto.DouyinMessageActionRequest, out *proto.DouyinMessageActionResponse) error { 58 | fmt.Println("调用了发消息功能") 59 | //1.判断一下token失效了吗,调用rpc_server的 GetIdByToken 方法,从token中解析出userId 60 | //解析token 61 | if in.Token == "" { 62 | out.StatusCode = -1 63 | out.StatusMsg = "登录失效,请重新登录" 64 | return nil 65 | } 66 | userId, err := rpc_server.GetIdByToken(in.Token) //当前用户id 67 | if err != nil { 68 | out.StatusCode = -1 69 | out.StatusMsg = "登录失效,请重新登录" 70 | return nil 71 | } 72 | message := model.Message{ 73 | FromUserId: userId, 74 | ToUserId: in.ToUserId, 75 | Content: in.Content, 76 | CreateAt: time.Now(), 77 | } 78 | _ = model.NewMessageDaoInstance().CreateMessage(&message) 79 | 80 | out.StatusMsg = "发消息成功" 81 | out.StatusCode = 0 82 | return nil 83 | } 84 | 85 | func BuildProtoMessage(message *model.Message) *proto.Message { 86 | return &proto.Message{ 87 | Id: message.Id, 88 | ToUserId: message.ToUserId, 89 | FromUserId: message.FromUserId, 90 | Content: message.Content, 91 | CreateTime: strconv.FormatInt(message.CreateAt.UnixNano()/1e6, 10), 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /message/core/to_relation/ToRelationService.go: -------------------------------------------------------------------------------- 1 | package to_relation 2 | 3 | import ( 4 | "context" 5 | "message/model" 6 | "message/service/to_relation" 7 | ) 8 | 9 | type ToRelationService struct { 10 | } 11 | 12 | func (*ToRelationService) QueryMessagesByUsers(ctx context.Context, in *to_relation.QueryMessagesByUsersRequest, out *to_relation.QueryMessagesByUsersResponse) error { 13 | var resultQueryBody []*to_relation.QueryBody 14 | for _, querybody := range in.QueryBody { 15 | query_body_temp := model.NewMessageDaoInstance().QueryMessage(querybody.ToUserId, querybody.FromUserId) 16 | resultQueryBody = append(resultQueryBody, query_body_temp) 17 | } 18 | out.StatusCode = 0 19 | out.QueryBody = resultQueryBody 20 | return nil 21 | } 22 | -------------------------------------------------------------------------------- /message/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2" 5 | "github.com/micro/go-micro/v2/registry" 6 | "github.com/micro/go-micro/v2/registry/etcd" 7 | "message/core" 8 | "message/core/to_relation" 9 | proto "message/service" 10 | to_relation_proto "message/service/to_relation" 11 | ) 12 | 13 | func main() { 14 | 15 | // etcd注册件 16 | etcdReg := etcd.NewRegistry( 17 | registry.Addrs("127.0.0.1:2379"), 18 | ) 19 | // 得到一个微服务实例 20 | microService := micro.NewService( 21 | micro.Name("rpcMessageService"), // 微服务名字 22 | micro.Address("127.0.0.1:8091"), 23 | micro.Registry(etcdReg), // etcd注册件 24 | micro.Metadata(map[string]string{"protocol": "http"}), 25 | ) 26 | 27 | // 结构命令行参数,初始化 28 | microService.Init() 29 | // 服务注册 30 | _ = proto.RegisterMessageServiceHandler(microService.Server(), new(core.MessageService)) 31 | _ = to_relation_proto.RegisterToRelationServiceHandler(microService.Server(), new(to_relation.ToRelationService)) 32 | // 启动微服务 33 | 34 | _ = microService.Run() 35 | 36 | } 37 | -------------------------------------------------------------------------------- /message/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | func init() { 14 | DB, _ = gorm.Open("mysql", "root:jhr292023@tcp(43.138.51.56:3306)/simple-douyin?charset=utf8&parseTime=True&loc=Local") 15 | } 16 | 17 | // Database 在中间件中初始化mysql链接 18 | func Database(connString string) { 19 | db, err := gorm.Open("mysql", connString) 20 | if err != nil { 21 | panic(err) 22 | } 23 | db.LogMode(true) 24 | if gin.Mode() == "release" { 25 | db.LogMode(false) 26 | } 27 | //默认不加复数 28 | db.SingularTable(true) 29 | //设置连接池 30 | //空闲 31 | db.DB().SetMaxIdleConns(20) 32 | //打开 33 | db.DB().SetMaxOpenConns(100) 34 | //超时 35 | db.DB().SetConnMaxLifetime(time.Second * 30) 36 | DB = db 37 | //migration() 38 | } 39 | -------------------------------------------------------------------------------- /message/model/message.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "gorm.io/gorm" 6 | "message/service/to_relation" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | type Message struct { 12 | Id int64 `gorm:"primary_key"` 13 | FromUserId int64 14 | ToUserId int64 15 | Content string 16 | CreateAt time.Time 17 | DeletedAt gorm.DeletedAt 18 | } 19 | 20 | func (Message) TableName() string { 21 | return "message" 22 | } 23 | 24 | type MessageDao struct { 25 | } 26 | 27 | var messageDao *MessageDao 28 | var messageOnce sync.Once //单例模式,只生成一个commentDao实例,提高性能 29 | 30 | func NewMessageDaoInstance() *MessageDao { 31 | messageOnce.Do( 32 | func() { 33 | messageDao = &MessageDao{} 34 | }) 35 | return messageDao 36 | } 37 | 38 | /** 39 | 创建一条消息 40 | */ 41 | func (*MessageDao) CreateMessage(message *Message) error { 42 | //和数据库进行操作 43 | result := DB.Create(&message) 44 | 45 | if result.Error != nil { 46 | return result.Error 47 | } 48 | return nil 49 | } 50 | 51 | /** 52 | 查询消息记录 53 | */ 54 | //根据时间和需要查询的条数,获取video列表 55 | func (*MessageDao) QueryMessageList(date *string, fromUserId int64, ToUserId int64) []*Message { 56 | fmt.Println(*date) 57 | var MessageList []*Message 58 | DB.Where("( (from_user_id = ? and to_user_id = ?) or (from_user_id = ? and to_user_id = ?) ) and create_at > ?", fromUserId, ToUserId, ToUserId, fromUserId, date).Order("create_at asc").Find(&MessageList) 59 | 60 | fmt.Println(MessageList) 61 | return MessageList 62 | } 63 | 64 | /** 65 | 66 | */ 67 | func (d *MessageDao) QueryMessage(toUserId int64, FromUserId int64) *to_relation.QueryBody { 68 | message := Message{} 69 | var msgType int64 70 | err := DB.Model(&Message{}).Where("(to_user_id=? and from_user_id=?) or (to_user_id=? and from_user_id=?)", toUserId, FromUserId, FromUserId, toUserId).Order("create_at desc").First(&message).Error 71 | if err != nil { //没查到,first会报个错 72 | return &to_relation.QueryBody{ 73 | FromUserId: FromUserId, 74 | ToUserId: toUserId, 75 | Message: &to_relation.Message{}, 76 | MsgType: 0, 77 | } 78 | } 79 | if FromUserId == message.FromUserId { 80 | msgType = 1 81 | } else { 82 | msgType = 0 83 | } 84 | 85 | return &to_relation.QueryBody{ 86 | FromUserId: FromUserId, 87 | ToUserId: toUserId, 88 | Message: &to_relation.Message{ 89 | Id: message.Id, 90 | Content: message.Content, 91 | }, 92 | MsgType: msgType, 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /message/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "message/rpc_server/etcd" 8 | tokenproto "message/service/tokenproto" 9 | ) 10 | 11 | /** 12 | 调用token解析 13 | */ 14 | func GetIdByToken(token string) (int64, error) { 15 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 16 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) 17 | 18 | var req tokenproto.GetIdByTokenRequest 19 | 20 | req.UserToken = token 21 | 22 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 23 | if err != nil { 24 | fmt.Println(err) 25 | } 26 | return int64(resp.UserId), err 27 | } 28 | -------------------------------------------------------------------------------- /message/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /message/service/proto/message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message douyin_message_chat_request { 6 | string token = 1; // 用户鉴权token 7 | int64 to_user_id = 2; // 对方用户id 8 | int64 pre_msg_time=3;//上次最新消息的时间(新增字段-apk更新中) 9 | } 10 | 11 | message douyin_message_chat_response { 12 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 13 | string status_msg = 2; // 返回状态描述 14 | repeated Message message_list = 3; // 消息列表 15 | } 16 | 17 | message Message { 18 | int64 id = 1; // 消息id 19 | int64 to_user_id = 2; // 该消息接收者的id 20 | int64 from_user_id =3; // 该消息发送者的id 21 | string content = 4; // 消息内容 22 | string create_time = 5; // 消息创建时间 23 | } 24 | 25 | message douyin_message_action_request { 26 | string token = 1; // 用户鉴权token 27 | int64 to_user_id = 2; // 对方用户id 28 | int32 action_type = 3; // 1-发送消息 29 | string content = 4; // 消息内容 30 | } 31 | 32 | message douyin_message_action_response { 33 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 34 | string status_msg = 2; // 返回状态描述 35 | } 36 | 37 | service MessageService{ 38 | rpc MessageList(douyin_message_chat_request) returns (douyin_message_chat_response); //聊天记录 39 | rpc MessageAction(douyin_message_action_request) returns(douyin_message_action_response); //发送消息 40 | } -------------------------------------------------------------------------------- /message/service/proto/to_relation/to_relation.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message query_messages_by_users_request { 6 | repeated QueryBody queryBody = 1; 7 | } 8 | 9 | message query_messages_by_users_response { 10 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 11 | repeated QueryBody queryBody = 2; 12 | } 13 | 14 | message QueryBody { 15 | int64 from_user_id = 1;// 登录用户 16 | int64 to_user_id = 2 ;//登录用户的好友 17 | Message message = 3 ;//这两个人的最新消息 18 | int64 msgType = 4; //message消息的类型,0 => 当前请求用户接收的消息, 1 => 当前请求用户发送的消息 19 | } 20 | 21 | 22 | message Message { 23 | int64 id = 1; // 消息id 24 | int64 to_user_id = 2; // 该消息接收者的id 25 | int64 from_user_id =3; // 该消息发送者的id 26 | string content = 4; // 消息内容 27 | string create_time = 5; // 消息创建时间 28 | } 29 | 30 | service ToRelationService{ 31 | rpc QueryMessagesByUsers(query_messages_by_users_request) returns (query_messages_by_users_response); //根据一组user,查一组最新消息 32 | } -------------------------------------------------------------------------------- /message/service/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /publish/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "fmt" 5 | "gopkg.in/ini.v1" 6 | "publish/model" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /publish/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin 12 | 13 | [OSS] 14 | endpoint = oss-cn-hangzhou.aliyuncs.com 15 | accessKeyID = LTAI5t8K2KtWjUGnwek7BmSn 16 | accessKeySecret = yMhZfvo165xVG0ILQMLQboU1G0iYZl 17 | bucketName = simple-douyin-1122233 18 | -------------------------------------------------------------------------------- /publish/core/to_comment/toCommentService.go: -------------------------------------------------------------------------------- 1 | package to_comment 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "publish/model" 7 | proto "publish/services/to_comment" 8 | ) 9 | 10 | type ToCommentService struct { 11 | } 12 | 13 | /** 14 | 给Comment微服务调用,更新视频表的评论数。 15 | req携带的参数:videoId 视频id count 增加或者减少的数字 type 1增加2减少 16 | */ 17 | func (ToCommentService) UpdateCommentCount(ctx context.Context, req *proto.UpdateCommentCountRequest, resp *proto.UpdateCommentCountResponse) error { 18 | if req.VideoId <= 0 || (req.Type != 1 && req.Type != 2) { 19 | resp.StatusCode = -1 20 | return errors.New("传入的videoId或者type有误") 21 | } 22 | //查一下,这个videoId能否查到,查不到报错,查到了返回count 23 | if _, err := model.NewVideoDaoInstance().FindVideoById(req.VideoId); err != nil { 24 | return errors.New("传入的VideoId查不到") 25 | } 26 | //调用数据库的修改功能 27 | if req.Type == 1 { 28 | //增加 29 | model.NewVideoDaoInstance().AddCommentCount(req.VideoId, req.Count) 30 | } else if req.Type == 2 { 31 | //减少 32 | model.NewVideoDaoInstance().ReduceCommentCount(req.VideoId, req.Count) 33 | } 34 | 35 | resp.StatusCode = 0 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /publish/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2" 5 | "github.com/micro/go-micro/v2/registry" 6 | "github.com/micro/go-micro/v2/registry/etcd" 7 | "publish/conf" 8 | "publish/core" 9 | toComment "publish/core/to_comment" 10 | toFavorite "publish/core/tofavorite" 11 | "publish/services" 12 | protoToComment "publish/services/to_comment" 13 | protoToFavorite "publish/services/to_favorite" 14 | redis "publish/utils" 15 | ) 16 | 17 | func main() { 18 | conf.Init() 19 | //redis 20 | redis.InitRedis() 21 | // etcd注册件 22 | etcdReg := etcd.NewRegistry( 23 | registry.Addrs("127.0.0.1:2379"), 24 | ) 25 | // 得到一个微服务实例 26 | microService := micro.NewService( 27 | micro.Name("rpcPublishService"), // 微服务名字 28 | micro.Address("127.0.0.1:8083"), 29 | micro.Registry(etcdReg), // etcd注册件 30 | micro.Metadata(map[string]string{"protocol": "http"}), 31 | ) 32 | // 结构命令行参数,初始化 33 | microService.Init() 34 | // 服务注册 35 | _ = services.RegisterPublishServiceHandler(microService.Server(), new(core.PublishService)) 36 | _ = protoToFavorite.RegisterToFavoriteServiceHandler(microService.Server(), new(toFavorite.ToFavoriteService)) 37 | _ = protoToComment.RegisterToCommentServiceHandler(microService.Server(), new(toComment.ToCommentService)) 38 | // 启动微服务 39 | _ = microService.Run() 40 | } 41 | -------------------------------------------------------------------------------- /publish/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | // Database 在中间件中初始化mysql链接 14 | func Database(connString string) { 15 | db, err := gorm.Open("mysql", connString) 16 | if err != nil { 17 | panic(err) 18 | } 19 | db.LogMode(true) 20 | if gin.Mode() == "release" { 21 | db.LogMode(false) 22 | } 23 | //默认不加复数 24 | db.SingularTable(true) 25 | //设置连接池 26 | //空闲 27 | db.DB().SetMaxIdleConns(20) 28 | //打开 29 | db.DB().SetMaxOpenConns(100) 30 | //超时 31 | db.DB().SetConnMaxLifetime(time.Second * 30) 32 | DB = db 33 | //migration() 34 | } 35 | -------------------------------------------------------------------------------- /publish/model/video.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "github.com/jinzhu/gorm" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | type Video struct { 11 | VideoId int64 `gorm:"primaryKey"` 12 | UserId int64 `gorm:"default:(-)"` 13 | PlayUrl string `gorm:"default:(-)"` 14 | CoverUrl string `gorm:"default:(-)"` 15 | FavoriteCount int64 `gorm:"default:(-)"` 16 | CommentCount int64 `gorm:"default:(-)"` 17 | Title string `gorm:"default:(-)"` 18 | CreateAt time.Time 19 | UpdateAt time.Time 20 | DeleteAt time.Time 21 | } 22 | 23 | func (Video) TableName() string { 24 | return "video" 25 | } 26 | 27 | type VideoDao struct { 28 | } 29 | 30 | var videoDao *VideoDao 31 | var videoOnce sync.Once //单例模式,只生成一个VideoDao实例,提高性能 32 | 33 | func NewVideoDaoInstance() *VideoDao { 34 | videoOnce.Do( 35 | func() { 36 | videoDao = &VideoDao{} 37 | }) 38 | return videoDao 39 | } 40 | 41 | /** 42 | 根据创建一个新的Video,返回Video实例 43 | */ 44 | func (*VideoDao) CreateVideo(video *Video) (*Video, error) { 45 | /*Video := Video{Name: Videoname, Password: password, FollowingCount: 0, FollowerCount: 0, CreateAt: time.Now()}*/ 46 | 47 | result := DB.Create(&video) 48 | 49 | if result.Error != nil { 50 | return nil, result.Error 51 | } 52 | 53 | return video, nil 54 | } 55 | 56 | //根据UserId,查出Video列表 57 | func (*VideoDao) QueryVideoByUserId(userId int64) ([]*Video, error) { 58 | var videos []*Video 59 | err := DB.Where("user_id = ?", userId).Find(&videos).Error 60 | if err != nil { 61 | fmt.Println("查询Video列表失败") 62 | return nil, err 63 | } 64 | return videos, nil 65 | } 66 | 67 | //comment 68 | //传入视频id,增加cnt条评论数 69 | func (*VideoDao) AddCommentCount(videoId int64, cnt int32) { 70 | err := DB.Model(&Video{}).Where("video_id=?", videoId).Update("comment_count", gorm.Expr("comment_count+?", cnt)).Error 71 | if err != nil { 72 | //log.Error(err) 73 | } 74 | } 75 | 76 | //传入视频id,减少cnt条评论数 77 | func (*VideoDao) ReduceCommentCount(videoId int64, cnt int32) { 78 | err := DB.Model(Video{}).Where("video_id=?", videoId).Update("comment_count", gorm.Expr("comment_count-?", cnt)).Error 79 | if err != nil { 80 | } 81 | } 82 | 83 | //favorite 84 | //传入视频id,增加cnt条点赞数 85 | func (*VideoDao) AddFavoriteCount(videoId int64, cnt int32) { 86 | err := DB.Model(Video{}).Where("video_id=?", videoId).Update("favorite_count", gorm.Expr("favorite_count+?", cnt)).Error 87 | if err != nil { 88 | //log.Error(err) 89 | } 90 | } 91 | 92 | //传入视频id,减少cnt条点赞数 93 | func (*VideoDao) ReduceFavoriteCount(videoId int64, cnt int32) { 94 | err := DB.Model(Video{}).Where("video_id=?", videoId).Update("favorite_count", gorm.Expr("favorite_count-?", cnt)).Error 95 | if err != nil { 96 | } 97 | } 98 | 99 | /** 100 | 根据videoid,查找视频实体 101 | */ 102 | func (d *VideoDao) FindVideoById(videoId int64) (*Video, error) { 103 | video := Video{VideoId: videoId} 104 | 105 | result := DB.Where("video_id = ?", videoId).First(&video) 106 | err := result.Error 107 | if err != nil { 108 | return nil, err 109 | } 110 | return &video, err 111 | } 112 | 113 | /** 114 | 根据视频id集,获取video实体集 115 | */ 116 | func (*VideoDao) GetVideosByIds(videoIds []int64) ([]*Video, error) { 117 | var videos []*Video 118 | 119 | err := DB.Where("video_id IN (?)", videoIds).Find(&videos).Error 120 | if err != nil { 121 | fmt.Println("model层查询Video列表失败") 122 | return nil, err 123 | } 124 | 125 | return videos, nil 126 | } 127 | -------------------------------------------------------------------------------- /publish/rpc_server/FavoriteRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "publish/rpc_server/etcd" 8 | services "publish/services/favorite_to_video_proto" 9 | ) 10 | 11 | /** 12 | 调用favorite服务,是否点赞接口 13 | */ 14 | func GetFavoriteStatus(videoId int64, userId int64) (bool, error) { 15 | //// 服务调用实例 16 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 17 | Service := services.NewToVideoService("rpcFavoriteService", MicroService.Client()) 18 | 19 | var req services.GetFavoriteStatus_Request 20 | 21 | req.VideoId = videoId 22 | req.UserId = userId 23 | 24 | resp, err := Service.GetFavoriteStatus(context.TODO(), &req) 25 | if err != nil { 26 | fmt.Println(err) 27 | } 28 | return resp.IsFavorite, err 29 | } 30 | 31 | /** 32 | 调用favorite服务,批量查询是否点赞接口 33 | */ 34 | func GetFavoritesStatus(isFavorites []*services.FavoriteStatus) ([]*services.FavoriteStatus, error) { 35 | //// 服务调用实例 36 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 37 | Service := services.NewToVideoService("rpcFavoriteService", MicroService.Client()) 38 | 39 | var req services.GetFavoritesStatus_Request 40 | 41 | req.FavoriteStatus = isFavorites 42 | //req.Token = token 43 | 44 | resp, err := Service.GetFavoritesStatus(context.TODO(), &req) 45 | if err != nil { 46 | fmt.Println(err) 47 | } 48 | return resp.IsFavorite, err 49 | } 50 | -------------------------------------------------------------------------------- /publish/rpc_server/FavoriteRpc_test.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "fmt" 5 | services "publish/services/favorite_to_video_proto" 6 | "testing" 7 | ) 8 | 9 | func TestGetFavoritesStatus(t *testing.T) { 10 | var isFavorites []*services.FavoriteStatus 11 | isFavorites = append(isFavorites, &services.FavoriteStatus{UserId: 51, VideoId: 28, IsFavorite: false}) 12 | isFavorites = append(isFavorites, &services.FavoriteStatus{UserId: 54, VideoId: 39, IsFavorite: false}) 13 | isFavorites = append(isFavorites, &services.FavoriteStatus{UserId: 58, VideoId: 6, IsFavorite: false}) 14 | //result, _ := GetUsersInfo(userId, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTEsImV4cCI6MTY3NjExODIxNSwiaXNzIjoiMTEyMjIzMyJ9.WD4uT4aQciCyxq-3kEpIi8XGtUpEDhrx32H6MqkUn2Q") 15 | result, _ := GetFavoritesStatus(isFavorites) 16 | 17 | fmt.Println(result) 18 | } 19 | -------------------------------------------------------------------------------- /publish/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "publish/rpc_server/etcd" 8 | tokenproto "publish/services/tokenproto" 9 | ) 10 | 11 | /** 12 | 调用token解析 13 | */ 14 | func GetIdByToken(token string) (int64, error) { 15 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 16 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) 17 | 18 | var req tokenproto.GetIdByTokenRequest 19 | 20 | req.UserToken = token 21 | 22 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 23 | if err != nil { 24 | fmt.Println(err) 25 | } 26 | return int64(resp.UserId), err 27 | } 28 | -------------------------------------------------------------------------------- /publish/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /publish/rpc_server/userRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "publish/rpc_server/etcd" 8 | from_user_proto "publish/services/from_user" 9 | usersproto "publish/services/to_relation" 10 | userproto "publish/services/userproto" 11 | ) 12 | 13 | /** 14 | 调用user查询用户信息 15 | */ 16 | func GetUserInfo(userId int64, token string) (*userproto.User, error) { 17 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 18 | userService := userproto.NewUserService("rpcUserService", userMicroService.Client()) 19 | 20 | var req userproto.DouyinUserRequest 21 | 22 | req.UserId = userId 23 | req.Token = token 24 | 25 | resp, err := userService.UserInfo(context.TODO(), &req) 26 | if err != nil { 27 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 28 | fmt.Println(err) 29 | } 30 | 31 | user := &userproto.User{ 32 | Id: resp.User.Id, 33 | Name: resp.User.Name, 34 | FollowCount: resp.User.FollowCount, 35 | FollowerCount: resp.User.FollowerCount, 36 | IsFollow: resp.User.IsFollow, 37 | } 38 | return user, err 39 | } 40 | 41 | /** 42 | 输入userId列表,查询User实体列表 43 | */ 44 | func GetUsersInfo(userId []int64, token string) ([]*usersproto.User, error) { 45 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 46 | usersService := usersproto.NewToRelationService("rpcUserService", userMicroService.Client()) 47 | 48 | var req usersproto.GetUsersByIdsRequest 49 | 50 | req.UserId = userId 51 | req.Token = token 52 | 53 | resp, err := usersService.GetUsersByIds(context.TODO(), &req) 54 | if err != nil { 55 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 56 | fmt.Println(err) 57 | } 58 | 59 | return resp.UserList, err 60 | } 61 | 62 | func UpdateWorkCount(uid int64, count int32, actionType int32) bool { 63 | toPublishMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 64 | toPublishService := from_user_proto.NewToPublishService("rpcUserService", toPublishMicroService.Client()) 65 | var req from_user_proto.UpdateWorkCountRequest 66 | req.UserId = uid 67 | req.Count = count 68 | req.Type = actionType 69 | resp, err := toPublishService.UpdateWorkCount(context.TODO(), &req) 70 | if err != nil || resp.StatusCode != 0 { 71 | fmt.Println("work_count维护失败:", err) 72 | return false 73 | } 74 | return true 75 | 76 | } 77 | -------------------------------------------------------------------------------- /publish/rpc_server/userRpc_test.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestGetUsersInfo(t *testing.T) { 9 | var userId []int64 10 | userId = append(userId, 51) 11 | userId = append(userId, 52) 12 | userId = append(userId, 53) 13 | //result, _ := GetUsersInfo(userId, "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTEsImV4cCI6MTY3NjExODIxNSwiaXNzIjoiMTEyMjIzMyJ9.WD4uT4aQciCyxq-3kEpIi8XGtUpEDhrx32H6MqkUn2Q") 14 | result, _ := GetUsersInfo(userId, "") 15 | 16 | fmt.Println(result) 17 | } 18 | -------------------------------------------------------------------------------- /publish/services/from_user/to_publish.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: to_publish.proto 3 | 4 | package services 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for ToPublishService service 37 | 38 | func NewToPublishServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for ToPublishService service 43 | 44 | type ToPublishService interface { 45 | UpdateWorkCount(ctx context.Context, in *UpdateWorkCountRequest, opts ...client.CallOption) (*UpdateWorkCountResponse, error) 46 | } 47 | 48 | type toPublishService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewToPublishService(name string, c client.Client) ToPublishService { 54 | return &toPublishService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *toPublishService) UpdateWorkCount(ctx context.Context, in *UpdateWorkCountRequest, opts ...client.CallOption) (*UpdateWorkCountResponse, error) { 61 | req := c.c.NewRequest(c.name, "ToPublishService.UpdateWorkCount", in) 62 | out := new(UpdateWorkCountResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for ToPublishService service 71 | 72 | type ToPublishServiceHandler interface { 73 | UpdateWorkCount(context.Context, *UpdateWorkCountRequest, *UpdateWorkCountResponse) error 74 | } 75 | 76 | func RegisterToPublishServiceHandler(s server.Server, hdlr ToPublishServiceHandler, opts ...server.HandlerOption) error { 77 | type toPublishService interface { 78 | UpdateWorkCount(ctx context.Context, in *UpdateWorkCountRequest, out *UpdateWorkCountResponse) error 79 | } 80 | type ToPublishService struct { 81 | toPublishService 82 | } 83 | h := &toPublishServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&ToPublishService{h}, opts...)) 85 | } 86 | 87 | type toPublishServiceHandler struct { 88 | ToPublishServiceHandler 89 | } 90 | 91 | func (h *toPublishServiceHandler) UpdateWorkCount(ctx context.Context, in *UpdateWorkCountRequest, out *UpdateWorkCountResponse) error { 92 | return h.ToPublishServiceHandler.UpdateWorkCount(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /publish/services/protos/publish.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;publish"; 4 | 5 | message DouyinPublishListRequest { 6 | // @gotags: json:"user_id" 7 | int64 UserId = 1; // 用户id 8 | // @gotags: json:"token" 9 | string Token = 2; // 用户鉴权token 10 | } 11 | 12 | message DouyinPublishListResponse { 13 | // @gotags: json:"status_code" 14 | int32 StatusCode = 1; // 状态码,0-成功,其他值-失败 15 | // @gotags: json:"status_msg" 16 | string StatusMsg = 2; // 返回状态描述 17 | // @gotags: json:"video_list" 18 | repeated Video VideoList = 3; // 用户发布的视频列表 19 | } 20 | 21 | message Video { 22 | // @gotags: json:"id" 23 | int64 Id = 1; // 视频唯一标识 24 | // @gotags: json:"author" 25 | User Author = 2; // 视频作者信息 26 | // @gotags: json:"play_url" 27 | string PlayUrl = 3; // 视频播放地址 28 | // @gotags: json:"cover_url" 29 | string CoverUrl = 4; // 视频封面地址 30 | // @gotags: json:"favorite_count" 31 | int64 FavoriteCount = 5; // 视频的点赞总数 32 | // @gotags: json:"comment_count" 33 | int64 CommentCount = 6; // 视频的评论总数 34 | // @gotags: json:"is_favorite" 35 | bool IsFavorite = 7; // true-已点赞,false-未点赞 36 | // @gotags: json:"title" 37 | string Title = 8; // 视频标题 38 | } 39 | 40 | message User { 41 | // @gotags: json:"id" 42 | int64 Id = 1; // 用户id 43 | // @gotags: json:"name" 44 | string Name = 2; // 用户名称 45 | // @gotags: json:"follow_count" 46 | int64 FollowCount = 3; // 关注总数 47 | // @gotags: json:"follower_count" 48 | int64 FollowerCount = 4; // 粉丝总数 49 | // @gotags: json:"is_follow" 50 | bool IsFollow = 5; // true-已关注,false-未关注 51 | } 52 | 53 | message DouyinPublishActionRequest { 54 | // @gotags: json:"token" 55 | string Token = 1; // 用户鉴权token 56 | // @gotags: json:"data" 57 | bytes Data = 2; // 视频数据 58 | // @gotags: json:"title" 59 | string Title = 3; // 视频标题 60 | } 61 | 62 | message DouyinPublishActionResponse { 63 | // @gotags: json:"status_code" 64 | int32 StatusCode = 1; // 状态码,0-成功,其他值-失败 65 | // @gotags: json:"status_msg" 66 | string StatusMsg = 2; // 返回状态描述 67 | } 68 | 69 | 70 | 71 | service PublishService{ 72 | rpc PublishList(DouyinPublishListRequest) returns (DouyinPublishListResponse); 73 | rpc Publish(DouyinPublishActionRequest) returns(DouyinPublishActionResponse); 74 | } 75 | -------------------------------------------------------------------------------- /publish/services/protos/to_comment/to_comment.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;service"; 4 | 5 | message UpdateCommentCount_request { 6 | int64 video_id = 1; // 视频id 7 | int32 count = 2;// 增加的数量 8 | int32 type = 3;// 1是增加,2是减少 9 | } 10 | 11 | message UpdateCommentCount_response { 12 | int32 status_code = 1; //响应,成功是0,失败是其他值 13 | } 14 | 15 | service ToCommentService{ 16 | rpc UpdateCommentCount(UpdateCommentCount_request) returns (UpdateCommentCount_response);//增加减少评论数 17 | } 18 | 19 | -------------------------------------------------------------------------------- /publish/services/protos/to_favorite/to_favorite.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;service"; 4 | 5 | message UpdateFavoriteCount_request { 6 | int64 video_id = 1; // 视频id 7 | int32 count = 2;// 增加的数量 8 | int32 type = 3;// 1是增加,2是减少 9 | } 10 | 11 | message UpdateFavoriteCount_response { 12 | int32 status_code = 1; //响应,成功是0,失败是其他值 13 | } 14 | 15 | message GetVideosByIds_request { 16 | repeated int64 video_id = 1; // 视频集合 17 | string token = 2 ; 18 | } 19 | 20 | message GetVideosByIds_response { 21 | int32 status_code = 1; //响应,成功是0,失败是其他值 22 | repeated Video VideoList = 2; //视频集合 23 | } 24 | 25 | message Video { 26 | // @gotags: json:"id" 27 | int64 Id = 1; // 视频唯一标识 28 | // @gotags: json:"author" 29 | User Author = 2; // 视频作者信息 30 | // @gotags: json:"play_url" 31 | string PlayUrl = 3; // 视频播放地址 32 | // @gotags: json:"cover_url" 33 | string CoverUrl = 4; // 视频封面地址 34 | // @gotags: json:"favorite_count" 35 | int64 FavoriteCount = 5; // 视频的点赞总数 36 | // @gotags: json:"comment_count" 37 | int64 CommentCount = 6; // 视频的评论总数 38 | // @gotags: json:"is_favorite" 39 | bool IsFavorite = 7; // true-已点赞,false-未点赞 40 | // @gotags: json:"title" 41 | string Title = 8; // 视频标题 42 | } 43 | 44 | message User { 45 | // @gotags: json:"id" 46 | int64 Id = 1; // 用户id 47 | // @gotags: json:"name" 48 | string Name = 2; // 用户名称 49 | // @gotags: json:"follow_count" 50 | int64 FollowCount = 3; // 关注总数 51 | // @gotags: json:"follower_count" 52 | int64 FollowerCount = 4; // 粉丝总数 53 | // @gotags: json:"is_follow" 54 | bool IsFollow = 5; // true-已关注,false-未关注 55 | } 56 | 57 | service ToFavoriteService{ 58 | rpc UpdateFavoriteCount(UpdateFavoriteCount_request) returns (UpdateFavoriteCount_response);//给视频点赞 59 | rpc GetVideosByIds(GetVideosByIds_request) returns (GetVideosByIds_response);//根据视频id获取视频集合 60 | } 61 | 62 | -------------------------------------------------------------------------------- /publish/services/publish.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: publish.proto 3 | 4 | package services 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for PublishService service 37 | 38 | func NewPublishServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for PublishService service 43 | 44 | type PublishService interface { 45 | PublishList(ctx context.Context, in *DouyinPublishListRequest, opts ...client.CallOption) (*DouyinPublishListResponse, error) 46 | Publish(ctx context.Context, in *DouyinPublishActionRequest, opts ...client.CallOption) (*DouyinPublishActionResponse, error) 47 | } 48 | 49 | type publishService struct { 50 | c client.Client 51 | name string 52 | } 53 | 54 | func NewPublishService(name string, c client.Client) PublishService { 55 | return &publishService{ 56 | c: c, 57 | name: name, 58 | } 59 | } 60 | 61 | func (c *publishService) PublishList(ctx context.Context, in *DouyinPublishListRequest, opts ...client.CallOption) (*DouyinPublishListResponse, error) { 62 | req := c.c.NewRequest(c.name, "PublishService.PublishList", in) 63 | out := new(DouyinPublishListResponse) 64 | err := c.c.Call(ctx, req, out, opts...) 65 | if err != nil { 66 | return nil, err 67 | } 68 | return out, nil 69 | } 70 | 71 | func (c *publishService) Publish(ctx context.Context, in *DouyinPublishActionRequest, opts ...client.CallOption) (*DouyinPublishActionResponse, error) { 72 | req := c.c.NewRequest(c.name, "PublishService.Publish", in) 73 | out := new(DouyinPublishActionResponse) 74 | err := c.c.Call(ctx, req, out, opts...) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return out, nil 79 | } 80 | 81 | // Server API for PublishService service 82 | 83 | type PublishServiceHandler interface { 84 | PublishList(context.Context, *DouyinPublishListRequest, *DouyinPublishListResponse) error 85 | Publish(context.Context, *DouyinPublishActionRequest, *DouyinPublishActionResponse) error 86 | } 87 | 88 | func RegisterPublishServiceHandler(s server.Server, hdlr PublishServiceHandler, opts ...server.HandlerOption) error { 89 | type publishService interface { 90 | PublishList(ctx context.Context, in *DouyinPublishListRequest, out *DouyinPublishListResponse) error 91 | Publish(ctx context.Context, in *DouyinPublishActionRequest, out *DouyinPublishActionResponse) error 92 | } 93 | type PublishService struct { 94 | publishService 95 | } 96 | h := &publishServiceHandler{hdlr} 97 | return s.Handle(s.NewHandler(&PublishService{h}, opts...)) 98 | } 99 | 100 | type publishServiceHandler struct { 101 | PublishServiceHandler 102 | } 103 | 104 | func (h *publishServiceHandler) PublishList(ctx context.Context, in *DouyinPublishListRequest, out *DouyinPublishListResponse) error { 105 | return h.PublishServiceHandler.PublishList(ctx, in, out) 106 | } 107 | 108 | func (h *publishServiceHandler) Publish(ctx context.Context, in *DouyinPublishActionRequest, out *DouyinPublishActionResponse) error { 109 | return h.PublishServiceHandler.Publish(ctx, in, out) 110 | } 111 | -------------------------------------------------------------------------------- /publish/services/to_comment/to_comment.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: to_comment.proto 3 | 4 | package to_comment 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for ToCommentService service 37 | 38 | func NewToCommentServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for ToCommentService service 43 | 44 | type ToCommentService interface { 45 | UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, opts ...client.CallOption) (*UpdateCommentCountResponse, error) 46 | } 47 | 48 | type toCommentService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewToCommentService(name string, c client.Client) ToCommentService { 54 | return &toCommentService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *toCommentService) UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, opts ...client.CallOption) (*UpdateCommentCountResponse, error) { 61 | req := c.c.NewRequest(c.name, "ToCommentService.UpdateCommentCount", in) 62 | out := new(UpdateCommentCountResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for ToCommentService service 71 | 72 | type ToCommentServiceHandler interface { 73 | UpdateCommentCount(context.Context, *UpdateCommentCountRequest, *UpdateCommentCountResponse) error 74 | } 75 | 76 | func RegisterToCommentServiceHandler(s server.Server, hdlr ToCommentServiceHandler, opts ...server.HandlerOption) error { 77 | type toCommentService interface { 78 | UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, out *UpdateCommentCountResponse) error 79 | } 80 | type ToCommentService struct { 81 | toCommentService 82 | } 83 | h := &toCommentServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&ToCommentService{h}, opts...)) 85 | } 86 | 87 | type toCommentServiceHandler struct { 88 | ToCommentServiceHandler 89 | } 90 | 91 | func (h *toCommentServiceHandler) UpdateCommentCount(ctx context.Context, in *UpdateCommentCountRequest, out *UpdateCommentCountResponse) error { 92 | return h.ToCommentServiceHandler.UpdateCommentCount(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /publish/services/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /publish/utils/ffmpeg.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ffmpeg "github.com/u2takey/ffmpeg-go" 7 | "image" 8 | "image/jpeg" 9 | "os" 10 | ) 11 | 12 | // ReadFrameAsJpeg 13 | // 从视频流中截取一帧并返回 需要在本地环境中安装ffmpeg并将bin添加到环境变量 14 | func ReadFrameAsJpeg(filePath string) ([]byte, error) { 15 | reader := bytes.NewBuffer(nil) 16 | err := ffmpeg.Input(filePath). 17 | Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", 1)}). 18 | Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}). 19 | WithOutput(reader, os.Stdout). 20 | Run() 21 | if err != nil { 22 | return nil, err 23 | } 24 | img, _, err := image.Decode(reader) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | buf := new(bytes.Buffer) 30 | jpeg.Encode(buf, img, nil) 31 | 32 | return buf.Bytes(), err 33 | } 34 | -------------------------------------------------------------------------------- /publish/utils/oss.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "github.com/aliyun/aliyun-oss-go-sdk/oss" 7 | "os" 8 | ) 9 | 10 | //将视频上传到阿里云,返回视频地址 11 | func UploadVideo(fileDir string, videobytes []byte) error { 12 | client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "LTAI5t8K2KtWjUGnwek7BmSn", "yMhZfvo165xVG0ILQMLQboU1G0iYZl") 13 | if err != nil { 14 | fmt.Println("Error:", err) 15 | os.Exit(-1) 16 | } 17 | // 填写存储空间名称,例如examplebucket。 18 | bucket, err := client.Bucket("simple-douyin-1122233") 19 | if err != nil { 20 | fmt.Println("Error:", err) 21 | os.Exit(-1) 22 | } 23 | 24 | err = bucket.PutObject(fileDir, bytes.NewReader(videobytes)) 25 | if err != nil { 26 | fmt.Println("Error:", err) 27 | os.Exit(-1) 28 | } 29 | 30 | return err 31 | } 32 | 33 | //将视频封面上传到阿里云,返回视频封面地址 34 | func UploadPicture(fileDir string, picturebytes []byte) error { 35 | // 创建OSSClient实例。 36 | // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。 37 | // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 38 | client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "LTAI5t8K2KtWjUGnwek7BmSn", "yMhZfvo165xVG0ILQMLQboU1G0iYZl") 39 | if err != nil { 40 | fmt.Println("Error:", err) 41 | os.Exit(-1) 42 | } 43 | // 填写存储空间名称,例如examplebucket。 44 | bucket, err := client.Bucket("simple-douyin-1122233") 45 | if err != nil { 46 | fmt.Println("Error:", err) 47 | os.Exit(-1) 48 | } 49 | 50 | err = bucket.PutObject(fileDir, bytes.NewReader(picturebytes)) 51 | if err != nil { 52 | fmt.Println("Error:", err) 53 | os.Exit(-1) 54 | } 55 | return err 56 | } 57 | -------------------------------------------------------------------------------- /publish/utils/redis.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "context" 5 | "github.com/go-redis/redis/v8" 6 | ) 7 | 8 | var Ctx = context.Background() 9 | var RdbVideoId *redis.Client 10 | 11 | // InitRedis 初始化Redis连接。 12 | func InitRedis() { 13 | 14 | RdbVideoId = redis.NewClient(&redis.Options{ 15 | Addr: "43.138.51.56:6379", 16 | Password: "292023", 17 | DB: 1, // 视频信息存入 DB1. 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /relation/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "fmt" 5 | "github.com/go-ini/ini" 6 | "relation/model" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /relation/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /relation/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2" 5 | "github.com/micro/go-micro/v2/registry" 6 | "github.com/micro/go-micro/v2/registry/etcd" 7 | "relation/core" 8 | proto "relation/service" 9 | ) 10 | 11 | func main() { 12 | 13 | // etcd注册件 14 | etcdReg := etcd.NewRegistry( 15 | registry.Addrs("127.0.0.1:2379"), 16 | ) 17 | // 得到一个微服务实例 18 | microService := micro.NewService( 19 | micro.Name("rpcRelationService"), // 微服务名字 20 | micro.Address("127.0.0.1:8090"), 21 | micro.Registry(etcdReg), // etcd注册件 22 | micro.Metadata(map[string]string{"protocol": "http"}), 23 | ) 24 | 25 | // 结构命令行参数,初始化 26 | microService.Init() 27 | // 服务注册 28 | _ = proto.RegisterRelationServiceHandler(microService.Server(), new(core.RelationService)) 29 | // 启动微服务 30 | 31 | _ = microService.Run() 32 | 33 | } 34 | -------------------------------------------------------------------------------- /relation/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | func init() { 14 | DB, _ = gorm.Open("mysql", "root:jhr292023@tcp(43.138.51.56:3306)/simple-douyin?charset=utf8&parseTime=True&loc=Local") 15 | } 16 | 17 | // Database 在中间件中初始化mysql链接 18 | func Database(connString string) { 19 | db, err := gorm.Open("mysql", connString) 20 | if err != nil { 21 | panic(err) 22 | } 23 | db.LogMode(true) 24 | if gin.Mode() == "release" { 25 | db.LogMode(false) 26 | } 27 | //默认不加复数 28 | db.SingularTable(true) 29 | //设置连接池 30 | //空闲 31 | db.DB().SetMaxIdleConns(20) 32 | //打开 33 | db.DB().SetMaxOpenConns(100) 34 | //超时 35 | db.DB().SetConnMaxLifetime(time.Second * 30) 36 | DB = db 37 | //migration() 38 | } 39 | -------------------------------------------------------------------------------- /relation/model/relation.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | type Relation struct { 10 | FollowerId int64 11 | FollowingId int64 12 | CreateAt time.Time 13 | } 14 | 15 | func (Relation) TableName() string { 16 | return "relation" 17 | } 18 | 19 | type RelationDao struct { 20 | } 21 | 22 | func (d RelationDao) CreateRelation(relation *Relation) error { 23 | //和数据库进行操作 24 | result := DB.Create(&relation) 25 | 26 | if result.Error != nil { 27 | return result.Error 28 | } 29 | return nil 30 | } 31 | 32 | func (d RelationDao) DeleteRelation(relation *Relation) error { 33 | err := DB.Where("follower_id=? and following_id=?", relation.FollowerId, relation.FollowingId).Delete(relation).Error 34 | if err != nil { 35 | fmt.Println("取关失败") 36 | return err 37 | } 38 | return nil 39 | } 40 | 41 | func (d RelationDao) QueryFollowingIds(id int64) []int64 { 42 | var Ids []int64 43 | var results []*Relation 44 | DB.Select("follower_id").Where("following_id=?", id).Find(&results) 45 | 46 | for i := 0; i < len(results); i++ { 47 | Ids = append(Ids, results[i].FollowerId) 48 | } 49 | fmt.Println("查询到的关注的人的集合是:") 50 | fmt.Println(Ids) 51 | return Ids 52 | } 53 | 54 | func (d RelationDao) QueryFollowerIds(id int64) []int64 { 55 | var Ids []int64 56 | var results []*Relation 57 | DB.Select("following_id").Where("follower_id=?", id).Find(&results) 58 | for i := 0; i < len(results); i++ { 59 | Ids = append(Ids, results[i].FollowingId) 60 | } 61 | fmt.Println("查询到的粉丝集合是:") 62 | fmt.Println(Ids) 63 | return Ids 64 | } 65 | 66 | func (d RelationDao) QueryFriendIds(userId int64, ids []int64) []int64 { 67 | var Ids []int64 68 | var count int32 69 | for _, id := range ids { 70 | _ = DB.Model(&Relation{}).Where("following_id=? and follower_id=?", id, userId).Count(&count).Error 71 | if count > 0 { 72 | Ids = append(Ids, id) 73 | } 74 | } 75 | fmt.Println("输出一下朋友的id是什么") 76 | fmt.Println(Ids) 77 | return Ids 78 | } 79 | 80 | var relationDao *RelationDao 81 | var relationOnce sync.Once //单例模式,只生成一个commentDao实例,提高性能 82 | 83 | func NewRelationDaoInstance() *RelationDao { 84 | relationOnce.Do( 85 | func() { 86 | relationDao = &RelationDao{} 87 | }) 88 | return relationDao 89 | } 90 | -------------------------------------------------------------------------------- /relation/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "relation/rpc_server/etcd" 8 | tokenproto "relation/service/tokenproto" 9 | ) 10 | 11 | /* 12 | * 13 | 调用token解析 14 | */ 15 | func GetIdByToken(token string) (int64, error) { 16 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 17 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) 18 | 19 | var req tokenproto.GetIdByTokenRequest 20 | 21 | req.UserToken = token 22 | 23 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 24 | if err != nil { 25 | fmt.Println(err) 26 | } 27 | return int64(resp.UserId), err 28 | } 29 | -------------------------------------------------------------------------------- /relation/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /relation/rpc_server/messageRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | etcdInit "relation/rpc_server/etcd" 8 | from_message "relation/service/from_message" 9 | ) 10 | 11 | /* 12 | * 13 | 输入QueryBody列表,查询Message实体列表 14 | */ 15 | func QueryMessagesByUsers(queryBody []*from_message.QueryBody) ([]*from_message.QueryBody, error) { 16 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 17 | Service := from_message.NewToRelationService("rpcMessageService", MicroService.Client()) 18 | 19 | var req from_message.QueryMessagesByUsersRequest 20 | req.QueryBody = queryBody 21 | 22 | resp, err := Service.QueryMessagesByUsers(context.TODO(), &req) 23 | if err != nil { 24 | fmt.Println("调用远程Message服务失败,具体错误如下") 25 | fmt.Println(err) 26 | } 27 | fmt.Println("调用回来了") 28 | fmt.Println(resp.QueryBody) 29 | 30 | return resp.QueryBody, err 31 | } 32 | -------------------------------------------------------------------------------- /relation/rpc_server/userRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "relation/rpc_server/etcd" 8 | usersproto "relation/service/to_relation" 9 | userproto "relation/service/userproto" 10 | ) 11 | 12 | /* 13 | * 14 | 调用user查询用户信息 15 | */ 16 | func GetUserInfo(userId int64, token string) (*userproto.User, error) { 17 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 18 | userService := userproto.NewUserService("rpcUserService", userMicroService.Client()) 19 | 20 | var req userproto.DouyinUserRequest 21 | 22 | req.UserId = userId 23 | req.Token = token 24 | 25 | resp, err := userService.UserInfo(context.TODO(), &req) 26 | if err != nil { 27 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 28 | fmt.Println(err) 29 | } 30 | 31 | user := &userproto.User{ 32 | Id: resp.User.Id, 33 | Name: resp.User.Name, 34 | FollowCount: resp.User.FollowCount, 35 | FollowerCount: resp.User.FollowerCount, 36 | IsFollow: resp.User.IsFollow, 37 | } 38 | return user, err 39 | } 40 | 41 | /* 42 | * 43 | 输入userId列表,查询User实体列表 44 | */ 45 | func GetUsersInfo(userId []int64, token string) ([]*usersproto.User, error) { 46 | userMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 47 | usersService := usersproto.NewToRelationService("rpcUserService", userMicroService.Client()) 48 | 49 | var req usersproto.GetUsersByIdsRequest 50 | 51 | req.UserId = userId 52 | req.Token = token 53 | 54 | resp, err := usersService.GetUsersByIds(context.TODO(), &req) 55 | if err != nil { 56 | fmt.Println("调用远程UserInfo服务失败,具体错误如下") 57 | fmt.Println(err) 58 | } 59 | fmt.Println("调用回来了") 60 | fmt.Println(resp.UserList) 61 | 62 | return resp.UserList, err 63 | } 64 | 65 | /* 66 | * 67 | 更新user表的following_count字段 68 | */ 69 | func UpdateFollowingCount(followId int64, followerId int64, count int32, actionType int32) bool { 70 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 71 | Service := usersproto.NewToRelationService("rpcUserService", MicroService.Client()) 72 | var req usersproto.UpdateFollowingCountRequest 73 | req.UserId = followId 74 | req.Count = count 75 | req.Type = actionType 76 | resp, err := Service.UpdateFollowingCount(context.TODO(), &req) 77 | if err != nil || resp.StatusCode != 0 { 78 | fmt.Println("followingCount维护失败:", err) 79 | return false 80 | } 81 | return true 82 | } 83 | 84 | /* 85 | * 86 | 更新user表的follower_count字段 87 | */ 88 | func UpdateFollowerCount(followId int64, followerId int64, count int32, actionType int32) bool { 89 | MicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 90 | Service := usersproto.NewToRelationService("rpcUserService", MicroService.Client()) 91 | var req usersproto.UpdateFollowerCountRequest 92 | req.UserId = followerId 93 | req.Count = count 94 | req.Type = actionType 95 | resp, err := Service.UpdateFollowerCount(context.TODO(), &req) 96 | if err != nil || resp.StatusCode != 0 { 97 | fmt.Println("followerCount维护失败:", err) 98 | return false 99 | } 100 | return true 101 | } 102 | -------------------------------------------------------------------------------- /relation/service/from_message/to_relation.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: to_relation.proto 3 | 4 | package from_message 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for ToRelationService service 37 | 38 | func NewToRelationServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for ToRelationService service 43 | 44 | type ToRelationService interface { 45 | QueryMessagesByUsers(ctx context.Context, in *QueryMessagesByUsersRequest, opts ...client.CallOption) (*QueryMessagesByUsersResponse, error) 46 | } 47 | 48 | type toRelationService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewToRelationService(name string, c client.Client) ToRelationService { 54 | return &toRelationService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *toRelationService) QueryMessagesByUsers(ctx context.Context, in *QueryMessagesByUsersRequest, opts ...client.CallOption) (*QueryMessagesByUsersResponse, error) { 61 | req := c.c.NewRequest(c.name, "ToRelationService.QueryMessagesByUsers", in) 62 | out := new(QueryMessagesByUsersResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for ToRelationService service 71 | 72 | type ToRelationServiceHandler interface { 73 | QueryMessagesByUsers(context.Context, *QueryMessagesByUsersRequest, *QueryMessagesByUsersResponse) error 74 | } 75 | 76 | func RegisterToRelationServiceHandler(s server.Server, hdlr ToRelationServiceHandler, opts ...server.HandlerOption) error { 77 | type toRelationService interface { 78 | QueryMessagesByUsers(ctx context.Context, in *QueryMessagesByUsersRequest, out *QueryMessagesByUsersResponse) error 79 | } 80 | type ToRelationService struct { 81 | toRelationService 82 | } 83 | h := &toRelationServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&ToRelationService{h}, opts...)) 85 | } 86 | 87 | type toRelationServiceHandler struct { 88 | ToRelationServiceHandler 89 | } 90 | 91 | func (h *toRelationServiceHandler) QueryMessagesByUsers(ctx context.Context, in *QueryMessagesByUsersRequest, out *QueryMessagesByUsersResponse) error { 92 | return h.ToRelationServiceHandler.QueryMessagesByUsers(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /relation/service/proto/relation.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message douyin_relation_action_request { 6 | string token = 1; // 用户鉴权token 7 | int64 to_user_id = 2; // 对方用户id 8 | int32 action_type = 3; // 1-关注,2-取消关注 9 | } 10 | 11 | message douyin_relation_action_response { 12 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 13 | string status_msg = 2; // 返回状态描述 14 | } 15 | 16 | message douyin_relation_follow_list_request { 17 | int64 user_id = 1; // 用户id 18 | string token = 2; // 用户鉴权token 19 | } 20 | 21 | message douyin_relation_follow_list_response { 22 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 23 | string status_msg = 2; // 返回状态描述 24 | repeated User user_list = 3; // 用户信息列表 25 | } 26 | 27 | message douyin_relation_follower_list_request { 28 | int64 user_id = 1; // 用户id 29 | string token = 2; // 用户鉴权token 30 | } 31 | 32 | message douyin_relation_follower_list_response { 33 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 34 | string status_msg = 2; // 返回状态描述 35 | repeated User user_list = 3; // 用户列表 36 | } 37 | 38 | message User { 39 | int64 id = 1; // 用户id 40 | string name = 2; // 用户名称 41 | int64 follow_count = 3; // 关注总数 42 | int64 follower_count = 4; // 粉丝总数 43 | bool is_follow = 5; // true-已关注,false-未关注 44 | string avatar = 6; //用户头像 45 | string background_image = 7; //用户个人页顶部大图 46 | string signature = 8; //个人简介 47 | int64 total_favorited = 9; //获赞数量 48 | int64 work_count = 10; //作品数量 49 | int64 favorite_count = 11; //点赞数量 50 | } 51 | 52 | message douyin_relation_friend_list_request { 53 | int64 user_id = 1; // 用户id 54 | string token = 2; // 用户鉴权token 55 | } 56 | 57 | message douyin_relation_friend_list_response { 58 | int32 status_code = 1; // 状态码,0-成功,其他值-失败 59 | string status_msg = 2; // 返回状态描述 60 | repeated FriendUser user_list = 3; // 用户列表 61 | } 62 | 63 | message FriendUser{ 64 | int64 id = 1; // 用户id 65 | string name = 2; // 用户名称 66 | int64 follow_count = 3; // 关注总数 67 | int64 follower_count = 4; // 粉丝总数 68 | bool is_follow = 5; // true-已关注,false-未关注 69 | string avatar = 6; //用户头像 70 | string background_image = 7; //用户个人页顶部大图 71 | string signature = 8; //个人简介 72 | int64 total_favorited = 9; //获赞数量 73 | int64 work_count = 10; //作品数量 74 | int64 favorite_count = 11; //点赞数量 75 | string message = 12; // 和该好友的最新聊天消息 76 | int64 msgType = 13; // message消息的类型,0 => 当前请求用户接收的消息, 1 => 当前请求用户发送的消息 77 | } 78 | service RelationService{ 79 | rpc RelationAction(douyin_relation_action_request) returns (douyin_relation_action_response); //关注,取消关注 80 | rpc FollowList(douyin_relation_follow_list_request) returns(douyin_relation_follow_list_response); //关注列表 81 | rpc FollowerList(douyin_relation_follower_list_request) returns(douyin_relation_follower_list_response);//粉丝列表 82 | 83 | rpc FriendList( douyin_relation_friend_list_request) returns(douyin_relation_friend_list_response); //好友列表 84 | } -------------------------------------------------------------------------------- /relation/service/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /tokenutils/core/tokenService.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "context" 5 | "github.com/dgrijalva/jwt-go" 6 | "tokenutils/service" 7 | ) 8 | 9 | type TokenService struct { 10 | } 11 | 12 | var jwtSecret = []byte("1122233") 13 | 14 | type Claims struct { 15 | Id int64 `json:"id"` 16 | jwt.StandardClaims 17 | } 18 | 19 | func (*TokenService) GetIdByToken(ctx context.Context, req *service.GetIdByTokenRequest, out *service.GetIdByTokenResponse) error { 20 | token := req.UserToken 21 | token = string(token) 22 | 23 | tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (i interface{}, e error) { return jwtSecret, nil }) 24 | if tokenClaims != nil { 25 | if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { 26 | out.UserId = int32(claims.Id) 27 | return nil 28 | 29 | } 30 | } 31 | return err 32 | 33 | } 34 | -------------------------------------------------------------------------------- /tokenutils/go.mod: -------------------------------------------------------------------------------- 1 | module tokenutils 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 7 | github.com/golang/protobuf v1.5.2 8 | github.com/micro/go-micro/v2 v2.9.1 9 | google.golang.org/protobuf v1.28.1 10 | ) 11 | 12 | require ( 13 | github.com/BurntSushi/toml v0.3.1 // indirect 14 | github.com/bitly/go-simplejson v0.5.0 // indirect 15 | github.com/coreos/etcd v3.3.18+incompatible // indirect 16 | github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect 17 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect 18 | github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect 19 | github.com/emirpasic/gods v1.12.0 // indirect 20 | github.com/fsnotify/fsnotify v1.4.7 // indirect 21 | github.com/ghodss/yaml v1.0.0 // indirect 22 | github.com/go-git/gcfg v1.5.0 // indirect 23 | github.com/go-git/go-billy/v5 v5.0.0 // indirect 24 | github.com/go-git/go-git/v5 v5.1.0 // indirect 25 | github.com/gogo/protobuf v1.2.1 // indirect 26 | github.com/google/uuid v1.1.1 // indirect 27 | github.com/hashicorp/hcl v1.0.0 // indirect 28 | github.com/hpcloud/tail v1.0.0 // indirect 29 | github.com/imdario/mergo v0.3.9 // indirect 30 | github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect 31 | github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect 32 | github.com/micro/cli/v2 v2.1.2 // indirect 33 | github.com/miekg/dns v1.1.27 // indirect 34 | github.com/mitchellh/go-homedir v1.1.0 // indirect 35 | github.com/mitchellh/hashstructure v1.0.0 // indirect 36 | github.com/nats-io/jwt v0.3.2 // indirect 37 | github.com/nats-io/nats.go v1.9.2 // indirect 38 | github.com/nats-io/nkeys v0.1.4 // indirect 39 | github.com/nats-io/nuid v1.0.1 // indirect 40 | github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect 41 | github.com/patrickmn/go-cache v2.1.0+incompatible // indirect 42 | github.com/pkg/errors v0.9.1 // indirect 43 | github.com/russross/blackfriday/v2 v2.0.1 // indirect 44 | github.com/sergi/go-diff v1.1.0 // indirect 45 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect 46 | github.com/xanzy/ssh-agent v0.2.1 // indirect 47 | go.uber.org/atomic v1.5.0 // indirect 48 | go.uber.org/multierr v1.3.0 // indirect 49 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect 50 | go.uber.org/zap v1.13.0 // indirect 51 | golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect 52 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect 53 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 // indirect 54 | golang.org/x/sys v0.0.0-20200523222454-059865788121 // indirect 55 | golang.org/x/text v0.3.2 // indirect 56 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361 // indirect 57 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1 // indirect 58 | google.golang.org/grpc v1.26.0 // indirect 59 | gopkg.in/fsnotify.v1 v1.4.7 // indirect 60 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 61 | gopkg.in/warnings.v0 v0.1.2 // indirect 62 | gopkg.in/yaml.v2 v2.2.4 // indirect 63 | honnef.co/go/tools v0.0.1-2019.2.3 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /tokenutils/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2" 5 | "github.com/micro/go-micro/v2/registry" 6 | "github.com/micro/go-micro/v2/registry/etcd" 7 | "tokenutils/core" 8 | "tokenutils/service" 9 | ) 10 | 11 | func main() { 12 | etcdReg := etcd.NewRegistry( 13 | registry.Addrs("127.0.0.1:2379"), 14 | ) 15 | // 得到一个微服务实例 16 | microService := micro.NewService( 17 | micro.Name("rpcTokenService"), // 微服务名字 18 | micro.Address("127.0.0.1:8085"), 19 | micro.Registry(etcdReg), // etcd注册件 20 | micro.Metadata(map[string]string{"protocol": "http"}), 21 | ) 22 | // 结构命令行参数,初始化 23 | microService.Init() 24 | // 服务注册 25 | _ = service.RegisterTokenServiceHandler(microService.Server(), new(core.TokenService)) 26 | // 启动微服务 27 | _ = microService.Run() 28 | 29 | } 30 | -------------------------------------------------------------------------------- /tokenutils/service/peoto/token_utils.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;service"; 4 | message GetIdByToken_request { 5 | string user_token = 1; // token 6 | 7 | } 8 | 9 | message GetIdByToken_response { 10 | int32 user_id = 1; // 用户id 11 | 12 | } 13 | service TokenService{ 14 | rpc GetIdByToken(GetIdByToken_request) returns (GetIdByToken_response); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tokenutils/service/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /user/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "fmt" 5 | "gopkg.in/ini.v1" 6 | "strings" 7 | "user/model" 8 | ) 9 | 10 | var ( 11 | Db string 12 | DbHost string 13 | DbPort string 14 | DbUser string 15 | DbPassWord string 16 | DbName string 17 | ) 18 | 19 | func Init() { 20 | file, err := ini.Load("./conf/config.ini") 21 | if err != nil { 22 | fmt.Println("配置文件读取错误,请检查文件路径:", err) 23 | } 24 | LoadMysqlData(file) 25 | path := strings.Join([]string{DbUser, ":", DbPassWord, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8&parseTime=True&loc=Local"}, "") 26 | model.Database(path) 27 | } 28 | 29 | func LoadMysqlData(file *ini.File) { 30 | Db = file.Section("mysql").Key("Db").String() 31 | DbHost = file.Section("mysql").Key("DbHost").String() 32 | DbPort = file.Section("mysql").Key("DbPort").String() 33 | DbUser = file.Section("mysql").Key("DbUser").String() 34 | DbPassWord = file.Section("mysql").Key("DbPassWord").String() 35 | DbName = file.Section("mysql").Key("DbName").String() 36 | } 37 | -------------------------------------------------------------------------------- /user/conf/config.ini: -------------------------------------------------------------------------------- 1 | [service] 2 | AppMode = debug 3 | HttpPort = :3000 4 | 5 | [mysql] 6 | Db = mysql 7 | DbHost = 43.138.51.56 8 | DbPort = 3306 9 | DbUser = root 10 | DbPassWord = jhr292023 11 | DbName = simple-douyin -------------------------------------------------------------------------------- /user/core/to_favorite/toFavoriteService.go: -------------------------------------------------------------------------------- 1 | package to_favorite 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "user/model" 7 | proto "user/services/to_favorite" 8 | ) 9 | 10 | type ToFavoriteService struct { 11 | } 12 | 13 | /** 14 | 给Favorite微服务调用,更新用户表的total_favorited。 15 | req携带的参数:userId 用户id count 增加或者减少的数字 type 1增加2减少 16 | */ 17 | func (ToFavoriteService) UpdateTotalFavorited(ctx context.Context, req *proto.UpdateTotalFavoritedRequest, resp *proto.UpdateTotalFavoritedResponse) error { 18 | if req.UserId <= 0 || (req.Type != 1 && req.Type != 2) { 19 | resp.StatusCode = -1 20 | return errors.New("传入的userId或者type有误") 21 | } 22 | //查一下,这个userId能否查到,查不到报错,查到了返回count 23 | if _, err := model.NewUserDaoInstance().FindUserById(req.UserId); err != nil { 24 | return errors.New("传入的VideoId查不到") 25 | } 26 | //调用数据库的修改功能 27 | if req.Type == 1 { 28 | //增加 29 | model.NewUserDaoInstance().AddTotalFavorited(req.UserId, req.Count) 30 | } else if req.Type == 2 { 31 | //减少 32 | model.NewUserDaoInstance().ReduceTotalFavorited(req.UserId, req.Count) 33 | } 34 | 35 | resp.StatusCode = 0 36 | return nil 37 | } 38 | 39 | /** 40 | 给Favorite微服务调用,更新用户表的favorite_count。 41 | req携带的参数:userId 用户id count 增加或者减少的数字 type 1增加2减少 42 | */ 43 | func (ToFavoriteService) UpdateFavoriteCount(ctx context.Context, req *proto.UpdateFavoriteCountRequest, resp *proto.UpdateFavoriteCountResponse) error { 44 | if req.UserId <= 0 || (req.Type != 1 && req.Type != 2) { 45 | resp.StatusCode = -1 46 | return errors.New("传入的userId或者type有误") 47 | } 48 | //查一下,这个userId能否查到,查不到报错,查到了返回count 49 | if _, err := model.NewUserDaoInstance().FindUserById(req.UserId); err != nil { 50 | return errors.New("传入的VideoId查不到") 51 | } 52 | //调用数据库的修改功能 53 | if req.Type == 1 { 54 | //增加 55 | model.NewUserDaoInstance().AddFavoriteCount(req.UserId, req.Count) 56 | } else if req.Type == 2 { 57 | //减少 58 | model.NewUserDaoInstance().ReduceFavoriteCount(req.UserId, req.Count) 59 | } 60 | 61 | resp.StatusCode = 0 62 | return nil 63 | } 64 | -------------------------------------------------------------------------------- /user/core/to_publish/toPublishService.go: -------------------------------------------------------------------------------- 1 | package to_publish 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "user/model" 7 | proto "user/services/to_publish" 8 | ) 9 | 10 | type ToPublishService struct { 11 | } 12 | 13 | /** 14 | 给Publish微服务调用,更新用户表的work_count。 15 | req携带的参数:userId 用户id count 增加或者减少的数字 type 1增加2减少 16 | */ 17 | func (ToPublishService) UpdateWorkCount(ctx context.Context, req *proto.UpdateWorkCountRequest, resp *proto.UpdateWorkCountResponse) error { 18 | if req.UserId <= 0 || (req.Type != 1 && req.Type != 2) { 19 | resp.StatusCode = -1 20 | return errors.New("传入的userId或者type有误") 21 | } 22 | //查一下,这个userId能否查到,查不到报错,查到了返回count 23 | if _, err := model.NewUserDaoInstance().FindUserById(req.UserId); err != nil { 24 | return errors.New("传入的VideoId查不到") 25 | } 26 | //调用数据库的修改功能 27 | if req.Type == 1 { 28 | //增加 29 | model.NewUserDaoInstance().AddWorkCount(req.UserId, req.Count) 30 | } else if req.Type == 2 { 31 | //减少 32 | model.NewUserDaoInstance().ReduceWorkCount(req.UserId, req.Count) 33 | } 34 | 35 | resp.StatusCode = 0 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /user/core/to_relation/toRelationService_test.go: -------------------------------------------------------------------------------- 1 | package to_relation 2 | -------------------------------------------------------------------------------- /user/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2" 5 | "github.com/micro/go-micro/v2/registry" 6 | "github.com/micro/go-micro/v2/registry/etcd" 7 | "user/conf" 8 | "user/core" 9 | to_favorite "user/core/to_favorite" 10 | to_publish "user/core/to_publish" 11 | to_relation "user/core/to_relation" 12 | "user/services" 13 | to_favorite_proto "user/services/to_favorite" 14 | to_publish_proto "user/services/to_publish" 15 | to_relation_proto "user/services/to_relation" 16 | "user/utils/redis" 17 | ) 18 | 19 | func main() { 20 | conf.Init() 21 | // 初始化redis-DB0的连接,follow选择的DB0. 22 | redis.InitRedis() 23 | // etcd注册件 24 | etcdReg := etcd.NewRegistry( 25 | registry.Addrs("127.0.0.1:2379"), 26 | ) 27 | // 得到一个微服务实例 28 | microService := micro.NewService( 29 | micro.Name("rpcUserService"), // 微服务名字 30 | micro.Address("127.0.0.1:8082"), 31 | micro.Registry(etcdReg), // etcd注册件 32 | micro.Metadata(map[string]string{"protocol": "http"}), 33 | ) 34 | // 结构命令行参数,初始化 35 | microService.Init() 36 | // 服务注册 37 | _ = services.RegisterUserServiceHandler(microService.Server(), new(core.UserService)) 38 | _ = to_relation_proto.RegisterToRelationServiceHandler(microService.Server(), new(to_relation.ToRelationService)) 39 | _ = to_publish_proto.RegisterToPublishServiceHandler(microService.Server(), new(to_publish.ToPublishService)) 40 | _ = to_favorite_proto.RegisterToFavoriteServiceHandler(microService.Server(), new(to_favorite.ToFavoriteService)) 41 | // 启动微服务 42 | _ = microService.Run() 43 | } 44 | -------------------------------------------------------------------------------- /user/model/init.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mysql" 7 | "time" 8 | ) 9 | 10 | // DB 数据库链接单例 11 | var DB *gorm.DB 12 | 13 | // Database 在中间件中初始化mysql链接 14 | func Database(connString string) { 15 | db, err := gorm.Open("mysql", connString) 16 | if err != nil { 17 | panic(err) 18 | } 19 | db.LogMode(true) 20 | if gin.Mode() == "release" { 21 | db.LogMode(false) 22 | } 23 | //默认不加复数 24 | db.SingularTable(true) 25 | //设置连接池 26 | //空闲 27 | db.DB().SetMaxIdleConns(20) 28 | //打开 29 | db.DB().SetMaxOpenConns(100) 30 | //超时 31 | db.DB().SetConnMaxLifetime(time.Second * 30) 32 | DB = db 33 | //migration() 34 | } 35 | -------------------------------------------------------------------------------- /user/model/relation.go: -------------------------------------------------------------------------------- 1 | package model 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | to_user "user/services/from_relation" 8 | ) 9 | 10 | type Relation struct { 11 | FollowerId int64 `gorm:"default:(-)"` 12 | FollowingId int64 `gorm:"default:(-)"` 13 | CreateAt time.Time 14 | } 15 | 16 | func (Relation) TableName() string { 17 | return "relation" 18 | } 19 | 20 | type RelationDao struct { 21 | } 22 | 23 | func (RelationDao) GetRelationsByIds(relationStatus []*to_user.RelationStatus) ([]*to_user.RelationStatus, error) { 24 | var result []*to_user.RelationStatus 25 | //调用relation数据库,查出relationStatus每一项的isFollow,封装成result返回. 26 | var count int 27 | 28 | for _, rs := range relationStatus { 29 | _ = DB.Model(Relation{}).Where("follower_id=? and following_id=?", rs.FollowerId, rs.FollowingId).Count(&count).Error 30 | result = append(result, &to_user.RelationStatus{IsFollow: count > 0, FollowerId: rs.FollowerId, FollowingId: rs.FollowingId}) 31 | } 32 | fmt.Println(result) 33 | return result, nil 34 | } 35 | 36 | var relationDao *RelationDao 37 | var relationOnce sync.Once //单例模式,只生成一个userDao实例,提高性能 38 | 39 | func NewRelationDaoInstance() *RelationDao { 40 | relationOnce.Do( 41 | func() { 42 | relationDao = &RelationDao{} 43 | }) 44 | return relationDao 45 | } 46 | 47 | /** 48 | 根据follower_id和followering_id,查找是否存在关系,返回bool值 49 | */ 50 | func (d *UserDao) FindRelationById(followerId int64, followeringId int64) (bool, error) { 51 | var count int 52 | err := DB.Model(Relation{}).Where("follower_id=? and following_id=?", followerId, followeringId).Count(&count).Error 53 | if err != nil { 54 | return false, err 55 | } 56 | return count > 0, nil 57 | } 58 | -------------------------------------------------------------------------------- /user/rpc_server/TokenRpc.go: -------------------------------------------------------------------------------- 1 | package rpc_server 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/micro/go-micro/v2" 7 | "user/rpc_server/etcd" 8 | tokenproto "user/services/tokenproto" 9 | ) 10 | 11 | func GetIdByToken(token string) (int64, error) { 12 | tokenMicroService := micro.NewService(micro.Registry(etcdInit.EtcdReg)) 13 | tokenService := tokenproto.NewTokenService("rpcTokenService", tokenMicroService.Client()) 14 | 15 | var req tokenproto.GetIdByTokenRequest 16 | req.UserToken = token 17 | 18 | resp, err := tokenService.GetIdByToken(context.TODO(), &req) 19 | if err != nil { 20 | fmt.Println(err) 21 | } 22 | 23 | return int64(resp.UserId), err 24 | } 25 | -------------------------------------------------------------------------------- /user/rpc_server/etcd/etcdInit.go: -------------------------------------------------------------------------------- 1 | package etcdInit 2 | 3 | import ( 4 | "github.com/micro/go-micro/v2/registry" 5 | "github.com/micro/go-micro/v2/registry/etcd" 6 | ) 7 | 8 | var EtcdReg registry.Registry 9 | 10 | func init() { 11 | EtcdReg = etcd.NewRegistry( 12 | registry.Addrs("127.0.0.1:2379"), 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /user/services/protos/from_relation/to_user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message GetRelationStatus_Request{ 6 | int64 following_id=1; //发起关注的人 7 | int64 follower_id=2; //被关注的人 8 | } 9 | 10 | message GetRelationStatus_Response{ 11 | int64 status_code = 1; 12 | bool isFollow = 2; 13 | } 14 | 15 | message GetRelationsStatus_Request{ 16 | repeated RelationStatus relationStatus = 1; 17 | string token = 2; 18 | } 19 | 20 | message GetRelationsStatus_Response{ 21 | int64 status_code = 1; 22 | repeated RelationStatus isFollow=2; 23 | } 24 | 25 | message RelationStatus { 26 | int64 following_id=1; //发起关注的人 27 | int64 follower_id=2; //被关注的人 28 | bool isFollow=3; //是否关注 29 | } 30 | 31 | service ToUserService{ 32 | rpc GetRelationStatus(GetRelationStatus_Request) returns (GetRelationStatus_Response); 33 | rpc GetRelationsStatus(GetRelationsStatus_Request) returns (GetRelationsStatus_Response); 34 | } -------------------------------------------------------------------------------- /user/services/protos/to_favorite/to_favorite.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | //获赞数 6 | message UpdateTotalFavorited_request { 7 | int64 user_id = 1; // 用户id 8 | int32 count = 2;// 增加的数量 9 | int32 type = 3;// 1是增加,2是减少 10 | } 11 | 12 | message UpdateTotalFavorited_response { 13 | int32 status_code = 1; //响应,成功是0,失败是其他值 14 | } 15 | 16 | //喜欢的视频数 17 | message UpdateFavoriteCount_request { 18 | int64 user_id = 1; // 用户id 19 | int32 count = 2;// 增加的数量 20 | int32 type = 3;// 1是增加,2是减少 21 | } 22 | 23 | message UpdateFavoriteCount_response { 24 | int32 status_code = 1; //响应,成功是0,失败是其他值 25 | } 26 | 27 | service ToFavoriteService{ 28 | rpc UpdateTotalFavorited(UpdateTotalFavorited_request) returns (UpdateTotalFavorited_response); 29 | rpc UpdateFavoriteCount(UpdateFavoriteCount_request) returns (UpdateFavoriteCount_response); 30 | } -------------------------------------------------------------------------------- /user/services/protos/to_publish/to_publish.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message UpdateWorkCount_request { 6 | int64 user_id = 1; // 用户id 7 | int32 count = 2;// 增加的数量 8 | int32 type = 3;// 1是增加,2是减少 9 | } 10 | 11 | message UpdateWorkCount_response { 12 | int32 status_code = 1; //响应,成功是0,失败是其他值 13 | } 14 | 15 | 16 | service ToPublishService{ 17 | rpc UpdateWorkCount(UpdateWorkCount_request) returns (UpdateWorkCount_response); 18 | } -------------------------------------------------------------------------------- /user/services/protos/to_relation/to_relation.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message UpdateFollowingCount_request { 6 | int64 user_id = 1; // 用户id 7 | int32 count = 2;// 增加的数量 8 | int32 type = 3;// 1是增加,2是减少 9 | } 10 | 11 | message UpdateFollowingCount_response { 12 | int32 status_code = 1; //响应,成功是0,失败是其他值 13 | } 14 | 15 | message UpdateFollowerCount_request { 16 | int64 user_id = 1; // 用户id 17 | int32 count = 2;// 增加的数量 18 | int32 type = 3;// 1是增加,2是减少 19 | } 20 | 21 | message UpdateFollowerCount_response { 22 | int32 status_code = 1; //响应,成功是0,失败是其他值 23 | } 24 | 25 | message GetUsersByIds_request { 26 | repeated int64 user_id = 1; // 用户id集合 27 | string token = 2 ; 28 | } 29 | 30 | message GetUsersByIds_response { 31 | int32 status_code = 1;//响应,成功是0,失败是其他值 32 | repeated User UserList = 2; //用户集合 33 | } 34 | 35 | 36 | message User { 37 | // @gotags: json:"id" 38 | int64 Id = 1; // 用户id 39 | // @gotags: json:"name" 40 | string Name = 2; // 用户名称 41 | // @gotags: json:"follow_count" 42 | int64 FollowCount = 3; // 关注总数 43 | // @gotags: json:"follower_count" 44 | int64 FollowerCount = 4; // 粉丝总数 45 | // @gotags: json:"is_follow" 46 | bool IsFollow = 5; // true-已关注,false-未关注 47 | // @gotags: json:"avatar" 48 | string Avatar = 6; //用户头像 49 | // @gotags: json:"background_image" 50 | string BackgroundImage = 7; //用户个人页顶部大图 51 | // @gotags: json:"signature" 52 | string Signature = 8; //个人简介 53 | // @gotags: json:"total_favorited" 54 | int64 TotalFavorited = 9; //获赞数量 55 | // @gotags: json:"work_count" 56 | int64 WorkCount = 10; //作品数量 57 | // @gotags: json:"favorite_count" 58 | int64 FavoriteCount = 11; //点赞数量 59 | } 60 | 61 | service ToRelationService{ 62 | rpc UpdateFollowerCount(UpdateFollowerCount_request) returns (UpdateFollowerCount_response); 63 | rpc UpdateFollowingCount(UpdateFollowingCount_request) returns (UpdateFollowingCount_response); 64 | rpc GetUsersByIds(GetUsersByIds_request) returns (GetUsersByIds_response); 65 | } -------------------------------------------------------------------------------- /user/services/protos/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package services; 3 | option go_package = "../;proto"; 4 | 5 | message DouyinUserRegisterRequest { 6 | // @gotags: json:"username" 7 | string Username = 1; //注册用户名,最长32个字符 8 | // @gotags: json:"password" 9 | string Password = 2; //密码,最长32个字符 10 | } 11 | 12 | message DouyinUserRegisterResponse { 13 | // @gotags: json:"status_code" 14 | int32 StatusCode = 1; //状态码 0-成功 其他值-失败 15 | // @gotags: json:"status_msg" 16 | string StatusMsg = 2; //返回状态描述 17 | // @gotags: json:"user_id" 18 | int64 UserId = 3; //用户id 19 | // @gotags: json:"token" 20 | string Token = 4; //用户鉴权token 21 | } 22 | 23 | message DouyinUserLoginRequest { 24 | // @gotags: json:"username" 25 | string Username = 1; //注册用户名,最长32个字符 26 | // @gotags: json:"password" 27 | string Password = 2; //密码,最长32个字符 28 | } 29 | 30 | message DouyinUserLoginResponse { 31 | // @gotags: json:"status_code" 32 | int32 StatusCode = 1; //状态码 0-成功 其他值-失败 33 | // @gotags: json:"status_msg" 34 | string StatusMsg = 2; //返回状态描述 35 | // @gotags: json:"user_id" 36 | int64 UserId = 3; //用户id 37 | // @gotags: json:"token" 38 | string Token = 4; //用户鉴权token 39 | } 40 | 41 | message User { 42 | // @gotags: json:"id" 43 | int64 Id = 1; //用户id 44 | // @gotags: json:"name" 45 | string Name = 2; //用户名称 46 | // @gotags: json:"follow_count" 47 | int64 FollowCount = 3; //关注总数 48 | // @gotags: json:"follower_count" 49 | int64 FollowerCount = 4; //粉丝总数 50 | // @gotags: json:"is_follow" 51 | bool IsFollow = 5; //true-已关注,false-未关注 52 | // @gotags: json:"avatar" 53 | string Avatar = 6; //用户头像 54 | // @gotags: json:"background_image" 55 | string BackgroundImage = 7; //用户个人页顶部大图 56 | // @gotags: json:"signature" 57 | string Signature = 8; //个人简介 58 | // @gotags: json:"total_favorited" 59 | int64 TotalFavorited = 9; //获赞数量 60 | // @gotags: json:"work_count" 61 | int64 WorkCount = 10; //作品数量 62 | // @gotags: json:"favorite_count" 63 | int64 FavoriteCount = 11; //点赞数量 64 | } 65 | 66 | message DouyinUserRequest { 67 | // @gotags: json:"user_id" 68 | int64 UserId = 1; //用户id 69 | // @gotags: json:"token" 70 | string Token = 2; //用户鉴权token 71 | } 72 | 73 | message DouyinUserResponse { 74 | // @gotags: json:"status_code" 75 | int32 StatusCode = 1; //状态码 0-成功,其他值-失败 76 | // @gotags: json:"status_msg" 77 | string StatusMsg = 2; //返回状态描述 78 | // @gotags: json:"user" 79 | User User = 3; //用户信息 80 | } 81 | 82 | service UserService{ 83 | rpc Login(DouyinUserLoginRequest) returns (DouyinUserLoginResponse); 84 | rpc Register(DouyinUserRegisterRequest) returns(DouyinUserRegisterResponse); 85 | rpc UserInfo(DouyinUserRequest) returns(DouyinUserResponse); 86 | } 87 | -------------------------------------------------------------------------------- /user/services/tokenproto/token_utils.pb.micro.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-micro. DO NOT EDIT. 2 | // source: token_utils.proto 3 | 4 | package service 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | import ( 13 | context "context" 14 | api "github.com/micro/go-micro/v2/api" 15 | client "github.com/micro/go-micro/v2/client" 16 | server "github.com/micro/go-micro/v2/server" 17 | ) 18 | 19 | // Reference imports to suppress errors if they are not otherwise used. 20 | var _ = proto.Marshal 21 | var _ = fmt.Errorf 22 | var _ = math.Inf 23 | 24 | // This is a compile-time assertion to ensure that this generated file 25 | // is compatible with the proto package it is being compiled against. 26 | // A compilation error at this line likely means your copy of the 27 | // proto package needs to be updated. 28 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 29 | 30 | // Reference imports to suppress errors if they are not otherwise used. 31 | var _ api.Endpoint 32 | var _ context.Context 33 | var _ client.Option 34 | var _ server.Option 35 | 36 | // Api Endpoints for TokenService service 37 | 38 | func NewTokenServiceEndpoints() []*api.Endpoint { 39 | return []*api.Endpoint{} 40 | } 41 | 42 | // Client API for TokenService service 43 | 44 | type TokenService interface { 45 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) 46 | } 47 | 48 | type tokenService struct { 49 | c client.Client 50 | name string 51 | } 52 | 53 | func NewTokenService(name string, c client.Client) TokenService { 54 | return &tokenService{ 55 | c: c, 56 | name: name, 57 | } 58 | } 59 | 60 | func (c *tokenService) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, opts ...client.CallOption) (*GetIdByTokenResponse, error) { 61 | req := c.c.NewRequest(c.name, "TokenService.GetIdByToken", in) 62 | out := new(GetIdByTokenResponse) 63 | err := c.c.Call(ctx, req, out, opts...) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return out, nil 68 | } 69 | 70 | // Server API for TokenService service 71 | 72 | type TokenServiceHandler interface { 73 | GetIdByToken(context.Context, *GetIdByTokenRequest, *GetIdByTokenResponse) error 74 | } 75 | 76 | func RegisterTokenServiceHandler(s server.Server, hdlr TokenServiceHandler, opts ...server.HandlerOption) error { 77 | type tokenService interface { 78 | GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error 79 | } 80 | type TokenService struct { 81 | tokenService 82 | } 83 | h := &tokenServiceHandler{hdlr} 84 | return s.Handle(s.NewHandler(&TokenService{h}, opts...)) 85 | } 86 | 87 | type tokenServiceHandler struct { 88 | TokenServiceHandler 89 | } 90 | 91 | func (h *tokenServiceHandler) GetIdByToken(ctx context.Context, in *GetIdByTokenRequest, out *GetIdByTokenResponse) error { 92 | return h.TokenServiceHandler.GetIdByToken(ctx, in, out) 93 | } 94 | -------------------------------------------------------------------------------- /user/utils/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "context" 5 | "github.com/go-redis/redis/v8" 6 | ) 7 | 8 | var Ctx = context.Background() 9 | var RdbUserId *redis.Client 10 | 11 | func InitRedis() { 12 | RdbUserId = redis.NewClient(&redis.Options{ 13 | Addr: "43.138.51.56:6379", 14 | Password: "292023", 15 | DB: 0, // 用户信息存入 DB0. 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /user/utils/sha256/sha256.go: -------------------------------------------------------------------------------- 1 | package sha256 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/hex" 6 | ) 7 | 8 | //Sha256加密 9 | func Sha256(src string) string { 10 | m := sha256.New() 11 | m.Write([]byte(src)) 12 | res := hex.EncodeToString(m.Sum(nil)) 13 | return res 14 | } 15 | --------------------------------------------------------------------------------