编排还是编舞,暨近几年工作回顾
第一次听到编排,还是在学习 K8S 时,了解到容器的编排。后来在微服务架构的实践中,也常听到服务编排这个词组。
对服务编排的实践,主要限于 BFF 层。最近几年的开发工作,主要都在 BFF 层,编排后端服务,为前端提供一个统一的服务界面。
细节上有些变化,但总体上就是做了个服务编排的工作而已。
第一阶段
之前使用 gRPC 调用后端服务,给前端提供 Restful 接口;
第二阶段
后来使用 restful 调用后端服务,给前端提供 restful 接口,相当于一个手写的网关。这时了解到了 bulk api,可以满足前端批量调用接口的需求,不过没有投入实践;
第三阶段
如今使用 restful 调用后端服务,给前端提供 graphql 接口,相当于跳过了 bulk api 阶段。
快速回顾
总之,近几年的饭碗是靠微服务架构的流行所赏赐的。在单体架构的时候,我是会饿死的。
以上就是会饿死我的单体架构示意图,虽然它仍然有存在的价值,但是最近几年换了几家公司,都不再用它了,都迁移到或者直接就上微服务了,微服务和单体架构的对比可以简列如下:
单体 | 微服务 |
全量部署,简单粗暴 | 局部部署 |
要么成功、要么失败 | 优雅降级 |
跨模块修改很普遍 | 清晰的模块边界 |
技术栈统一 | 技术栈多样 |
垂直扩展 | 水平扩展 |
共享数据存储 | 分离的数据存储 |
所有人共享 | 单一开发人员或者团队拥有 |
当然,仅有微服务,我还是没有饭吃,因为前端可以直接访问微服务呀:
从上图的一团乱麻可以看出,点对点的 API 访问非常繁杂。而且,服务越多,API 调用越繁杂。
以上的调用,在增加前端和服务之后:
为了解决前端到服务的调用变成一团乱麻的问题,业界引入了网关层,也给了我一碗饭吃:
前面提到,我的饭碗进入到第二阶段时,主要是在手写网关层,这个网关层由几个 BFF 项目构成。
可以见到,手写网关层,导致了调用关系的更加繁杂。这时虽然了解到了 bulk api,但是没有投入实践。跳过了 bulk api,直接开始实践 GraphQL。GraphQL 和 restful API 的对比如下:
GraphQL | REST | |
架构 | 客户端驱动 | 服务器端驱动 |
组织形式 | 模式与类型系统 | 服务端点 |
操作 | 查询、修改、订阅 | 创建、读取、更新、删除 |
数据获取 | 单 API 调用获取定制化的数据 | 多 API 调用获取固定的数据 |
社区 | 成长中 | 巨大 |
性能 | 快 | 多网络调用更加耗时 |
开发速度 | 更快 | 更慢 |
学习曲线 | 陡峭 | 较平缓 |
自文档 | 自带 | 不支持 |
文件上传 | 不支持 | 支持 |
缓存 | 需要通过上层库来完成 比如 Apollo Response Cache,以及启用 APQ 实现 CDN 缓存 | 支持 |
稳定性 | 不容易出错,自动验证以及类型检查 | 对复杂的查询来说是更好的选择 |
使用场景 | 多微服务、移动端应用 | 简单的应用、资源驱动的应用 |
未来展望
以上三个阶段全部是在请求驱动的架构下工作,做的工作都是服务编排的范畴。GraqphQL 是个明显的趋势,未来还需要继续学习,引入并实战 GraphQL Federation。
最早在《基于微服务的事件驱动系统的架构考量》中接触到事件驱动的架构这一概念,并同时接触到了编舞这个词,不过还没有在工作中实践过,仅仅在参与一个异步 API 的黑客松时,浅尝了一下。后续在实际使用一段时间后,再来分享,这里先放个编排与编舞的对比表格:
编排 | 编舞 | |
实时性 | 同步 | 异步 |
扩展性 | 点对点集成 | 易扩展 |
一致性 | 强一致 | 最终一致 |
耦合性 | 强耦合 | 松耦合 |
领域知识 | 需要 | 很少甚至不需要 |
可观测性 | 清晰的工作流 | 缺少整体状态 |
性能考量 | 延时 | 吞吐 |
应用环境 | 限界上下文之内 | 限界上下文之间 |