0%

Kratos 源码分析(六):gRPC Transport(1)

上一篇文章 我们分析了 kratos 的 App 模块,了解了应用的生命周期管理机制。App 管理的核心对象之一就是 Transport Server,这篇文章我们将深入分析 gRPC Transport 层的实现原理,理解一个 gRPC 请求从进入到业务处理的完整链路。

Transport 层总体设计

kratos 的 Transport 层是对底层通信协议的抽象,目前支持 HTTP 和 gRPC 两种协议。整个 Transport 层的设计围绕以下几个核心接口展开:

transport.Server 接口

所有 Transport 服务器都必须实现 transport.Server 接口,App 通过它统一管理生命周期:

1
2
3
4
5
// transport/transport.go
type Server interface {
Start(context.Context) error
Stop(context.Context) error
}

transport.Endpointer 接口

transport.Endpointer 接口用于获取服务的 Endpoint 地址,App 在构建服务实例时通过此接口自动收集 Server 的 Endpoint 地址

1
2
3
4
// transport/transport.go
type Endpointer interface {
Endpoint() (*url.URL, error)
}

transport.Transporter 接口

Transporter 是 Transport 层的核心上下文接口,它携带了一次请求的传输层信息,通过 Context 在中间件和业务逻辑之间传播:

1
2
3
4
5
6
7
type Transporter interface {
Kind() Kind // 协议类型:"grpc" 或 "http"
Endpoint() string // 服务端点,如 "grpc://127.0.0.1:9000"
Operation() string // 方法全名,如 "/helloworld.v1.Greeter/SayHello"
RequestHeader() Header // 请求头
ReplyHeader() Header // 响应头
}

middleware.Middleware 接口

kratos 的中间件是 Transport 无关的,HTTP 和 gRPC 共用同一套中间件定义:

1
2
3
4
// middleware/middleware.go
type Handler func(ctx context.Context, req any) (any, error)

type Middleware func(Handler) Handler

接口关系图

下图简单总结了各个接口之间的关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
transport.Server          生命周期接口(App 管理)
├─ http.Server HTTP 服务器实现
└─ grpc.Server gRPC 服务器实现
├─ 实现 transport.Server → Start / Stop
├─ 实现 transport.Endpointer → Endpoint
├─ 内嵌 *grpc.Server → 原生 gRPC 能力
└─ 持有 matcher.Matcher → 中间件选择器

transport.Transporter 请求上下文接口(每次请求创建)
├─ grpc.Transport gRPC 请求的传输信息
└─ http.Transport HTTP 请求的传输信息

middleware.Middleware 中间件定义(Transport 无关)
└─ 通过 interceptor 桥接到 gRPC / HTTP

原生 gRPC Server 开发

在分析 kratos gRPC Transport 之前,我们需要先理解:如果不使用 kratos,用原生 gRPC 库开发一个服务需要做哪些事情?这能帮我们看清哪些是 protoc 自动生成的、哪些是框架完成的、哪些是业务需要补全的。

定义 Proto 文件

一切从 Proto 文件开始,这部分无论用不用 kratos 都是一样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// api/helloworld/v1/greeter.proto
syntax = "proto3";
package helloworld.v1;

option go_package = "native-grpc-demo/api/helloworld/v1;v1";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

protoc 生成代码

执行 protoc 命令后,会生成两个文件:

1
2
3
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
api/helloworld/v1/greeter.proto
文件 生成工具 内容
greeter.pb.go protoc-gen-go 消息类型 HelloRequest、HelloReply 的序列化/反序列化代码
greeter_grpc.pb.go protoc-gen-go-grpc 服务接口 GreeterServer、客户端 GreeterClient、注册函数 RegisterGreeterServer、处理器 _Greeter_SayHello_Handler

greeter_grpc.pb.go 是重点,它包含以下关键内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 1. 服务接口 —— 你必须实现这个接口
type GreeterServer interface {
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
mustEmbedUnimplementedGreeterServer()
}

// 2. 前向兼容结构体 —— 嵌入即可获得默认实现
type UnimplementedGreeterServer struct{}
func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
return nil, status.Error(codes.Unimplemented, "method SayHello not implemented")
}

// 3. 注册函数 —— 将你的实现注册到 gRPC Server
func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) {
s.RegisterService(&Greeter_ServiceDesc, srv)
}

// 4. 方法处理器 —— gRPC 内部调用链的关键节点
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context,
dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HelloRequest)
if err := dec(in); err != nil { // 解码请求
return nil, err
}
if interceptor == nil {
return srv.(GreeterServer).SayHello(ctx, in) // 无拦截器,直接调用
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/helloworld.v1.Greeter/SayHello",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
}
return interceptor(ctx, in, info, handler) // 有拦截器,走拦截器链
}

// 5. 服务描述符 —— 描述服务名和方法列表
var Greeter_ServiceDesc = grpc.ServiceDesc{
ServiceName: "helloworld.v1.Greeter",
HandlerType: (*GreeterServer)(nil),
Methods: []grpc.MethodDesc{
{MethodName: "SayHello", Handler: _Greeter_SayHello_Handler},
},
Streams: []grpc.StreamDesc{},
}

业务开发

接下来开发整个 grpc 服务的实现,包括实现 GreeterServer 接口以提供 grpc 服务接口的实现,创建真实的 gRPC Server 并启动等等。如下是一个参考实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// main.go —— 原生 gRPC Server
package main

import (
"context"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

pb "native-grpc-demo/api/helloworld/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
)

// ========== 第一部分:业务实现(必须手写)==========
type GreeterService struct {
pb.UnimplementedGreeterServer // 嵌入以获得前向兼容
}

func (s *GreeterService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

// ========== 第二部分:基础设施代码(kratos 帮你完成了这些)==========
func main() {
// 1. 创建 TCP Listener(手动)
lis, err := net.Listen("tcp", ":9000")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}

// 2. 创建 gRPC Server(手动)
server := grpc.NewServer()

// 3. 注册业务服务(手动)
pb.RegisterGreeterServer(server, &GreeterService{})

// 4. 注册健康检查(手动,kratos 自动注册)
healthServer := health.NewServer()
grpc_health_v1.RegisterHealthServer(server, healthServer)
healthServer.Resume()

// 5. 注册反射服务(手动,kratos 自动注册)
reflection.Register(server)

// 6. 启动服务(手动,kratos App.Run 封装了这些)
fmt.Println("gRPC server listening on :9000")
go func() {
if err := server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()

// 7. 信号处理(手动,kratos App.Run 封装了这些)
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
<-sigCh

// 8. 优雅停机(手动,kratos App.Stop 封装了这些)
server.GracefulStop()
fmt.Println("Server stopped")
}

总结一下,开发一个 gRPC Server 需要完成以下核心工作:

  1. 定义 Proto 文件:编写 .proto 文件,定义服务接口和消息类型
  2. 生成代码:执行 protoc 生成消息类型的序列化代码和服务接口代码
  3. 实现服务接口:嵌入 UnimplementedXxxServer,实现业务方法(如 SayHello
  4. 创建 gRPC Servergrpc.NewServer() 创建服务器实例
  5. 注册服务:调用 RegisterXxxServer 将业务实现注册到 Server
  6. 注册辅助服务:健康检查、反射服务等
  7. 监听与启动:创建 TCP Listener,调用 server.Serve(lis) 启动服务
  8. 信号处理与优雅停机:监听系统信号,调用 server.GracefulStop() 优雅停机

如果需要添加中间件功能,需要手动实现拦截器并注册到 gRPC 服务中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1. 实现拦截器
func timeoutInterceptor(timeout time.Duration) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req any,
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
return handler(ctx, req)
}
}

// 2. 注册到 gRPC 服务器
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(timeoutInterceptor(10*time.Second)),
// 多个拦截器需要使用 grpc.ChainUnaryInterceptor
)

kratos-layout 中的 gRPC 使用

之前文章我们已经详细分析过 kratos-layout 以及 [Kratos-CLI] 的用法。这一小节我们来重点分析下 kratos-layout 项目中是如何使用 gRPC Server 的。

Proto 定义

在 kratos-layout 项目中,服务接口通过 Protobuf 定义,位于 api/helloworld/v1/greeter.proto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
syntax = "proto3";
package helloworld.v1;

import "google/api/annotations.proto";

option go_package = "kratos-demo/api/helloworld/v1;v1";

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/helloworld/{name}"
};
}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

生成的 gRPC 注册代码

执行 kratos proto client 后,会生成以下文件:

文件 生成工具 说明
greeter.pb.go protoc-gen-go Protobuf 消息类型(HelloRequest、HelloReply)
greeter_grpc.pb.go protoc-gen-go-grpc gRPC 服务接口(GreeterServer、RegisterGreeterServer)
greeter_http.pb.go protoc-gen-go-http HTTP 服务接口和路由注册(GreeterHTTPServer、RegisterGreeterHTTPServer)

greeter_grpc.pb.go 是由 protoc-gen-go-grpc 自动生成的,其内容和上面 原生 gRPC Server 开发 示例中的代码一致。

业务代码需要补全的部分:

文件 说明
internal/service/greeter.go 实现 GreeterServer 接口,编写业务逻辑
internal/server/grpc.go 创建 gRPC Server,注册服务和中间件
internal/server/http.go 创建 HTTP Server,注册服务和中间件

业务实现

Service 层internal/service/greeter.go)——实现 GreeterServer 接口:

1
2
3
4
5
6
7
8
9
10
11
12
type GreeterService struct {
v1.UnimplementedGreeterServer // 嵌入未实现结构体,保证前向兼容
uc *biz.GreeterUsecase // 业务逻辑层
}

func (s *GreeterService) SayHello(ctx context.Context, in *v1.HelloRequest) (*v1.HelloReply, error) {
g, err := s.uc.CreateGreeter(ctx, &biz.Greeter{Hello: in.Name})
if err != nil {
return nil, err
}
return &v1.HelloReply{Message: "Hello " + g.Hello}, nil
}

Server 层internal/server/grpc.go)——创建 gRPC Server 并注册服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func NewGRPCServer(c *conf.Server, greeter *service.GreeterService, logger log.Logger) *grpc.Server {
var opts = []grpc.ServerOption{
grpc.Middleware(recovery.Recovery()), // 注册中间件
}
if c.Grpc.Addr != "" {
opts = append(opts, grpc.Address(c.Grpc.Addr))
}
if c.Grpc.Timeout != nil {
opts = append(opts, grpc.Timeout(c.Grpc.Timeout.AsDuration()))
}
srv := grpc.NewServer(opts...)
v1.RegisterGreeterServer(srv, greeter) // 注册 gRPC 服务
return srv
}

请求处理流程图

下面总结下 gRPC 请求的处理流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
gRPC 请求到达


原生 gRPC Server 接收请求


Greeter_ServiceDesc 定位到 _Greeter_SayHello_Handler


_Greeter_SayHello_Handler 调用 kratos 注册的 UnaryInterceptor


unaryServerInterceptor(kratos 的桥接拦截器)
├─ 1. 合并 Context(ic.Merge)
├─ 2. 创建 Transport(携带 operation、header 等信息)
├─ 3. 设置超时
├─ 4. 匹配中间件并执行 middleware.Chain
│ └─ recovery.Recovery → ... → 最终 handler
└─ 5. 返回响应


GreeterService.SayHello(业务逻辑)

这里需要注意,在 greeter_grpc.pb.go 中的实现的 _Greeter_SayHello_Handler 中, interceptor 是 gRPC 原生的 UnaryServerInterceptor,而 kratos 的中间件是 middleware.Middleware,两者之间需要桥接,这就是 kratos interceptor.go 的工作,后面会介绍。

代码分层总览

通过上面的分析,我们可以清晰地看到一个 gRPC 服务从定义到运行,每一层各完成了哪些工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
┌─────────────────────────────────────────────────────────────┐
│ 开发者手写 │
│ ├── greeter.proto │
│ │ 定义消息类型(HelloRequest、HelloReply)和 RPC 方法 │
│ │ │
│ ├── internal/service/greeter.go │
│ │ 实现 GreeterServer 接口,编写业务逻辑(SayHello) │
│ │ │
│ └── internal/server/grpc.go │
│ 创建 kratos grpc.Server、配置选项、注册服务和中间件 │
├─────────────────────────────────────────────────────────────┤
│ protoc 自动生成 │
│ ├── greeter.pb.go │
│ │ 消息类型的序列化/反序列化(HelloRequest、HelloReply) │
│ │ │
│ ├── greeter_grpc.pb.go │
│ │ GreeterServer 接口(方法签名) │
│ │ UnimplementedGreeterServer(前向兼容) │
│ │ RegisterGreeterServer(注册函数) │
│ │ _Greeter_SayHello_Handler(方法处理器) │
│ │ Greeter_ServiceDesc(服务描述符) │
│ │ │
│ └── greeter_http.pb.go │
│ GreeterHTTPServer 接口和路由注册 │
├─────────────────────────────────────────────────────────────┤
│ grpc-go 库提供 │
│ ├── grpc.Server TCP 监听、连接管理、请求分发 │
│ ├── grpc.UnaryServerInterceptor 拦截器机制 │
│ ├── grpc.ServiceRegistrar 服务注册抽象 │
│ ├── grpc.ServiceDesc 服务描述符(由protoc生成后传入) │
│ ├── 编解码(protobuf/json) 消息的序列化与反序列化 │
│ └── 健康检查、反射等标准服务 │
├─────────────────────────────────────────────────────────────┤
│ kratos 框架完成 │
│ ├── grpc.NewServer() 创建 Server 并注册内部服务 │
│ ├── server.Start() 启动服务(监听 + 健康检查) │
│ ├── server.Stop() 优雅停机(含超时强制停止) │
│ ├── unaryServerInterceptor 拦截器桥接(gRPC → kratos) │
│ ├── middleware.Middleware 统一的中间件定义与执行链 │
│ ├── matcher.Matcher 选择性中间件匹配 │
│ ├── ic.Merge Context 合并 │
│ ├── Transport 注入 注入传输信息到 Context │
│ ├── 超时控制 自动设置请求超时 │
│ ├── 健康检查 / 反射 / Admin 自动注册内部服务 │
│ ├── JSON Codec 默认使用 JSON 编解码 │
│ └── App 生命周期管理 信号处理、服务注册/注销 │
└─────────────────────────────────────────────────────────────┘

gRPC Server 实现

Server 结构体

如下是 kratos 中 gRPC Server 的结构体定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// transport/grpc/server.go
type Server struct {
*grpc.Server // 嵌入原生 gRPC Server
baseCtx context.Context
tlsConf *tls.Config
lis net.Listener
err error
network string
address string
endpoint *url.URL
timeout time.Duration
middleware matcher.Matcher // Unary 中间件选择器
streamMiddleware matcher.Matcher // Stream 中间件选择器
unaryInts []grpc.UnaryServerInterceptor
streamInts []grpc.StreamServerInterceptor
grpcOpts []grpc.ServerOption
health *health.Server
customHealth bool
metadata *apimd.Server
adminClean func()
disableReflection bool
}

Server 嵌入了 *grpc.Server,因此它既是 kratos 的 transport.Server,也是标准的 gRPC 服务器。所有原生 gRPC 功能(服务注册、反射、健康检查等)都直接可用。

创建 Server

NewServer() 负责 gRPC Server 的创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// transport/grpc/server.go
func NewServer(opts ...ServerOption) *Server {
srv := &Server{
baseCtx: context.Background(),
network: "tcp",
address: ":0",
timeout: 1 * time.Second,
health: health.NewServer(),
middleware: matcher.New(),
streamMiddleware: matcher.New(),
}

// 应用选项
for _, o := range opts {
o(srv)
}

// 构建拦截器链:kratos 拦截器始终在最前面
unaryInts := []grpc.UnaryServerInterceptor{
srv.unaryServerInterceptor(), // kratos 桥接拦截器
}
streamInts := []grpc.StreamServerInterceptor{
srv.streamServerInterceptor(), // kratos 桥接拦截器
}
// 用户自定义的 gRPC 拦截器追加在后面
if len(srv.unaryInts) > 0 {
unaryInts = append(unaryInts, srv.unaryInts...)
}
if len(srv.streamInts) > 0 {
streamInts = append(streamInts, srv.streamInts...)
}

grpcOpts := []grpc.ServerOption{
grpc.ChainUnaryInterceptor(unaryInts...),
grpc.ChainStreamInterceptor(streamInts...),
}
if srv.tlsConf != nil {
grpcOpts = append(grpcOpts, grpc.Creds(credentials.NewTLS(srv.tlsConf)))
}
if len(srv.grpcOpts) > 0 {
grpcOpts = append(grpcOpts, srv.grpcOpts...)
}

// 创建原生 gRPC Server
srv.Server = grpc.NewServer(grpcOpts...)

// 注册内部服务
srv.metadata = apimd.NewServer(srv.Server)
if !srv.customHealth {
grpc_health_v1.RegisterHealthServer(srv.Server, srv.health)
}
apimd.RegisterMetadataServer(srv.Server, srv.metadata)
if !srv.disableReflection {
reflection.Register(srv.Server)
}
srv.adminClean, _ = admin.Register(srv.Server)

return srv
}

关键设计:

  1. 拦截器顺序:kratos 的桥接拦截器始终在链的最前面,确保所有请求都经过 kratos 的中间件处理
  2. 内部服务注册:默认注册了健康检查(grpc_health_v1)、元数据服务和反射服务
  3. 中间件选择器:使用 matcher.New() 创建,支持按 operation 精确匹配和前缀通配

gRPC Server 默认注册的内部服务有:

服务 说明
grpc_health_v1 gRPC 标准健康检查协议
apimd.Metadata kratos 元数据服务
reflection gRPC 反射服务(可用 grpcurl 探测)
admin gRPC admin 服务

Server 选项

``NewServer()` 同样通过选项模式来配置 Server,其支持如下配置选项:

选项函数 说明 默认值
Network(network) 网络类型 "tcp"
Address(addr) 监听地址 ":0"
Endpoint(url) 服务端点 自动从 Listener 获取
Timeout(d) 请求超时 1s
Middleware(m...) 注册中间件
StreamMiddleware(m...) Stream 中间件
TLSConfig(c) TLS 配置 nil
Listener(lis) 自定义 Listener 自动创建
UnaryInterceptor(in...) gRPC Unary 拦截器
StreamInterceptor(in...) gRPC Stream 拦截器
CustomHealth() 自定义健康检查 false
DisableReflection() 禁用反射 false
Options(opts...) 原生 gRPC 选项

启动与停止

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// transport/grpc/server.go
func (s *Server) Start(ctx context.Context) error {
if err := s.listenAndEndpoint(); err != nil {
return s.err
}
s.baseCtx = ctx
log.Infof("[gRPC] server listening on: %s", s.lis.Addr().String())
s.health.Resume() // 健康检查设为 Serving
return s.Serve(s.lis) // 阻塞
}

func (s *Server) Stop(ctx context.Context) error {
if s.adminClean != nil {
s.adminClean()
}
s.health.Shutdown() // 健康检查设为 NotServing

done := make(chan struct{})
go func() {
defer close(done)
log.Info("[gRPC] server stopping")
s.GracefulStop() // 优雅停止
}()

select {
case <-done: // 优雅停止完成
case <-ctx.Done(): // 超时,强制停止
log.Warn("[gRPC] server couldn't stop gracefully in time, doing force stop")
s.Server.Stop()
}
return nil
}

Stop() 方法先调用 GracefulStop() 优雅停止(等待正在处理的请求完成),但如果 Context 超时(由 App 的 stopTimeout 控制),则调用 Stop 强制停止。这保证了应用不会因为个别长请求而无限期阻塞。

Endpoint 构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// transport/grpc/server.go
func (s *Server) listenAndEndpoint() error {
if s.lis == nil {
lis, err := net.Listen(s.network, s.address)
if err != nil {
s.err = err
return err
}
s.lis = lis
}
if s.endpoint == nil {
addr, err := host.Extract(s.address, s.lis)
if err != nil {
s.err = err
return err
}
s.endpoint = endpoint.NewEndpoint(endpoint.Scheme("grpc", s.tlsConf != nil), addr)
}
return s.err
}

Endpoint 的构建分两步:

  1. 创建 Listener:如果未提供自定义 Listener,则根据 network 和 address 创建
  2. 生成 Endpoint URL:格式如 grpc://192.168.1.100:9000,地址通过 host.Extract 自动提取(处理 0.0.0.0 等特殊情况,能够自动选择真实的的本机 IP 地址、端口返回)

小结

这篇文章我们介绍了 kratos gRPC Server 的关键设计,首先分析了开发一个原生 gRPC Server 的步骤,之后以 kratos-layout 为例,展示了 kratos 框架下开发 gRPC 服务的基本流程以及各个组件的职责,最后介绍了 kratos gRPC Server 结构定义、启动与停止逻辑等细节。

下一篇文章我们将继续深入 kratos gRPC Server 的实现细节,包括拦截器/中间件、编解码等实现原理。