API 工程化分享( 三 )


如果公司内代码都在一起 , api 的定义都在一起 , 那么大仓绝对是最优解 , 其次才是 git submodules , 这也是 Google 的建议
我们倾向于最终 proto 的管理是集中在一个仓库里面 , 并且只有一份 , 不会做任何的 copy , 通过 submodules 引入到自己的微服务里面 , 也就是说你的微服务里面都会通过 submodules 把集中 API 的 git 拷贝到本地项目里面 , 但是它是通过 submodeles 的方式来承载的 , 然后你再通过一系列 shell 的工具让你的整个编译过程变得更简单
IDL Project LayoutProto Project Layout在统一仓库中管理 proto , 以仓库为名
根目录:

  • 目录结构和 package 对齐;
  • 复杂业务的功能目录区分;
  • 公共业务功能:api、rpc、type;

API 工程化分享

文章插图
 
目录结构和 package 对齐我们看一下 googleapis 大量的 api 是如何管理的?
第一个就是在 googleapis 这个项目的 github 里面 , 它的第一级目录叫 google , 就是公司名称 , 第二个目录是它的业务域 , 业务的名称
目录结构和 protobuf 的包名是完全对齐的 , 方便检索
复杂业务的功能目录区分v9 目录下分为公共、枚举、错误、资源、服务等等
公共业务功能:api、rpc、type在 googleapis 的根目录下还有类似 api、rpc、type 等公共业务功能
IDL Errors
  • Proto Errors
  • Proto Errors:Server
  • Proto Errors:Client
Proto Errors
  • 使用一小组标准错误配合大量资源
  • 错误传播
用简单的协议无关错误模型 , 这使我们能够在不同的 API , API 协议(如 gRPC 或 HTTP)以及错误上下文(例如 , 异步 , 批处理或工作流错误)中获得一致的体验 。
API 工程化分享

文章插图
 

API 工程化分享

文章插图
 
使用一小组标准错误配合大量资源服务器没有定义不同类型的“找不到”错误 , 而是使用一个标准 google.rpc.Code.NOT_FOUND 错误代码并告诉客户端找不到哪个特定资源 。状态空间变小降低了文档的复杂性 , 在客户端库中提供了更好的惯用映射 , 并降低了客户端的逻辑复杂性 , 同时不限制是否包含可操作信息 。
我们以前自己的业务代码关于404 , 关于某种资源找不到的错误码 , 定义了上百上千个 , 请问为什么大家在设计 HTTP restful 或者 grpc 接口的时候不用人家标准的状态码呢?人家有标准的404 , 或者 not found 的状态码 , 用状态码去映射一下通用的错误信息不好吗?你不可能调用一个接口 , 返回几十种具体的错误码 , 你根本对于调用者来说是无法使用的 。当我的接口返回超过3个自定义的错误码 , 你就是面向错误编程了 , 你不断根据错误码做不同的处理 , 非常难搞 , 而且你每一个接口都要去定义
这里的核心思路就是使用标准的 HTTP 状态码 , 比方说500是内部错误 , 503是网关错误 , 504是超时 , 404是找不到 , 401是参数错误 , 这些都是通用的 , 非常标准的一些状态码 , 或者叫错误码 , 先用它们 , 因为不是所有的错误都需要我们叫业务上 hint , 进一步处理 , 也就是说我调你的服务报错了 , 我大概率是啥都不做的 , 因为我无法纠正服务端产生的一个错误 , 除非它是带一些业务逻辑需要我做一些跳转或者做一些特殊的逻辑 , 这种不应该特别多 , 我觉得两个三个已经非常多了
所以说你会发现大部分去调用别人接口的时候 , 你只需要用一个通用的标准的状态码去映射 , 它会大大降低客户端的逻辑复杂性 , 同时也不限制说你包含一些可操作的 hint 的一些信息 , 也就是说你可以包含一些指示你接下来要去怎么做的一些信息 , 就是它不冲突
错误传播如果您的 API 服务依赖于其他服务 , 则不应盲目地将这些服务的错误传播到您的客户端 。


推荐阅读