『数据库』微服务化的基石——持续集成


一、持续集成对于微服务的意义:拆之前要先解决合的问题在很多微服务化的文章中 , 很少会把持续集成放在第一篇 , 因为大多数的文章都会将如何拆的问题 , 例如拆的粒度 , 拆的时机 , 拆的方式 。
为什么需要拆呢?因为这是人类处理问题的本质方式:将一个大的复杂问题 , 变成很多个小问题解决 。
所以当一个系统复杂到一定程度 , 当维护一个系统的人数多到一定程度 , 解决问题的难度和沟通成本大大提高 , 因而需要拆成很多个工程 , 拆成很多个团队 , 分而治之 。
然而当每个子团队将子问题解决了 , 整个系统的问题就解决了么?你可以想象你将一辆整车拆成零件 , 然后再组装起来的过程 , 你就可以想象拆虽然不容易 , 合则更难 , 需要各种标准 , 各种流水线 , 才能将零件组装称为车 。
我们先来回顾一下拆的过程 。
最初的应用大多数是一个单体应用:
『数据库』微服务化的基石——持续集成
本文插图

一个Java后端 , 后面跟一个数据库 , 基本上就搞定了 。
随着系统复杂度的增加 , 首先Java程序需要做的是纵向的拆分 。
『数据库』微服务化的基石——持续集成
本文插图

  1. 首先最外面是一个负载均衡 , 接着是接入的Nginx , 做不同服务的路由 。
  2. 不同的服务拆成独立的进程 , 独立部署 , 每个服务使用自己的数据库和缓存 , 解决数据库和缓存的单点瓶颈 。
  3. 数据库使用一主多从的模式 , 进行读写分离 , 主要针对读多写少的场景 。
  4. 为了承载更多的请求 , 设置缓存层 , 将数据缓存到Memcached或者Redis中 , 增加命中率 。
  5. 当然还有些跨服务的查询 , 或者非结构化数据的查询 , 引入搜索引擎 , 比关系型数据库的查询速度快很多 。

『数据库』微服务化的基石——持续集成
本文插图

在高并发情况下 , 仅仅纵向拆分还不够 , 因而需要做真正的服务化 。
一个服务化的架构如图所示 。
  1. 首先是接入层 , 这一层主要实现API网关和动态资源和静态资源的分离及缓存 , 并且可以在这一层做整个系统的限流 。
  2. 接下来是Web层 , 也就是controller , 提供最外层的API , 是对外提供服务的一层 。
  3. 下面是组合服务层 , 有时候被称为编排层 , compose层 , 是实现复杂逻辑的一层 。
  4. 下面是基础服务层 , 是提供原子性的基本的逻辑的一层 , 他下面是缓存 , 数据库 。
  5. 服务之间需要治理 , 需要相互发现 , 所以一般会有dubbo或者springcloud一样的框架 。
  6. 对所有的服务 , 都应该有监控告警 , 及时发现异常 , 并自动修复或者告警运维手动修复 。
  7. 对于所有的服务的日志 , 应该有相同的格式 , 收集到一起 , 称为日志中心 , 方便发现错误的时候 , 在统一的一个地方可以debug 。
  8. 对于所有的服务的配置 , 有统一的管理的地方 , 称为配置中心 , 可以通过修改配置中心 , 下发配置 , 对于整个集群进行配置的修改 , 例如打开熔断或者降级开关等 。
通过简单的描述 , 大家可以发现 , 从一个简单的单体应用 , 变成如此复杂的微服务架构 , 除了关心怎么拆的问题 , 还必须关注:
  • 如何控制拆的风险
  • 如何保证代码质量
  • 如何保证功能不变 , 不引入新的Bug
答案当然就是集成 , 从一开始就集成 , 并且不断的集成 , 反复的将拆分的模块重新组合 , 看看是否能够顺利组合起来 , 并且保证功能的不变 。


推荐阅读