凡事都有两面性,微服务也不例外,微服务相对于单体应用来说具有很多的优势,当然也有它的不足,主要体现在如下方面。

  • 微服务的复杂度
  • 分布式的事务
  • 服务的划分
  • 服务的部署

1.3.1 微服务的复杂度

构建一个微服务系统并不是一件容易的事,微服务是分布式系统,构建的复杂度远远超过单体系统,开发人员需要付出一定的学习成本去掌握更多的架构知识和框架知识。服务与服务之间通过HTTP协议或者消息传递机制通信,开发者需要选出最佳的通信机制,并解决网络服务较差时带来的风险。

另外服务与服务之间相互依赖,如果修改某一个服务,会对另一个服务产生影响,如果掌控不好,会产生不必要的麻烦。由于服务的依赖性,测试也会变得很复杂,比如修改一个比较基础的服务,可能需要重启所有的服务才能完成测试。

1.3.2 分布式事务

微服务架构所设计的系统是分布式系统。分布式系统有一个著名的CAP理论,即同时满足“一致性”“可用性”和“分区容错”是一件不可能的事。CAP理论是同Eric Brewer在2000年PODC会议上提出的,该理论在两年后被证明成立。CAP理论告诉架构师不要妄想设计出同时满足三者的系统,应该有所取舍,设计出适合业务的系统。

  • Consistency:指数据的一致性。如果写入某个数据成功,之后读取,读到的都是新写入的数据;如果写入失败,之后读取的都不是写入失败的数据。
  • Availability:指服务的可用性。
  • Partition-tolerance:指分区容错。

在分布式系统中,P是基本要求,而单体服务是CA系统。微服务系统通常是一个AP系统,即同时满足了可用性和分区容错。这就有了一个难题:在分布式系统中如何保证数据的一致性?这就是大家经常讨论的分布式事务。

在微服务系统中,每个服务都是独立的进程单元,每个服务都有自己的数据库。通常情况下,只有关系型数据库在特定的数据引擎下才支持事务,而大多数非关系型数据库是不支持事务的,例如MongDB是不支持事务的,而Redis是支持事务的。在微服务架构中,分布式事务一直都是一个难以解决的问题,业界给出的解决办法通常是两阶段提交。

网上购物在日常生活中是一个非常普通的场景,假设我在淘宝上买了一部手机,需要我从我的账户中扣除1000元钱,同时手机的库存数量需要减1。当然需要在卖方的账户中加1000元钱,为了使案例简单化,暂时不考虑。

如果这是一个单体应用,并且使用支持事务的MySQL数据库(InnoDB数据库引擎才支持事务),我们可以这样写代码:

@Transactional
public void update() throws RuntimeException{
	updateAccountTable();  //更新账户表
	updateGoodsTable(); //更新商品表
}

如果是微服务架构,账户是一个服务,而商品是一个服务,这时不能用数据库自带的事务,因为这两个数据表不在一个数据库中。因此常常用以两阶段提交。

第一阶段,service-account发起一个分布式事务,交给事务协调器TC处理,事务协调器TC向所有参与的事务的节点发送处理事务操作的准备操作。所有的参与节点执行准备操作,将Undo和Redo信息写 进日志,并身事务管理器返回准备操作是否成功。

第二阶段,事务管理器收集所有节点的准备操作是否成功,如果都成功,则通知所有的节点执行提交操作;如果有一个失败,则执行回滚操作。

两阶段提交,将事务分成两部分能够大大提高分布式事务成功的概率。如果在第一阶段都成功了,而执行第二阶段的某一个节点失败,仍然导致数据的不准确,这时一般需要人工去处理,这就是当初在第一步记录日志的原因。另外,如果分布式事务涉及的节点很多,某一个节点的网络出现异常会导致整个事务处理阻塞状态,大大降低数据库的性能。所以一般情况下,尽量少用分布式事务。

1.3.3 服务的划分

将一个完整的系统拆分成很多个服务,是一件非常困难的事,因为这涉及了具体的业务场景,比命名一个类更加困难。对于微服务的拆分原则,Martin Fowler给出的建议是;服务是可以严格的边界。当然这个原则很抽象,根据具体的业务场景来拆分服务,需要依靠团队人员对业务的熟悉程序和理解程序,并考虑与已有架构的冲突、业务的扩展性、开发的风险和未来业务的发展等诸多因素。

领域驱动设计是一个全新的概念,也是一个比较理想的微服务拆分的理念。领域驱动设计通过代码和数据分析找到合理的切分点,并通过数据分析来判断服务的划分边界和划分粒度。目前来说,在中国几乎没有公司去落地领域驱动设计这个理念,随着微服务的发展,这一理念在以后可能会落地。

1.3.4 服务的部署

一个简的单体系统可能只需要将程序集群部署并配置负载均衡服务器即可,而部署一个复杂的微服务架构的系统就复杂得多。因为每一个微服务可能还涉及比较底层的组件,例如数据库、消息中间件等。微服务系统往往由数量众多的服务构成,例如Netflix公司有大约600个服务,而每个服务又有大量的实例。微服务系统需要对每个服务治理、监控和管理等,而每个服务有大量的配置,还需要考虑服务的启动时机等。

部署微服务系统,需要开发人员或者运维人员对微服务系统有足够强的控制力。随着云计算和云服务器的发展,部署微服务系统并不是一件难事,例如使用PaaS服务、使用Docker编排等。这就是人们往往提到微服务,就会想到Docker、DevOps的原因。其中,微服务是核心;Docker为容器技术,是微服务最佳部署的容器;DevOps是一种部署手段或理念。