rpc生成多分组服务

参考文档:

https://go-zero.dev/docs/tutorials/proto/services/group

服务分组描述

在 go-zero 中,我们通过在 proto 文件中以 service 为维度来进行文件分组,我们可以在 proto 文件中定义多个 service,每个 service 都会生成一个独立的文件夹,这样就可以将不同的服务进行分组,从而提高代码的可读性和可维护性。

除了 proto 文件中定义了 service 外,分组与否还需要在 goctl 中控制,生成带分组或者不带分组的代码取决于开发者,我们通过示例来演示一下。

操作步骤

  1. 定义proto文件
  2. 命令生成文件
  3. main文件注册service服务
  4. 编写业务逻辑
  5. 启动文件

proto文件定义

首先,我们需要在 proto 文件中定义多个 service

syntax = "proto3";

package user;

option go_package = "github.com/example/user";

message LoginReq{}
message LoginResp{}
message UserInfoReq{}
message UserInfoResp{}
message UserInfoUpdateReq{}
message UserInfoUpdateResp{}
message UserListReq{}
message UserListResp{}
service UserService{
  rpc Login (LoginReq) returns (LoginResp);
  rpc UserInfo (UserInfoReq) returns (UserInfoResp);
  rpc UserInfoUpdate (UserInfoUpdateReq) returns (UserInfoUpdateResp);
  rpc UserList (UserListReq) returns (UserListResp);
}

message UserRoleListReq{}
message UserRoleListResp{}
message UserRoleUpdateReq{}
message UserRoleUpdateResp{}
message UserRoleInfoReq{}
message UserRoleInfoResp{}
message UserRoleAddReq{}
message UserRoleAddResp{}
message UserRoleDeleteReq{}
message UserRoleDeleteResp{}
service UserRoleService{
  rpc UserRoleList (UserRoleListReq) returns (UserRoleListResp);
  rpc UserRoleUpdate (UserRoleUpdateReq) returns (UserRoleUpdateResp);
  rpc UserRoleInfo (UserRoleInfoReq) returns (UserRoleInfoResp);
  rpc UserRoleAdd (UserRoleAddReq) returns (UserRoleAddResp);
  rpc UserRoleDelete (UserRoleDeleteReq) returns (UserRoleDeleteResp);
}

message UserClassListReq{}
message UserClassListResp{}
message UserClassUpdateReq{}
message UserClassUpdateResp{}
message UserClassInfoReq{}
message UserClassInfoResp{}
message UserClassAddReq{}
message UserClassAddResp{}
message UserClassDeleteReq{}
message UserClassDeleteResp{}
service UserClassService{
  rpc UserClassList (UserClassListReq) returns (UserClassListResp);
  rpc UserClassUpdate (UserClassUpdateReq) returns (UserClassUpdateResp);
  rpc UserClassInfo (UserClassInfoReq) returns (UserClassInfoResp);
  rpc UserClassAdd (UserClassAddReq) returns (UserClassAddResp);
  rpc UserClassDelete (UserClassDeleteReq) returns (UserClassDeleteResp);
}

生成代码

通过 -m 指定 goctl 生成分组的代码
$ goctl rpc protoc user.proto –go_out=. –go-grpc_out=. –zrpc_out=. -m

我们来看一下带分组的情况下,goctl 生成的代码结构:

# 通过 -m 指定 goctl 生成分组的代码
$ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=. -m
$ tree
.
├── client
│   ├── userclassservice
│   │   └── userclassservice.go
│   ├── userroleservice
│   │   └── userroleservice.go
│   └── userservice
│       └── userservice.go
├── etc
│   └── user.yaml
├── github.com
│   └── example
│       └── user
│           ├── user.pb.go
│           └── user_grpc.pb.go
├── go.mod
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   ├── userclassservice
│   │   │   ├── userclassaddlogic.go
│   │   │   ├── userclassdeletelogic.go
│   │   │   ├── userclassinfologic.go
│   │   │   ├── userclasslistlogic.go
│   │   │   └── userclassupdatelogic.go
│   │   ├── userroleservice
│   │   │   ├── userroleaddlogic.go
│   │   │   ├── userroledeletelogic.go
│   │   │   ├── userroleinfologic.go
│   │   │   ├── userrolelistlogic.go
│   │   │   └── userroleupdatelogic.go
│   │   └── userservice
│   │       ├── loginlogic.go
│   │       ├── userinfologic.go
│   │       ├── userinfoupdatelogic.go
│   │       └── userlistlogic.go
│   ├── server
│   │   ├── userclassservice
│   │   │   └── userclassserviceserver.go
│   │   ├── userroleservice
│   │   │   └── userroleserviceserver.go
│   │   └── userservice
│   │       └── userserviceserver.go
│   └── svc
│       └── servicecontext.go
├── user.go
└── user.proto

19 directories, 28 files

在 user.go 中注册服务

// 引入包
import (
    userclassservice "ytss_go_zero/app/core/cmd/rpc/internal/server/userclassservice"
    userroleservice "ytss_go_zero/app/core/cmd/rpc/internal/server/userroleservice"
    userservice "ytss_go_zero/app/core/cmd/rpc/internal/server/userservice"
)

func main() {
    flag.Parse()

    var c config.Config
    conf.MustLoad(*configFile, &c)
    ctx := svc.NewServiceContext(c)

   //注册服务
    s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
        pb.RegisterUseClassClassServer(grpcServer, testserviceServer.NewUserClassServiceServer(ctx))
        pb.RegisterRoleServiceServer(grpcServer, userserviceServer.NewRoleerviceServer(ctx))
        pb.RegisterUserServiceServer(grpcServer, authgroupservice.NewUserServiceServer(ctx))

        if c.Mode == service.DevMode || c.Mode == service.TestMode {
            reflection.Register(grpcServer)
        }
    })
    defer s.Stop()

    fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
    s.Start()
}

启动服务

go run user.go -f ./etc/user.yaml

api调用rpc步骤

  1. 修改 NewServiceContext
  2. loginc 中调用
    app/core/cmd/api/internal/logic/authGroup/update_auth_group_logic.go

实际操作

  1. 修改service_context

app/core/cmd/api/internal/svc/service_context.go


import (
   "ytss_go_zero/app/core/cmd/rpc/client/testservice"
)

type ServiceContext struct {
    CoreRpcAuthGroupService authgroupservice.AuthGroupService
}


func NewServiceContext(c config.Config) *ServiceContext {
    // 初始化业务redis驱动
    var rdbConf redis.Options
    copier.Copy(&rdbConf, &c.RedisDB)

    //// 初始化go-zero redis驱动
    //var zrdbConf zredis.RedisConf
    //copier.Copy(&zrdbConf, &c.Redis)

    // 创建一个根Context
    rootCtx := utils.NewKeyValueContext(context.Background())

    // 测试上下文件
    //rootCtx.Set("redisToken", "someToken")
    //if token, ok := rootCtx.Get("redisToken"); ok {
    //    fmt.Println("Redis Token:", token)
    //}

    return &ServiceContext{
        Config: c,
        //Auth:      middleware.NewAuthMiddleware().Handle,
        TokenAuth: middleware.NewTokenAuthMiddleware(rootCtx).Handle,
        RootCtx:   rootCtx,
        RDB:       models.InitRedis(rdbConf),
        //RDBZ:   models.InitRedisGoZero(zrdbConf),

        // 测试服务
        CoreRpcTestService: testservice.NewTestService(zrpc.MustNewClient(c.CoreRpcConf)),
        // 用户服务
        CoreRpcUserService: userservice.NewUserService(zrpc.MustNewClient(c.CoreRpcConf)),
        //CoreRpcUserService: userservice.NewUserService(zrpc.MustNewClient(c.CoreRpcConf, zrpc.WithUnaryClientInterceptor(HeaderStreamInterceptor))),

        // 角色组服务
        CoreRpcAuthGroupService: authgroupservice.NewAuthGroupService(zrpc.MustNewClient(c.CoreRpcConf)),
    }
}
  1. loginc 中调用

import (

    "ytss_go_zero/app/core/cmd/rpc/client/testservice"

)

func (l *PingRpcLogic) PingRpc(req *types.PingReq) (resp *types.PingResp, err error) {

    //if req.Id == 0 {
    //    err = errors.New("req.id is required")
    //}
    if err != nil {
        return nil, err
    }
    // 调用rpc入参
    pongReq := testservice.PongReq{}
    err = copier.Copy(&pongReq, req)
    if err != nil {
        return nil, err
    }
    pong, err := l.svcCtx.CoreRpcTestService.Pong(l.ctx, &pongReq)

    if err != nil {
        //return nil, err
        //参数1,返回给前端,参数2,打印到日志到控制台
        return nil, errors.Wrapf(xerr.NewErrMsg("add address fail"), "add address rpc AddUserAddress fail req: %+v , err : %v ", req, err)
    }
    resp = &types.PingResp{
        Msg: pong.Msg,
    }
    return
}
作者:海马  创建时间:2024-08-10 17:02
最后编辑:海马  更新时间:2024-12-22 19:32