goweb3系列解析6:gorpc 模块解析gorpc 是 goweb3 项目中基于 go-micro 框架构建的 gRPC 通信模块,提供服务端启动、客户端调用、服务注册与发现等微服务通信能力
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秒 |
EtcdHost | etcd 地址 | 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/v2 | v2 | 微服务框架 |
github.com/micro/go-micro/v2/registry/etcd | v2 | etcd 服务发现 |
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 定义九、典型应用场景
- 微服务间通信:替代 HTTP,实现高效的跨服务调用
- 数据库代理:通过 RPC 封装数据库操作,实现读写分离
- 分布式计算:将计算任务分发到多个 RPC 服务节点
- API 网关:通过 RPC 聚合多个后端服务
- 消息处理:与 NATS 配合,实现异步消息的同步处理
