API 工程化分享( 四 )


举个例子 , 你现在要跟移动端说我有一个接口 , 那么这个接口会返回哪些错误码 , 你始终讲不清楚 , 你为什么讲不清楚呢?因为我们整个微服务的调用链是 A 调 B , B 调 C , C 调 D , D 的错误码会一层层透传到 A , 那么 A 的错误码可能会是 ABCD 错误码的并集 , 你觉得你能描述出来它返回了哪些错误码吗?根本描述不出来
所以对于一个服务之间的依赖关系不应该盲目地将下游服务产生的这些错误码无脑透传到客户端 , 并且曾经跟海外很多公司 , 像 Uber , Twitter , Netflix , 跟他们很多的华人的朋友交流 , 他们都不建议大家用这种全局的错误码 , 比方 A 部门用 01 开头 , B 部门用 02 开头 , 类似这样的方式去搞所谓的君子契约 , 或者叫松散的没有约束的脆弱的这种约定
在翻译错误时 , 我们建议执行以下操作:

  • 隐藏实现详细信息和机密信息
  • 调整负责该错误的一方 。例如 , 从另一个服务接收 INVALID_ARGUMENT 错误的服务器应该将 INTERNAL 传播给它自己的调用者 。
比如你返回的错误码是4 , 代表商品已下架 , 我对这个错误很感兴趣 , 但是错误码4 在我的项目里面已经被用了 , 我就把它翻译为我还没使用的错误码6 , 这样每次翻译的时候就可以对上一层你的调用者 , 你就可以交代清楚你会返回错误码 , 因为都是你定义的 , 而且是你翻译的 , 你感兴趣的才翻译 , 你不感兴趣的通通返回 500 错误 , 就是内部错误 , 或者说 unknown , 就是未知错误 , 这样你每个 API 都能讲清楚自己会返回哪些错误码
API 工程化分享

文章插图
 
在 grpc 传输过程中 , 它会要求你要实现一个 grpc states 的一个接口的方法 , 所以在 Kraots 的 v2 这个工程里面 , 我们先用前面定义的 message Error 这个错误模型 , 在传输到 grpc 的过程中会转换成 grpc 的 error_details.proto 文件里面的 ErrorInfo , 那么在传输到 client 的时候 , 就是调用者请求服务 , service 再返回给 client 的时候再把它转换回来
也就是说两个服务使用一个框架就能够对齐 , 因为你是基于 message Error 这样的错误模型 , 这样在跨语言的时候同理 , 经过 ErrorInfo 使用同样的模型 , 这样就解决了跨语言的问题 , 通过模型的一致性
API 工程化分享

文章插图
 
Proto Errors:Server
API 工程化分享

文章插图
 
errors.proto 定义了 Business Domain Error 原型 , 使用最基础的 Protobuf Enum , 将生成的源码放在 biz 大目录下 , 例如 biz/errors
  • biz 目录中核心维护 Domain , 可以直接依赖 errors enum 类型定义;
  • data 依赖并实现了 biz 的 Reporisty/ACL , 也可以直接使用 errors enum 类型定义;
  • TODO:Kratos errors 需要支持 cause 保存 , 支持 Unwrap();
在某一个微服务工程里面 , errors.proto 文件实际上是放在 API 的目录定义 , 之前讲的 API 目录定义实际上是你的服务里面的 API 目录 , 刚刚讲了一个 submodules , 现在你可以理解为这个 API 目录是另外一个仓库的 submodules , 最终你是把这些信息提交到那个 submodules , 然后通过 reference 这个 submodules 获取到最新的版本 , 其实你可以把它打成一个本地目录 , 就是说我的定义声明是在这个地方
这个 errors.proto 文件其实就列举了各种错误码 , 或者叫错误的字符串 , 我们其实更建议大家用字符串 , 更灵活 , 因为一个数字没有写文档前你根本不知道它是干啥的 , 如果我用字符串的话 , 我可以 user_not_found 告诉你是用户找不到 , 但是我告诉你它是3548 , 你根本不知道它是什么含义 , 如果我没写文档的话
所以我们建议使用 Protobuf Enum 来定义错误的内容信息 , 定义是在这个地方 , 但是生成的代码 , 按照 DDD 的战术设计 , 属于 Domain , 因为业务设计是属于领域的一个东西 , Domain 里面 exception 它最终的源码会在哪?会在 biz 的大目录下 , biz 是 business 的缩写 , 就是在业务的目录下 , 举个例子 , 你可以放在 biz 的 errors 目录下


推荐阅读