在一個(gè)大的系統(tǒng)中,多個(gè)子系統(tǒng)(服務(wù))間必然存在數(shù)據(jù)傳遞,有數(shù)據(jù)傳遞就需要通信方式,你可以選擇最簡(jiǎn)單的http進(jìn)行通信,也可以選擇rpc服務(wù)進(jìn)行通信, 在go-zero,我們使用zrpc來(lái)進(jìn)行服務(wù)間的通信,zrpc是基于grpc。
在前面我們完善了對(duì)用戶進(jìn)行登錄,用戶查詢圖書(shū)等接口協(xié)議,但是用戶在查詢圖書(shū)時(shí)沒(méi)有做任何用戶校驗(yàn),如果當(dāng)前用戶是一個(gè)不存在的用戶則我們不允許其查閱圖書(shū)信息,從上文信息我們可以得知,需要user服務(wù)提供一個(gè)方法來(lái)獲取用戶信息供search服務(wù)使用,因此我們就需要?jiǎng)?chuàng)建一個(gè)user rpc服務(wù),并提供一個(gè)getUser方法。
$ vim service/user/rpc/user.proto
syntax = "proto3";
package user;
option go_package = "./user";
message IdReq{
int64 id = 1;
}
message UserInfoReply{
int64 id = 1;
string name = 2;
string number = 3;
string gender = 4;
}
service user {
rpc getUser(IdReq) returns(UserInfoReply);
}
$ cd service/user/rpc
$ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.
如果安裝的 protoc-gen-go 版大于1.4.0, proto文件建議加上go_package添加配置及完善yaml配置項(xiàng)
$ vim service/user/rpc/internal/config/config.go
type Config struct {
zrpc.RpcServerConf
Mysql struct {
DataSource string
}
CacheRedis cache.CacheConf
}
$ vim /service/user/rpc/etc/user.yaml
Name: user.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- $etcdHost
Key: user.rpc
Mysql:
DataSource: $user:$password@tcp($url)/$db?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
CacheRedis:
- Host: $host
Pass: $pass
Type: node
- $user: mysql數(shù)據(jù)庫(kù)user
- $password: mysql數(shù)據(jù)庫(kù)密碼
- $url: mysql數(shù)據(jù)庫(kù)連接地址
- $db: mysql數(shù)據(jù)庫(kù)db名稱,即user表所在database
- $host: redis連接地址 格式:ip:port,如:127.0.0.1:6379
- $pass: redis密碼
- $etcdHost: etcd連接地址,格式:ip:port,如: 127.0.0.1:2379
$ vim service/user/rpc/internal/svc/servicecontext.go
type ServiceContext struct {
Config config.Config
UserModel model.UserModel
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := sqlx.NewMysql(c.Mysql.DataSource)
return &ServiceContext{
Config: c,
UserModel: model.NewUserModel(conn, c.CacheRedis),
}
}
$ service/user/rpc/internal/logic/getuserlogic.go
func (l *GetUserLogic) GetUser(in *user.IdReq) (*user.UserInfoReply, error) {
one, err := l.svcCtx.UserModel.FindOne(in.Id)
if err != nil {
return nil, err
}
return &user.UserInfoReply{
Id: one.Id,
Name: one.Name,
Number: one.Number,
Gender: one.Gender,
}, nil
}
接下來(lái)我們?cè)趕earch服務(wù)中調(diào)用user rpc
$ vim service/search/api/internal/config/config.go
type Config struct {
rest.RestConf
Auth struct {
AccessSecret string
AccessExpire int64
}
UserRpc zrpc.RpcClientConf
}
$ vim service/search/api/etc/search-api.yaml
Name: search-api
Host: 0.0.0.0
Port: 8889
Auth:
AccessSecret: $AccessSecret
AccessExpire: $AccessExpire
UserRpc:
Etcd:
Hosts:
- $etcdHost
Key: user.rpc
- $AccessSecret:這個(gè)值必須要和user api中聲明的一致。
- $AccessExpire: 有效期
- $etcdHost: etcd連接地址
- etcd中的Key必須要和user rpc服務(wù)配置中Key一致
$ vim service/search/api/internal/svc/servicecontext.go
type ServiceContext struct {
Config config.Config
Example rest.Middleware
UserRpc user.User
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
Example: middleware.NewExampleMiddleware().Handle,
UserRpc: user.NewUser(zrpc.MustNewClient(c.UserRpc)),
}
}
$ vim /service/search/api/internal/logic/searchlogic.go
func (l *SearchLogic) Search(req types.SearchReq) (*types.SearchReply, error) {
userIdNumber := json.Number(fmt.Sprintf("%v", l.ctx.Value("userId")))
logx.Infof("userId: %s", userIdNumber)
userId, err := userIdNumber.Int64()
if err != nil {
return nil, err
}
// 使用user rpc
_, err = l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdReq{
Id: userId,
})
if err != nil {
return nil, err
}
return &types.SearchReply{
Name: req.Name,
Count: 100,
}, nil
}
$ cd service/user/rpc
$ go run user.go -f etc/user.yaml
Starting rpc server at 127.0.0.1:8080...
$ cd service/search/api
$ go run search.go -f etc/search-api.yaml
$ curl -i -X GET \
'http://127.0.0.1:8889/search/do?name=%E8%A5%BF%E6%B8%B8%E8%AE%B0' \
-H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTI4NjcwNzQsImlhdCI6MTYxMjc4MDY3NCwidXNlcklkIjoxfQ.JKa83g9BlEW84IiCXFGwP2aSd0xF3tMnxrOzVebbt80'
HTTP/1.1 200 OK
Content
-Type: application/json
Date: Tue, 09 Feb 2021 06:05:52 GMT
Content-Length: 32
{"name":"西游記","count":100}
更多建議: