目录

一、场景分析

二、微服务拆分的原则

三、微服务化带来的问题和解决思路


一、场景分析

在这个架构中,我们将用户、订单和商品相关的逻辑抽取成服务独立的部署,原本的Web工程和队列处理程序将不再直接依赖缓存和数据库,而是通过调用服务接口查询存储中的信息。

有了构思和期望之后,为了将服务化拆分尽快落地,你们决定抽调主力研发同学共同制定拆分计划。但是仔细讨论后你们发现,虽然对服务拆分有了大致的方向可还是有很多疑问

  • 服务拆分时要遵循哪些原则
  • 服务的边界如何确定?服务的粒度是怎样的?
  • 服务化之后会遇到哪些问题呢?我们又将如何来解决?

二、微服务拆分的原则

原则一,做到单一服务内部功能的高内聚和低耦合

项目中有用户服务和内容服务,用户信息中有“是否为认证用户”字段。组内有个同学在内容服务里有这么一段逻辑:如果用户认证字段等于1,代表是认证用户,那么就把内容权重提升。问题是判断用户是否为认证用户的逻辑应该内聚在用户服务内部,而不应该由内容服务判断,否则认证的逻辑一旦变更内容服务也需要一同跟着变更,这就不满足高内聚、低耦合的要求了。所幸我们在Review代码时及时发现了这个问题,并在服务上线之前修复了它。 

原则二,你需要关注服务拆分的粒度,先粗略拆分再逐渐细化

不过服务多了也会带来问题,像是服务个数的增加会增加运维的成本。再比如原本一次请求只需要调用进程内的多个方法,现在则需要跨网络调用多个RPC服务,在性能上肯定会有所下降拆分初期可以把服务粒度拆得粗一些,后面随着团队对于业务和微服务理解的加深,再考虑把服务粒度细化

原则三,拆分的过程,要尽量避免影响产品的日常功能迭代

拆分只能在现有一体化系统的基础上不断剥离业务独立部署,剥离的顺序你可以参考以下几点

1.优先剥离比较独立的边界服务(比如短信服务、地理位置服务),从非核心的服务出发减少拆分对现有业务的影响,也给团队一个练习、试错的机会;

2.当两个服务存在依赖关系时优先拆分被依赖的服务。比如内容服务依赖于用户服务获取用户的基本信息,那么如果先把内容服务拆分出来,内容服务就会依赖于一体化架构中的用户模块,这样还是无法保证内容服务的快速部署能力。

原则四,服务接口的定义要具备可扩展性

服务拆分之后,由于服务是以独立进程的方式部署,所以服务之间通信就不再是进程内部的方法调用而是跨进程的网络通信了。在这种通信模型下服务接口的定义要具备可扩展性,否则在服务变更时会造成意想不到的错误。 服务接口的参数类型最好是封装类,这样如果增加参数就不必变更接口的签名,而只需要在类中添加字段就可以了


三、微服务化带来的问题和解决思路

微服务化只是一种架构手段,有效拆分后可以帮助实现服务的敏捷开发和部署。但是由于将原本一体化架构的应用拆分成了多个通过网络通信的分布式服务,为了在分布式环境下协调多个服务正常运行,就必然引入一定的复杂度,这些复杂度主要体现在以下几个方面

1.服务接口的调用不再是同一进程内的方法调用而是跨进程的网络调用,这会增加接口响应时间的增加

我们就要选择高效的服务调用框架,同时接口调用方需要知道服务部署在哪些机器的哪个端口上,这些信息需要存储在一个分布式一致性的存储中,于是就需要引入服务注册中心, 这一点,是我在24讲会提到的内容。不过在这里我想强调的是,注册中心管理的是服务完整的生命周期,包括对于服务存活状态的检测

错综复杂的依赖关系

一个服务会依赖多个其它服务也会被多个服务所依赖,那么一旦被依赖的服务的性能出现问题产生大量的慢请求就会导致依赖服务的工作线程池中的线程被占满,依赖的服务也会出现性能问题。接下来问题就会沿着依赖网逐步向上蔓延,直到整个系统出现故障为止。 

3.服务拆分到多个进程后,一条请求的调用链路上涉及多个服务,那么一旦这个请求的响应时间增长或者是出现错误,我们就很难知道是哪一个服务出现的问题

这就需要引入分布式追踪工具,以及更细致的服务端监控报表。