Skip to content

Latest commit

 

History

History
133 lines (97 loc) · 6.44 KB

README.zh_CN.md

File metadata and controls

133 lines (97 loc) · 6.44 KB

English | 中文

tRPC-Go Client 模块

背景

客户端通过桩代码发起 RPC 请求,请求会经过框架的 client 模块,进行服务发现,执行拦截器,序列化,压缩等,最后通过 transport 模块发送到网络中;而接收到网络响应后,会执行解压缩,反序列化,执行拦截器,最终返回响应给用户。client 模块中的每个步骤都是可以自定义的,用户可以自定义服务发现方式,自定义拦截器,自定义序列化和压缩等。

客户端选项

用户可以在发起 RPC 请求的时候传入不同的客户端选项,包括请求的目的地址,网络类型等;也可以通过选项指定各个步骤的具体实现,包括服务发现方式,序列化方式等。

proxy := pb.NewGreeterClientProxy()
rsp, err := proxy.Hello(
    context.Background(),
    &pb.HelloRequest{Msg: "world"},
    client.WithTarget("ip://127.0.0.1:9000"), // 指定 client 选项
)

常用的选项如下:

  • WithTarget(target string) 设置服务端地址

  • WithNetwork(network string) 设置网络类型

  • WithNamespace(ns string) 设置服务端命名空间(Production/Development)

  • WithServiceName(name string) 设置服务端服务名,服务名会直接在服务发现用于寻址

  • WithTimeout(timeout time.Duration) 设置请求的超时时间

  • WithNamedFilter(name string, f filter.ClientFilter) 设置拦截器

  • WithSerializationType(t int) 设置序列化类型,内置的序列化方式有 protobuf,json,flatbuffer 等,自定义序列化类型需要先使用 codec.RegisterSerializer 注册序列化类型

  • WithCompressType(t int) 设置压缩类型,内置的序列化方式有 gzip,snappy,zlib 等,自定义压缩类型需要先使用 codec.RegisterCompressor 注册压缩类型

  • WithProtocol(s string) 设置自定义协议类型(默认是 trpc),需要先使用 codec.Register 注册协议类型

客户端配置

用户不仅可以在发起 RPC 请求时传入不同的选项,还可以在配置文件中添加客户端的配置。客户端选项和客户端配置的功能是部分重合的,客户端选项的优先级高于客户端配置,如果同时添加了配置和选项的话,选项中的内容会覆盖配置。使用客户端配置的优点是方便修改配置内容,不需要频繁变更代码。

client: # 客户端配置
  timeout: 1000 # 所有请求最长处理时间(ms)
  namespace: Development # 所有请求服务端的环境
  filter: # 所有请求的拦截器
    - debuglog # 使用 debuglog 打印具体请求和响应数据
  service: # 请求特定服务端的配置
    - callee: trpc.test.helloworld.Greeter # 请求服务端协议文件的 service name, 如果 callee 和下面的 name 一样,那只需要配置其中之一即可
      name: trpc.test.helloworld.Greeter1 # 请求服务名字路由的 service name
      target: ip://127.0.0.1:8000 # 服务端地址,如果 name 可以直接用作服务发现,则可以不用配置,例如 ip://ip:port, polaris://servicename
      network: tcp # 请求的网络类型 tcp udp
      protocol: trpc # 应用层协议 trpc http
      timeout: 800 # 请求超时时间(ms)
      serialization: 0 # 序列化方式 0-pb 2-json 3-flatbuffer,默认不用配置
      compression: 1 # 压缩方式 1-gzip 2-snappy 3-zlib,默认不用配置

配置中的 calleename 的区别:

callee 是指被调方的 pb 协议文件的 service name,格式是 pbpackage.service

如 pb 为:

package trpc.a.b;
service Greeter {
    rpc SayHello(request) returns reply
}

那么 callee 即为 trpc.a.b.Greeter

name 是指被调方注册在名字服务上面的服务名,也就是被调服务配置文件里面的 server.service.name 的字段值。

一般情况下,calleename 是相同的,只需配置其中任何一个即可,但是有些场景下,如存储服务,同一份 pb 会部署多个实例,这个时候的名字服务的 service name 和 pb service name 就不一样了,此时配置文件就必须同时配置 calleename

client:
  service:
    - callee: pbpackage.service # 必须同时配置 callee 和 name,callee 是 pb 的 service name,用于匹配 client proxy 和配置
      name: polaris-service-name # 名字服务的 service name,用于寻址
      protocol: trpc

通过 pb 生成的 client 桩代码,默认会把 pb servicename 填入到 client 中,所以 client 寻找配置时只会 以 callee 为 key(也就是 pb 的 service name)来匹配

而通过类似 redis.NewClientProxy("trpc.a.b.c") 等(包括 database 下面所有插件以及 http)生成的 client,默认 service name 就是用户自己输入的字符串,所以 client 寻找配置时以 NewClientProxy 的输入参数为 key(即以上的 trpc.a.b.c)来匹配

同时,框架还支持了同时以 calleename 为 key 来寻找配置,比如以下两个客户端配置共享了相同的 callee, 但是 name 不同:

client:
  service:
    - callee: pbpackage.service # callee 是 pb 的 service name
      name: polaris-service-name1 # 名字服务的 service name,用于寻址
      network: tcp # 使用 TCP
    - callee: pbpackage.service # callee 是 pb 的 service name
      name: polaris-service-name2 # 另一个名字服务的 service name,用于寻址
      network: udp # 使用 UDP

用户在代码中可以使用 client.WithServiceName 来同时用 called 以及 name 作为 key 进行配置的寻找:

// proxy1 使用第一项配置,使用 TCP
proxy1 := pb.NewClientProxy(client.WithServiceName("polaris-service-name1"))
// proxy2 使用第二项配置,使用 UDP
proxy2 := pb.NewClientProxy(client.WithServiceName("polaris-service-name2"))

客户端调用流程

  1. 用户传入请求,在使用桩代码发起 RPC 调用
  2. 进入 client 模块
  3. 根据配置的 option 和配置文件信息完成客户端配置
  4. 进行服务发现,根据服务名获取服务真实地址
  5. 调用拦截器,执行拦截器前置阶段
  6. 序列化请求体,得到二进制数据
  7. 压缩请求体
  8. 打包完整请请求,添加协议头
  9. transport 模块发起网络请求
  10. transport 模块接收网络响应
  11. 解包响应,得到协议头和响应体
  12. 解压响应体
  13. 反序列化响应,得到响应结构
  14. 调用拦截器,执行拦截器后置阶段
  15. 将响应返回给用户