go-zero rpc編寫(xiě)與調(diào)用

2022-04-21 10:56 更新

rpc編寫(xiě)與調(diào)用

在一個(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。

場(chǎng)景

在前面我們完善了對(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方法。

rpc服務(wù)編寫(xiě)

  • 編譯proto文件
  $ 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);
  }
  • 生成rpc服務(wù)代碼
$ 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)

  • 添加配置及完善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),
      }
  }
  • 添加rpc邏輯
  $ 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
  }

使用rpc

接下來(lái)我們?cè)趕earch服務(wù)中調(diào)用user rpc

  • 添加UserRpc配置及yaml配置項(xiàng)
  $ 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)),
      }
  }
  • 補(bǔ)充邏輯
  $ 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
  }

啟動(dòng)并驗(yàn)證服務(wù)

  • 啟動(dòng)etcd、redis、mysql
  • 啟動(dòng)user rpc

  $ cd service/user/rpc
  $ go run user.go -f etc/user.yaml
  Starting rpc server at 127.0.0.1:8080...

  • 啟動(dòng)search api

$ cd service/search/api
$ go run search.go -f etc/search-api.yaml

  • 驗(yàn)證服務(wù)

  $ 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}


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)