grpc-go API设计实践,参考 https://www.youtube.com/watch?v=Z_yD7YPL2oE

  1. API接口幂等性
    1. 服务接口应该是幂等的,可以让客户端在请求失败的情况下安全重试
  2. 性能
    1. repeated字段
      1. 请求:可能包含无限制请求,需要设置限制
      2. 回复:应该支持分页
    2. 避免长时间运行操作
      1. 运行时间越长,重试可能性就越大
      2. 后台执行(可靠性),异步发送回复(回调,邮件,pubsub),或者提供可跟踪token
  3. 默认值
    1. 定义合理的默认行为
      1. 枚举zero value为Unset,使用UNKOWN/UNSPECIFIED/UNSET作为默认值(防止误用)
    2. 向前兼容
      1. 服务的和客户端是无法同步更新的
      2. 添加字段时,默认行为应该是之前的行为
      3. 加入新特性时可回滚
  4. 错误信息
    1. Errors
      1. grpc内置First-class
      2. 不要在response payload中包含错误信息(大多数情况下)
    2. 避免批量处理多个无关操作
      1. 例如更新数据库的多条记录
      2. 错误处理会变得更复杂(因为存在部分成功的场景)
      3. 使用stream形式的接口,或者调用多次接口
  5. 错误处理-避免Panic,尽可能优雅的处理错误
    1. 只有内部状态无法恢复时,Panic才是合适做法
      1. 内存错误
      2. OOM
      3. 数据错误
    2. 错误都返回给调用方(避免隐藏错误)
    3. 避免nil指针异常(使用proto结构的getter方法,可以正确处理nil指针)
  6. 错误处理-适当传播错误,
    1. 避免直接返回从依赖库或服务产生的错误,调用方可能无法理解错误信息,难以调试
  7. Deadline
    1. 客户端应该总是使用deadline来调用接口
    2. 服务端在必要的情况下检查deadline设置(避免过短或过长的Deadline)
      1. 过短的Deadline会导致操作无法在指定时间内完成,接口几乎总是失败
      2. 过长的Deadline可能会占用其他用户的资源(特定任务类型的情况下)
  8. 传播Deadline-服务继续调用其他服务或接口
    1. 直接重用客户端的context
      1. 优点:简单有效
      2. 缺点:依赖接口可能需要不同的deadline设置
    2. 为每个接口指定适当的deadline
      1. 优点:可以更早的取消调用(cancellation)
      2. 缺点:代码较多,可能过早取消
  9. 限速-服务在需要的情况下应该限制接口调用速率
    1. golang.org/x/time/rate
    2. 客户端也应该对接口调用限速(限制调用次数和速率,特别是在重试的情况下)
  10. 内存管理
    1. 限制并发goroutine(grpc-Go默认无限制)
      1. 设置listener限制和并发stream限制 golang.org/x/net/netutil
      2. 当太多的rpc请求在执行中时,使用Tap handler处理错误
      3. 健康报告和负载均衡
    2. 限制请求和回复payload大小
      1. 设置最大request payload size:grpc.MaxRecvMsgSize
      2. 防止产生过大回复请求
        1. 例如数据库查询(select * from …)
        2. API设计-使用stream返回,或者使用分页返回限制单次最大返回
  11. 日志
    1. 在错误时发生时详细记录错误上下文,便于调试
    2. 开发阶段使用Trace或Debug级别记录日志
    3. 使用日志分析工具进行统计和告警
  12. 监控
    1. 导出各种监控指标(响应时间,请求数,失败数,etc…),总和,平均,峰值,按接口分类
    2. 配置合适的告警策略

发表评论

电子邮件地址不会被公开。 必填项已用*标注