说到大规模微服务系统,往往是一些7*24时不间断运行的在线系统,这样的系统往往有以下的要求:
第一,高可用。这类的系统往往需要保持一定的SLA的,7*24时不间断运行不代表完全不挂,而是有一定的百分比的。例如我们常说的可用性需达到4个9(99.99%),全年停机总计不能超过1小时,约为53分钟,也即服务停用时间小于53分钟,就说明高可用设计合格。
第二,用户分布在全国。大规模微服务系统所支撑的用户一般在全国各地,因而每个地区的人,都希望能够就近访问,所以一般不会一套系统服务全国,而是每个地区都要有相应的业务单元,使得用户可以就近访问。
第三,并发量大,存在波峰波谷。微服务之所以规模比较大,其实是承载的压力比较大,而且需要根据请求的波峰波谷进行弹性伸缩。
第四,有故障性能诊断和快速恢复的机制。大规模微服务场景下,运维人员很难进行命令式手动运维来控制应用的生命周期,应该采用声明式的运维方法。另外一旦有了性能瓶颈或者故障点,应该有自动发现定位的机制,迅速找到瓶颈点和故障点,及时修复,才能保障SLA。
战略设计
为了满足以上的要求,这个系统绝不是运维组努力一把,或者开发组努力一把,就能解决的,是一个端到端的,各个部门共同完成的一个目标,所以我们常称为战略设计。
第一,研发
一个能支撑高并发,高可用的系统,一定是需要从研发环节就开始下功夫的。
首先,每一个微服务都有实现良好的无状态化处理,幂等服务接口设计。
状态分为分发,处理,存储几个过程,如果对于一个用户的所有的信息都保存在一个进程中,则从分发阶段,就必须将这个用户分发到这个进程,否则无法对这个用户进行处理,然而当一个进程压力很大的时候,根本无法扩容,新启动的进程根本无法处理那些保存在原来进程的用户的数据,不能分担压力。
所以要讲的整个架构分成两个部分,无状态部分和有状态部分,而业务逻辑的部分往往作为无状态的部分,而将状态保存在有状态的中间件中,如缓存,数据库,对象存储,大数据平台,消息队列等。
这样无状态的部分可以很容易的横向扩展,在用户分发的时候,可以很容易分发到新的进程进行处理,而状态保存到后端。而后端的中间件是有状态的,这些中间件设计之初,就考虑了扩容的时候,状态的迁移,复制,同步等机制,不用业务层关心。
对于数据的存储,主要包含几类数据:
- 会话数据等,主要保存在内存中。对于保存在内存里的数据,例如Session,可以放在外部统一的缓存中。
- 结构化数据,主要是业务逻辑相关。对于业务相关的数据,则应该保存在统一的数据库中
- 文件图片数据,比较大,往往通过CDN下发。对于文件,照片之类的数据,应该存放在统一的对象存储里面
- 非结构化数据,例如文本,评论等。对于非结构化数据,可以存在在统一的搜索引擎里面,例如ElasticSearch。
但是还有一个遗留的问题,就是已经分发,正在处理,但是尚未存储的数据,肯定会在内存中有一些,在进程重启的时候,数据还是会丢一些的,那这部分数据怎么办呢?
这部分就需要通过重试进行解决,当本次调用过程中失败之后,前序的进程会进行重试,例如Dubbo就有重试机制。既然重试,就需要接口是幂等的,也即同一次交易,调用两次转账1元,不能最终转走2元。
接口分为查询,插入,更新,删除等操作。
对于查询接口来讲,本身就是幂等的,不用做特殊的判断。
对于插入接口来讲,如果每一个数据都有唯一的主键,也能保证插入的唯一性,一旦不唯一,则会报错。
对于更新操作来讲,则比较复杂,分几种情况。
一种情况是同一个接口,前后调用多次的幂等性。另一种情况是同一个接口,并发环境下调用多次的正确性。
为了保持幂等性,往往要有一个幂等表,通过传入幂等参数匹配幂等表中ID的方式,保证每个操作只被执行一次,而且在实