gorpc 模块解析

gorpc 是 goweb3 项目中基于 go-micro 框架构建的 gRPC 通信模块,提供服务端启动、客户端调用、服务注册与发现等完整的微服务通信能力。


一、模块架构


plainText

gorpc/
├── server/                        # 服务端
│   ├── main.go                    # 入口文件
│   ├── startgrpc/startgrpc.go     # 启动封装
│   ├── register/grpc_register.go  # 服务注册
│   └── handler/                   # 业务处理器
├── client/                        # 客户端
│   ├── hello/hello_cli.go         # 示例客户端
│   └── dbgorpc/                   # 数据库RPC客户端
└── goconfig/gogrpc/               # 配置层
    ├── gorpcserver/               # 服务端核心
    ├── gorpcclient/               # 客户端核心
    ├── gofacade/                  # RPC门面
    └── proto/                     # Protobuf定义

二、核心组件详解

1. GogrpcServer - 服务端核心

go

type GogrpcServer struct {
    basedto.BaseEntitySingle
    registerGrpc IgogrpcRegister   // 服务注册器
}

服务启动流程

go

func Start(reg IgogrpcRegister, dto *baseconfig.RpcServerDto) {
    // 1. 创建服务实例
    gogrpcServer := NewGogrpcServer(reg)
    
    // 2. 运行服务
    gogrpcServer.RunServer(dto)
}

func (server *GogrpcServer) RunServer(serverDto *baseconfig.RpcServerDto) {
    // 1. 初始化服务(注册到 etcd)
    service := server.Init(serverDto)
    
    // 2. 注册 Handler
    server.registerGrpc.RegisterGrpc(service)
    
    // 3. 启动服务
    service.Run()
}

服务初始化


go

func (server *GogrpcServer) Init(serverDto *baseconfig.RpcServerDto) micro.Service {
    // 1. 创建 etcd 注册中心
    register := etcd.NewRegistry(func(options *registry.Options) {
        options.Addrs = strutil.Split(serverDto.EtcdHost, ",")
    })
    
    // 2. 配置服务选项
    opts := []micro.Option{
        micro.Name(serverDto.ServerName),
        micro.Version(version),
        micro.RegisterTTL(time.Second * 90),      // 服务过期时间
        micro.RegisterInterval(time.Second * 30), // 心跳间隔
        micro.Registry(register),
        micro.Address(":" + serverDto.ServerPort),
    }
    
    // 3. 创建服务
    service := micro.NewService(opts...)
    service.Init()
    return service
}
2. GorpcCli - 泛型客户端

go

type GorpcCli[S any] struct {
    rpcClient      S                           // 泛型 RPC 客户端
    RpcServiceName string                      // 服务名称
    FuncNew        func(name string, c client.Client) S  // 客户端构造函数
}

客户端初始化

go

func (g *GorpcCli[S]) init(funcNew func(name string, c client.Client) S) *GorpcCli[S] {
    // 使用 go-micro 共享客户端
    g.rpcClient = funcNew(g.RpcServiceName, *common.Client())
    return g
}

客户端管理


go

var RpcCliMap sync.Map  // 线程安全的客户端缓存

func Register[S any](s string, rpcli *GorpcCli[S]) {
    RpcCliMap.Store(s, rpcli)
}

func Find[S any](s string) *GorpcCli[S] {
    ci, ok := RpcCliMap.Load(s)
    if ok {
        return ci.(*GorpcCli[S])
    }
    return nil
}
3. GrpcRegister - 服务注册器

go

type GrpcRegister struct {
    basedto.BaseEntitySingle
}

func (grpcRegister *GrpcRegister) RegisterGrpc(service micro.Service) {
    // 注册各个 Handler
    helloProto.RegisterHelloYeahHandler(service.Server(), handler.NewHelloRpc())
    godbProto.RegisterGeneralGodbHandler(service.Server(), handler.NewGeneralGodbRpc())
}

三、服务发现机制


plainText

┌─────────────────────────────────────────────────────────────┐
│                     服务发现流程                            │
├─────────────────────────────────────────────────────────────┤
│  服务端                                                    │
│  ├── 启动时注册到 etcd                                     │
│  ├── 定时发送心跳(30s)                                    │
│  └── TTL 过期自动下线(90s)                                │
├─────────────────────────────────────────────────────────────┤
│  客户端                                                    │
│  ├── 从 etcd 查询服务地址                                   │
│  ├── 负载均衡选择实例                                       │
│  └── 建立连接调用                                          │
└─────────────────────────────────────────────────────────────┘

配置项

配置项说明默认值
RegisterTTL服务存活时间90秒
RegisterInterval心跳间隔30秒
EtcdHostetcd 地址localhost:2379

四、配置与依赖

RPC 配置(来自 IchubConfig)

yaml

rpc:
  servername: rpcweb.website.com
  version: v1.0
  serverport: "8081"
  clientname: rpcweb-client

etcd:
  server:
    hosturl: localhost:2379
核心依赖
依赖版本用途
github.com/micro/go-micro/v2v2微服务框架
github.com/micro/go-micro/v2/registry/etcdv2etcd 服务发现
google.golang.org/grpc-gRPC 核心

五、使用示例

1. 服务端启动

go

func main() {
    // 读取 RPC 配置
    rpc := ichubconfig.FindBeanIchubConfig().ReadVar2Rpc("rpc")
    
    // 启动服务
    startgrpc.Start(rpc)
}
2. 定义 Handler

go

type HelloRpc struct{}

func NewHelloRpc() *HelloRpc {
    return &HelloRpc{}
}

func (h *HelloRpc) SayHello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error {
    rsp.Message = "Hello " + req.Name
    return nil
}
3. 客户端调用

go

// 创建门面
facade := gofacade.NewRpcFacade()

// 调用 RPC
req := &proto.HelloRequest{Name: "World"}
rsp, err := facade.HelloService.RpcClient().SayHello(context.Background(), req)
4. 注册服务

go

func (grpcRegister *GrpcRegister) RegisterGrpc(service micro.Service) {
    proto.RegisterHelloYeahHandler(service.Server(), handler.NewHelloRpc())
}

六、设计亮点

特性实现方式优势
泛型客户端GorpcCli[S] 泛型结构体类型安全,支持任意服务
服务发现go-micro + etcd自动服务注册、健康检查
心跳机制RegisterTTL + RegisterInterval自动剔除故障节点
客户端缓存sync.Map复用连接,减少开销
依赖注入basedi 容器统一管理,易于测试

七、完整调用链路


plainText

客户端请求
    ↓
RpcFacade.HelloService.RpcClient()
    ↓
GorpcCli[S].rpcClient(从 etcd 获取服务地址)
    ↓
gRPC 网络调用
    ↓
服务端 Handler 处理
    ↓
返回响应

八、代码生成支持

项目提供了 RPC 代码生成能力,通过模板自动生成:

  • config/factroy/template/gorpc/Rpc.template - Handler 模板
  • config/factroy/template/gorpc/Rpc.proto.template - Proto 模板

生成的代码结构:


plainText

domain/internal/db/gorpc/
├── service/xxx_gorpc.go      # Handler 实现
└── proto/
    ├── xxx_proto.pb.go        # Go 代码
    ├── xxx_proto.pb.micro.go  # go-micro 封装
    └── pb/xxx_proto.proto     # Proto 定义

九、典型应用场景

  1. 微服务间通信:替代 HTTP,实现高效的跨服务调用
  2. 数据库代理:通过 RPC 封装数据库操作,实现读写分离
  3. 分布式计算:将计算任务分发到多个 RPC 服务节点
  4. API 网关:通过 RPC 聚合多个后端服务
  5. 消息处理:与 NATS 配合,实现异步消息的同步处理

更多推荐