├── .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 |
--------------------------------------------------------------------------------