单体服务的演进过程
最初业务刚开始
上面没有容灾的方案,服务端挂了,就直接挂了。
当业务有点发展以后,使用 nginx 做负载均衡,横向扩展服务,数据库升级一下。
在 DNS 上加负载均衡,使用 K8S 管理服务,使用 redis 增加缓存。
这个架构足以支持大部分初创项目。
优点
- 开发简单
- 测试简单
- 部署简单
缺点
- 难以理解和扩展
- 小改动也得全量更新
- 小问题容易触发大故障
- 能够支持的业务规模有限
微服务
单体能够承载的业务规模有限,当规模扩大的时候,就需要升级到微服务。
每个微服务都单独连接一个数据库。
优点
- 边界清晰的业务拆分
- 易开发,易理解,易维护
- 技术栈可相对独立
- 持续集成,持续部署更容易
- 按需对服务进行治理
- 稳定性更容易保障
缺点
- 增量了系统复杂度
- 数据拆分复杂度
- 难调试,难测试
- 跨服务修改麻烦
- 难部署
什么信号表明该考虑单体转微服务了
- 单体系统过度复杂
- 当前架构不能满意业务发展需要
- 研发效率低下,提交代码冲突
- 持续集成,持续交付比较困难,不太敢更新,小版本要等大版本,要死一起死
- 团队人员较多
如何启动?
开着飞机换引擎
在转型的过程中,很难零故障的完全转换。
需要公司或部门领导的支持,要有一个敢于扛责任的领导,在改造期间,要管理好预期收益,实际在转换期间是很难看到成果的。
建立服务迁移核心团队,需要经验,执行力强,自驱力强的队员。从一个小的服务开始,遇到问题不能跳过,一定要解决,完成这个服务形成最佳实践后,可以推广到整个团队。
微服务改造策略
- 由外向内,由边缘到核心
- 数据拆分,迁移和验证,可回滚 (要保证当微服务挂掉后,可以回滚到旧的服务)
- fork 请求,proxy 验证
- 定期复盘过程,总结可复制套路
- 汇报成果,让领导看到收益
微服务数据库拆分
- 数据不能乱,规则先确定
- 定义数据边界,避免数据冗余
- 数据库互相隔离,避免故障传递
接口聚类收敛
- 按功能聚类接口
- 避免微服务过微
- 避免调用链路过深
fork 请求
将老的服务上面的请求 fork 到新的服务上,比较结果是否一致。
- 循序渐进可回滚
- fork 请求,验证正确性
- 灰度逐步迁移
- 监控有无漏网请求
- 保证回滚可能性
单体到微服务改造案例
单体应用,有通知和打卡两个模块,一个 DB 读存数据
第一步,才代码上拆分,服务部署的方式没有改变。只是将 打卡 模块的代码抽出来。
第二步,数据库的拆分。依然还是一个单体,但连接两个数据库。
增加一个 DB 用来存储打开相关内容。
第三步,将打卡服务单独部署。承载 fork 的请求,然后比较新旧服务返回的结果是否一致。
注意同一个 DB 读取没有什么影响,但是写入需要做隔离。
第四步,通过一段时间的测试,确保服务测试通过后,就可以上线。
加一个 api_getway,将请求全部发到新服务上。这里要保留旧的服务,如果出现问题,随时回滚。
第五步,老的服务确实没有流量了,新服务完全稳定了,将老的服务删除。