参考教程:
https://www.bilibili.com/video/av113820458553104/
主要是根据视频进行微服务中一些基本概念的扫盲。
分布式基础 - Nacos - OpenFeign - Sentinel - Gateway - Seata
1.1 单体架构
单体架构:all in one,所有的模块都在一个项目。
- 项目进行打包,打包成一个可执行jar包,买个服务器,上传应用;再买一台服务器部署数据库。而用户要访问我们的应用,需要买一个公网IP,但是ip地址不好记,所以再买一个域名(将域名和ip进行绑定)。一个服务器就是一个节点
特点:开发部署简单;但是无法应对高并发。
单体架构将所有模块集成在一个项目中,通过打包成可执行的 Jar 包部署到服务器,并搭配数据库来实现应用功能。用户访问应用时,需通过绑定域名与公网 IP 来定位服务器。其优势在于开发与部署流程较为简单,但面对高并发场景时存在性能瓶颈。
1.2 集群架构
如果只有这一台服务器,大量用户访问就会卡死。我们把这样的服务器多复制上几份,多搞几个副本就行了。一堆服务器在一起工作就叫做集群。
用户访问一个域名,然后这个域名指向任何一个服务器都能运行。但是你还是只能指向一个服务器,没吊用啊。所以要用到网关(企业中主流的是Nginx),将网关部署到一个服务器上面,让域名绑定这个服务器的公网IP,用户访问这个域名,相当于来到了这个网关。但是网关无法处理业务请求,所以网关要把收来的业务请求转给下面处理业务的服务器。所以网关的功能是:请求的路由。
但是在路由期间,不能把所有的请求转给某一个服务器,所以这里要用到负载均衡的算法均摊给每一个服务器。所以网关是所有请求流量的入口。
最后,这些服务器在做业务期间,要操作数据库,依然连向数据库。一个数据库可能也存不下,所以对数据库也进行副本复制,形成数据库集群,让商场应用随便连上数据库集群中的某一个数据库。
集群架构就是解决大并发问题的,那么这里涉及到一个场景,比如说:双十一的时候,淘宝访问量巨大,所以对服务器集群进行扩容;而等到双十一过去之后,访问量没有那么大了,就可以对服务器集群进行缩容,就是把多购买的服务器释放掉。如何扩缩就根据当前的请求量和业务量进行选择即可。
集群架构已经能解决很多问题了,而且大部分公司也在使用,为什么要分布式?
Q1:订单功能要进行升级:v1.0,v2.0等,如果要把新的订单版本部署到服务器,由于现在所有的代码还是在单体架构中,要把整个项目重新打包,把所有服务器的项目下线,重新部署。模块化升级会导致牵一发动全身。
Q2:现在要用直播功能,涉及到流媒体服务器,JAVA又不太行,要用cpp开发直播模块,那么直播模块就不能搞一个jar包去调用方法了。也就是多语言团队如何分工合作?
1.3 分布式架构
分布式:一个大型应用被拆分成很多小应用分布部署在各个机器;是一种工作方式
集群:是一种物理形态,很多机器就叫做集群。
微服务(自治)独立部署、数据隔离、语言无关
负载均衡、单点故障、服务雪崩、服务熔断
远程调用 Remote Procedure Call RPC:HTTP+JSON
分布式事务
**微服务:**把整个商场应用按照功能模块进行拆分,拆成一个个的小应用,这些小应用就叫做“微服务”。数据库也可以垂直拆分,按照业务边界进行拆分。每个微服务只连自己的数据库,每一个微服务是语言无关的。
所以,每一个服务器就部署多个微服务。
Q1:能不能把所有的商品微服务放在同一个服务器上?
A:出现单点故障问题,鸡蛋不能放在一个篮子里。
那么就又会出现一个问题,用户需要查订单(远程调用,Remote Procedure Call,RPC,RPC有多种,其中发一个HTTP请求,让订单返回json数据,就是一种),但是订单在别的服务器,而且可能在多个服务器上,怎么找呢?
流程如下:
某个微服务注册上线了,就连上注册中心,告诉注册中心,我是订单,我在xxx服务器。下线了,也要告诉注册中心。那么注册中心里面就会有一个[服务-ip]的清单列表,order[0.6,0.5], product[0.4,0.5]…
那么,用户就可以先问注册中心,订单在哪些服务器有?注册中心告诉他订单在哪。这个过程叫做“服务发现”;那么同理,也要负载均衡,上一次连0.5下一次连0.6等;
之前进行模块化升级,是要下线上线重新部署。而注册中心,同时也可以作为配置中心,所有的配置都放在一起。统一管理所有的配置修改,并且将配置变更推送给对应的模块。
**服务雪崩:**订单要调用支付功能,一切正常的时候,调用完成,数据返回,资源释放。如果支付卡住了,百万请求调用订单,订单调用支付,都卡死了。而其他模块调用订单也会卡死,所以一个微服务的卡顿会导致一个调用链的卡顿。而且在高并发的情况下,调用链有百万个请求的卡顿。最终导致服务雪崩。在微服务之间进行服务调用是由于某一个服务故障,导致级联服务故障的现象,称为雪崩效应。雪崩效应描述的是提供方不可用,导致消费方不可用并将不可用逐渐放大的过程。
服务熔断: RPC期间,用户发起对订单调用了,如果我发现订单卡了,我不等你,我直接快速返回。调用链都很快的情况下,就不会导致请求挤压。比如说我在熔断里面配置:5s内50%的请求都卡顿,那么之后的请求就直接返回“失败”。
那么现在如何访问呢?用户访问的是域名,但是每个服务器的微服务不是完整的应用,所以还是要用到网关。那么网关还是做请求路由,比如说发的是以/order/xxx
的请求,那么就发给订单所在的服务器,但是网关又不知道订单在哪些服务器,所以还是要问一下注册中心,那么继续往下转。
微服务进行业务处理的时候,就访问自己的数据库。但是现在数据库也是分散的,所以就出现了另一个问题,分布式事务。
1.4 分布式事务
- 如果事务对数据一致性要求非常高且业务流程简单,可以选择 两阶段提交(2PC)。
- 如果业务流程较长且复杂,可以采用 SAGA 模式,通过补偿操作来处理事务。
- 如果希望对业务逻辑的侵入性较小,且能够兼顾性能和一致性,可以考虑 TCC 模式。
- 如果需要解耦服务,提高系统的灵活性和可扩展性,可以采用 消息驱动的事务 处理方式。
在分布式架构中,微服务通常会有自己的数据库。当一个业务操作需要跨多个微服务(也就是跨多个数据库)时,就会出现分布式事务问题。简单来说,就是如何确保这些跨数据库的操作要么全部成功,要么全部失败。以下是几种常见的处理方法:
- 两阶段提交(2PC)
想象一下,你要组织一个团队活动,每个团队成员负责一个任务。在活动开始前,你(作为协调者)会先问每个成员是否准备好(准备阶段)。如果所有人都准备好,你就宣布活动正式开始(提交阶段);如果有人没准备好,你就告诉大家活动取消(回滚阶段)。在分布式事务中,协调者会先让所有参与的服务准备好(锁定资源),然后根据大家的反馈决定是提交还是回滚。
优点:可靠性高,能确保所有服务要么都成功,要么都失败。
缺点:性能较差,容易出现单点故障。如果协调者挂了,整个事务就会卡住。
- SAGA 模式
可以把 SAGA 模式想象成一场接力赛。每个参赛者(服务)完成自己的赛段(子事务)。如果某个人掉棒了(某个服务出错),前面的人会把棒捡回来(补偿事务),恢复到原来的状态。例如,在一个订单流程中,如果支付成功但库存扣减失败,系统会自动退款(补偿事务)。SAGA 模式把一个大的事务拆分成多个小事务,并为每个小事务设计补偿机制。
优点:灵活性高,特别适合长事务流程,可以根据需要设计补偿逻辑。
缺点:实现复杂,尤其是补偿逻辑的编写和测试。
- 最终一致性(TCC 模式)
TCC 是 Try-Confirm-Cancel 模式。先尝试(Try)操作,比如锁定资源;确认(Confirm)操作是真正执行;取消(Cancel)则是回滚。这个模式要求每个业务服务提供三个接口,分别处理这三个阶段。例如,用户下单时,先尝试冻结库存和资金,确认无误后正式扣款和扣除库存,如果出现错误则释放冻结的库存和资金。
优点:兼顾性能和一致性,在高并发场景下表现良好。
缺点:对业务逻辑侵入性强,需要对现有代码进行较大改造。
- 消息驱动的事务
这就像传纸条。服务 A 完成操作后,发一条消息(纸条)到消息队列,服务 B 监听消息并执行操作。通过消息的可靠传递和消费确认机制,确保事务的最终一致性。例如,订单服务下单成功后,发送消息到队列,库存服务消费消息后扣除库存。
优点:解耦服务,提高系统灵活性和可扩展性。
缺点:引入消息中间件增加系统复杂性。
1.5 分布式技术总结
微服务:SpringBoot
注册中心/配置中心:Spring Cloud Alibaba Nacos
网关:Spring Cloud Gateway
远程调用:Spring Cloud openFeign
服务熔断:Spring Cloud Alibaba Sentinel
分布式事务:Spring Cloud Alibaba Seata