很多应用拆分成微服务,是为了承载高并发,往往一个进程扛不住这么大的量,因而需要拆分成多组进程,每组进程承载特定的工作,根据并发的压力用多个副本公共承担流量。
阻碍单体架构变为分布式架构的关键点就在于状态的处理。如果状态全部保存在本地,无论是本地的内存,还是本地的硬盘,都会给架构的横向扩展带来瓶颈。
所以要讲整个架构分成两个部分,无状态部分和有状态部分,而业务逻辑的部分往往作为无状态的部分,而将状态保存在有状态的中间件中,如缓存、数据库、对象存储、大数据平台、消息队列等。
容器和微服务是双胞胎,因为微服务会将单体应用拆分成很多小的应用,因而运维和持续集成会工作量变大,而容器技术能很好的解决这个问题。然而在微服务化之前,建议先进行容器化,在容器化之前,建议先无状态化,当整个流程容器化了,以后的微服务拆分才会水到渠成。
幂等的接口设计
由于存在重试的机制,就需要接口是幂等的
接口分为查询、插入、更新、删除等操作。
对于查询接口来讲,本身就是幂等的,不用做特殊的判断。
对于插入接口来讲,如果每一个数据都有唯一的主键,也能保证插入的唯一性,一旦不唯一,则会报错。
对于更新操作来讲,则比较复杂,分几种情况。
一种情况是同一个接口,前后调用多次的幂等性。另一种情况是同一个接口,并发环境下调用多次的正确性。
为了保持幂等性,往往要有一个幂等表,通过传入幂等参数匹配幂等表中ID的方式,保证每个操作只被执行一次,而且在实行最终一致性的时候,可以通过不断重试,保证最终接口调用的成功。
对于并发条件下,谁先调用,谁后调用,需要通过分布式锁如Redis,ZooKeeper等来实现同一个时刻只有一个请求被执行,如何保证多次执行结果仍然一致呢?则往往需要通过状态机,每个状态只流转一次。还有就是乐观锁,也即分布式的CAS操作,将状态的判断、更新整合在一条语句中,可以保证状态流转的原子性。乐观锁并不保证更新一定成功,需要有对应的机制来应对更新失败。
容器的技术部分
容器运行时
看起来是隔离的技术,namesapace
用起来是隔离的技术,cgroup
当容器平台规模不是很大的时候,Docker Swarm Mode还是比较好用的:
- 集群的维护不需要ZooKeeper,不需要Etcd,自己内置
- 命令行和Docker一样的,用起来顺手
- 服务发现和DNS是内置的
- Docker Overlay网络是内置的
当规模比较大,应用比较复杂的时候,则推荐Kubernetes。
可以尝试一下docker swarm的方式来进行