我大概 2015 年时候对 GraphQL 有过一些想法,当时还在从事用户产品研发,想法主要还是围绕业务公网 API 的。现在我的工作有很长一段时间是围绕服务化相关问题,视角也就有所改变了。加之重温了华翼老师当年的 slide,产生了一些随想。很碎,但是记录下来。
优点
- 将数据获取需求一步送到服务端,减少 IO 往返次数
- 涉及数据过滤、剪裁时,使用简单(和 SQL 类似),下游可以较少考虑 RPC 开销优化之类的问题
- 灵活,下游无须为了新需求而请求上游排期开发、部署特定接口,自己就可以搞掂(同时也是缺点)
缺点
- 接口语义模糊,太过于“通用”,抽象泄漏
- 难以设计服务端缓存(无法预知查询语句)
- 难以治理(完全由用户定制查询类型,服务端难以做监控、告警、QoS 和保护熔断等)
- IDL 不明确,向后兼容困难(不知道下游是怎么用的)
折衷方案
首先要有 service mesh with sidecar(不能是 smart sdk 形式的)。
在 sidecar 上引入类似 API Gateway 的方式,允许服务提供方使用 GraphQL 设计接口,对内(后端服务)剪裁过滤数据处理查询,对外(调用方)暴露的是业务语义明确的简单 RPC 接口。
下游业务需求有变动时,可以在不变更 codebase 的情况下,单独向 sidecar 发布新增或者修改的 RPC 接口以及背后的 GraphQL 查询语句。
公网出口
针对公网出口(提供客户端接入)而非内网 SOA 的情况,设计部署一个 API Gatway 比让客户端用 GraphQL 更好。理由同上。
RESTful API 在公网出口上有着许许多多的优点,相应的开发调试工具链、软件库和中间件也都很成熟。很多文章阐述了这点,这里就不再重复。
识别拐点
评估引入这样一套机制的 ROI 时,除了看业务类型(内容主导?交易主导?),还有就是看业务现在的实际状况和短期未来的发展趋势。
下游的查询需求真的有这么多样化、变更频繁吗?如果不是,针对下游业务需求定制 RPC 接口,比丢一个万能的 GraphQL 接口给下游好。
查询真的有这么复杂吗?机房内网往返次数带来的延时放大真的有这么明显吗?业务本身真的对延时这么敏感吗?如果都不是,设计细粒度、正交的 RPC 接口(业务原语)由下游自行组装定制更好。
针对内网服务(SOA),如果公司研发人数超过 1000 且组织架构复杂,那么“治理”的优先级应该远远高于“优化”的,人灾带来的复杂度比技术灾影响概念更长远、更难事后优化挽回,因此也就更需要未雨绸缪。
即使是“折衷方案”,也在拐点靠前一点的位置做变更,不要为不存在或者还有很久才会来的需求做设计,后者很可能会随着时间推进演变为前者。