并发与高并发(二十)高并发の应用拆分思路
前言
这一章节我们将讲解高并发解决方案中的应用拆分思路,也可以称之为系统拆分。单个服务器再优化,它的处理都是有上限的,因此我们采用扩容、缓存、消息队列等对程序进行优化,这些手段都可行,但还不是全部。随着项目的需求要求越来越多,应用自然会跟着越来越大,因此呢,架构师设计出了特别容易扩展的方案,从整体将一个应用拆分成多个应用。当然应用也不是随便拆的,需要根据项目的实情,一般大家会根据应用的功能模块(比如从一个大的交易系统中拆分出订单系统和产品系统等等)。
主体概要
- 股票系统拆分举例
- 应用拆分的基本原则和思考
- 应用拆分组件
主体内容
一、股票系统拆分举例
1.拆分图
图中我们对行情中心进行了又一次拆分(定时任务、流程处理)。
这样拆分完其实不止是光有好处,其实也是有弊端的:
一个应用被拆分成多个,它必然会带来管理上的复杂性,之前管理好一个应用就可以了,拆分完可能是十几个或者几十个,管理成本必然提高,这就带来服务器的成本随之提高。另外,应用多列,势必会带来网络的开销,任何子应用互相间的调用必然需要网络开销。
二、应用拆分的基本原则和思考
1.基本原则
- 业务优先:确定业务边界,每一个系统天然的会根据多个功能分成多个模块,每个模块又包含许多业务相关的功能,在拆分时,我们就按照业务边界进行切割,切割完成再针对每个模块进行拆解,类似于“庖丁解牛”,找到关键点。
- 循序渐进:边拆分边测试,拆分和测试是需要并行进行的,二者缺一不可。每一步拆分完成要测试,保证系统功能的完整性。
- 兼顾技术:重构、分层,系统不能为了分布式而分布式,系统拆分的代价相当的昂贵。分层指的就是针对熟悉前端的拆分,熟悉后端的拆分,熟悉数据库的拆分...便于合适的人做合适的事情。
- 可靠测试
2.应用拆分-思考
- 应用之间的通信:RPC(dubbo等)、消息队列:消息传输适用于传输数据包小但是数据量大,对实时性要求不高的场景。比如下单成功后通过短信通知用户。而选用RPC框架实时性更高一些。
- 应用之间的数据库设计:每个应用都有独立的数据库
- 避免事务操作跨应用:分布式事务是一个非常消耗资源的问题。这样应用和应用的耦合度降低,某一个应用挂了后不影响其他应用的运行。
三、应用拆分组件
- Dubbo
- Spring Cloud
1.Dubbo
(1)介绍:Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。
(2)结构图
解释:
Consumer:服务消费者
Provider:服务提供者
Container:服务容器
消费者(Consumer)要使用服务提供者(Provider)的服务,要通过invoke方法(红色实线箭头sync是同步的意思)。调用的时候,服务提供者(Provider)的位置相对于消费者(Consumer)是透明的。同一个Consumer调用两次Provider的相同服务,对应的Provider是不一定的(就是Provider的位置是不确定的)。
我们说一个完整的流程:首先,Provider的start方法启动,调用Registry的register方法(通常我们选择注册到zookeeper上)。而消费者Consumer通过subscribe方法来订阅服务,如果没有订阅到自己想获得的服务,它会不断的尝试订阅。新的服务如果注册到了Registry注册中心,注册中心会通过notify方法通知到消费者。Monitor在这里是一个监控的角色,图中红色虚线代表的是Consumer和Provider是通过异步的方式发送消息给Monitor。Monitor在整个架构中是可选的,使用Monitor的话需要配置,如果不配置或者出问题,它会挂掉,但不影响服务的调用。比如以上的股票系统中Consumer就是拆分后剩下的部分,而Provider就是拆分的子应用。
2.Spring Cloud
(1)介绍:Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
(2)结构图
(3)我们通过更加实际的例子理解一下Spring Cloud的具体特征。
官方理解是它是一些独立的服务共同组成整个系统,每个服务有独立的业务开发,他们是分布式管理的,非常强调隔离性;是按照业务而不是技术来划分组件的,它是有生命的产品而不是项目;自动化运维;具有高度的容错性;可以快速的演化和迭代。
微服务通常是从重写一个模块开始的,要想把整个特别大的应用重写,是由很大的风险的,也不一定有这个必要。我们向微服务迁移的时候,通常从耦合度最低的模块开始,对扩展性要求最高的模块开始,把他们一个一个剥离出来。
图中的API Gateway并不是为了重用代码,而是减少客户端和服务间的往来。微服务通常是直接面对客户的。
(4)要想实际使用微服务,我们需要解决四个问题
- 客户端如何访问这些服务:API Gateway提供统一的服务入口,对前台透明,同时可以聚合后台的服务,提供安全过滤流控等api的管理功能。
- 每个服务之间是如何通信的:异步的话使用消息队列,同步调用使用REST或者是RPC,Rest可以使用springboot,RPC通常使用Dubbo;同步调用一致性强但是出现调用问题,REST一般基于http实现,能够跨客户端,同时对客户端没有更多的要求。同步中的RPC的传输协议更高效,安全也更加可控。特别是在一个公司内部如果有统一的开发规范和统一的框架,它的开发效率会更加明显。而异步消息在分布式系统中有特别广泛的应用,它既能减少调用服务之间的耦合,又能成为调用之间的缓冲,确保消息积压不会冲垮被调用方。同时保证调用方的用户的体验,继续干自己的活。付出的代价是一致性的减慢,需要接受数据的最终一致性。
- 如此多的服务如何实现:在微服务架构中一般每一服务都会拷贝进行负载均衡,服务如何相互感知,如何相互管理,这就是服务发现的问题了,一般都是进行服务注册信息的分布式管理。
- 服务挂了该如何解决:分布式最大的特性就是网络是不可靠的,当系统是由一系列的调用链组成的时候,其中任何一个出问题都不至于影响到整个链路。相应的手段有:重试机制、应用的限流、熔断机制、负载均衡、系统降级...