Skip to content

Latest commit

 

History

History
33 lines (17 loc) · 4.91 KB

File metadata and controls

33 lines (17 loc) · 4.91 KB

微服务

如何拆分?

系统设计是一种创作,而不是应试,不可能每一位架构师设计的服务粒度全都相同,微服务的大小、边界不应该只有唯一正确的答案或绝对的标准,但是应该有个合理的范围,笔者称其为微服务粒度的上下界。我们可以分析如果微服务的粒度太小或者太大会出现哪些问题,从而得出服务上下界应该定在哪里。

可能是受微服务名字中“微”的“蛊惑”,笔者听过不少人提倡过微服务越小越好,最好做到一个 REST Endpoint 就对应于一个微服务,这种极端的理解肯定是错误的,如果将微服务粒度定的过细,会受到以下几个方面的反噬:

  • 从性能角度看,一次进程内的方法调用(仅计算调用,与方法具体内容无关),耗时在零(按方法完全内联的场景来计算)到数百个时钟周期(按最慢的虚方法调用无内联缓存要查虚表的场景来计算)之间;一次跨服务的方法调用里,网络传输、参数序列化和结果反序列化都是不可避免的,耗时要达到毫秒级别,你可以算一下这两者有多少个数量级的差距。远程服务调用里已经解释了“透明的分布式通信”是不存在的,因此,服务粒度大小必须考虑到消耗在网络上的时间与方法本身执行时间的比例,避免设计得的过于琐碎,客户端不得不多次调用服务才能完成一项业务操作,譬如,将字符串处理这样的功能设计为一个微服务便是不合适的,这点要求微服务从功能设计上看应该是完备的。

  • 从数据一致性角度看,每个微服务都有自己独立的数据源,如果多个微服务要协同工作,我们可以采用很多办法来保证它们处理数据的最终一致性,但如果某些数据必须要求保证强一致性的话,那它们本身就应当聚合在同一个微服务中,而不是强行启用XA 事务来实现,因为参与协作的微服务越多,XA 事务的可用性就越差,这点要求微服务从数据一致性上看应该是内聚(Cohesion)的。

  • 从服务可用性角度看,服务之间是松散耦合的依赖关系,微服务架构中无法也不应该假设被调用的服务具有绝对的可用性,服务可能因为网络分区、软件重启升级、硬件故障等任何原因发生中断。如果两个微服务都必须依赖对方可用才能正常工作,那就应当将其合并到同一个微服务中(注意这里说的是“彼此依赖对方才能工作”,单向的依赖是必定存在的),这条要求微服务从依赖关系上看应该是独立的。

综合以上,我们可以得出第一个结论:微服务粒度的下界是它至少应满足独立——能够独立发布、独立部署、独立运行与独立测试,内聚——强相关的功能与数据在同一个服务中处理,完备——一个服务包含至少一项业务实体与对应的完整操作。

网关

Zuul VS Spring Cloud Gateway

在 Spring Cloud Gateway 出现之前,网关都是用 Zuul 构建的,虽然 Netflix 开源了 Zuul2,由于各种原因,官方并没有打算将 Zuul2 集成到 Spring Cloud 体系中。而是自己研发了一个全新的网关 Spring Cloud Gateway,由于 Zuul1 基于 Servlet 构建,使用的是阻塞的 IO,性能并不是很理想。Spring Cloud Gateway 则基于 Spring 5、Spring boot 2 和 [Reactor] 构建,使用 Netty 作为运行时环境,比较完美的支持异步非阻塞编程。

官方提供的压测报告显示 Spring Cloud Gateway 的性能是 Zuul 的 1.5 倍,Spring Cloud Gateway 刚出不久,稳定性有待验证,主要是缺乏大规模流量的验证,而 Zuul 开源的时间较长,同时在 Netflix 内部经过了大规模流量的验证,比较稳定。长期发展来说,Spring Cloud Gateway 的优势比较大,毕竟官方主推。

参考

微服务架构:稳定性设计

如何优雅关闭服务

发布策略