跳到主要内容

客户端调用

如何创建可复用的 Kitex Client?​

  • service name: NewClient 的第一个参数; 是服务发现和观测的核心维度;
  • 禁止模式: 每个请求调用一次 NewClient; 会放大连接、CPU、配置拉取和 goroutine;
  • 构造期配置: 连接超时、RPC 超时、重试、熔断等通常在 NewClient 时一次性配置;
func newUserClient() (userservice.Client, error) {
cli, err := userservice.NewClient(
"user",
client.WithHostPorts("127.0.0.1:8888"),
client.WithConnectTimeout(200*time.Millisecond),
client.WithRPCTimeout(time.Second),
)
if err != nil {
return nil, fmt.Errorf("create user client: %w", err)
}
return cli, nil
}

如何发起一次 RPC 调用?​

  • 实践: 每个调用方法都会接收 context.Context 和请求对象,返回响应与 error;
  • context: 约束本地调用的取消和 deadline;跨进程传播需要 超时配置 中的协议前提;
  • Call Option: 通过方法尾参传入,只对单次调用生效,优先级高于 Client Option;
  • callopt.WithRPCTimeout: 单次覆盖超时; 只用于特例,不要到处散落;
  • callopt.WithHostPort: 单次直连指定实例; 适合诊断,不适合生产流量;
func getUser(ctx context.Context, cli userservice.Client, id int64) (*api.GetUserResponse, error) {
resp, err := cli.GetUser(ctx, &api.GetUserRequest{Id: id})
if err != nil {
return nil, fmt.Errorf("get user %d: %w", id, err)
}
return resp, nil
}

如何给 Client 提供目标地址?​

  • 本地开发: client.WithHostPorts 直接指定实例地址;
  • 动态环境: client.WithResolver 获取实例列表,由 LoadBalancer 选择;
  • URL/DNS: callopt.WithURL 或 HTTP Resolver; 解析结果仍需连接目标;
  • 预热: 首次调用延迟敏感时用 warming up 初始化 Resolver 和连接池;

如何处理调用失败?​

  • 实践: 先处理 err,再读取 response; 不能假设失败时 response 可用;
  • 实践: 用 errors.Is、kerrors.IsTimeoutError 或业务异常转换判断错误类别;
  • 实践: 不因“读请求”就盲目重试; 必须确认接口幂等并留有总时间预算;