Java笔记之SpringCloudAlibaba

1.架构之路:一般而言,架构的发展可能都会经历单体架构、垂直化和集群、SOA(面向服务架构)、微服务架构等。
2.单体架构:通常来说,如果一个war包或者jar包里面包含一个应用的所有功能,则称这种架构为单体架构。
3.集群及垂直化:针对单体架构的应用,考虑从两个方面进行优化:通过横向增加服务器,把单台机器变成多台机器的集群;按照业务的垂直领域进行拆分,减少业务的耦合度,以及降低单个war包带来的伸缩性困难问题。
4.SOA:面向服务的架构,从语义上说,它和面向过程、面向对象、面向组件的思想是一样的,都是一种软件组建及开发的方式。核心目标是把一些通用的、会被多个上层服务调用的共享业务提取成独立的基础服务,这些被提取出来的共享服务相对来说比较独立,并且可以重用。所以在SOA中,服务是最核心的抽象手段,业务被划分为一些粗粒度的业务服务和业务流程。在SOA中,会采用ESB(企业服务总线)来作为系统和服务之间的通信桥梁,ESB本身还提供服务地址的管理、不同系统之间的协议转换和数据格式转换等。调用端不需要关心目标服务的位置,从而使得服务之间的交互是动态的,这样做的好处是实现了调用者和服务的提供者之间的高度解耦。总的来说,SOA主要解决的问题是:信息孤岛;共享业务的重用。
5.微服务架构:如果SOA是面向服务开发思想的雏形,那么微服务就是针对可重用业务服务的更进一步优化,可以把SOA看成微服务的超集,也就是多个微服务可以组成一个SOA服务。
6.SOA与微服务:SOA关注的是服务的重用性及解决信息孤岛的问题,微服务关注的是解耦,虽然解耦和可重用性从特定的角度来看是一样的,但本质上是有区别的,解耦是降低业务之间的耦合度,而重用性关注的是服务的复用。微服务乎更多地关注在DevOps的持续交付上,因为服务粒度细化之后使得开发运维变得更加重要,因此微服务与容器化技术的结合更近紧密。
7.微服务架构的优点:复杂度可控,技术选型更加灵活,可扩展性更强,独立部署,容错性。
8.微服务面临的挑战:故障排查,服务监控,分布式架构的复杂性,服务依赖,运维成本。
9.Spring Cloud其实就是一套规范,而Spring Cloud Netflix、Spring Cloud Consul、Spring Cloud Alibaba才是Spring Cloud规范的实现。Spring Cloud主要致力于解决如下问题:分布式版本化配置、服务注册与发现、服务路由、服务调用、负载均衡、断路器、全局锁、Leader选举及集群状态、分布式消息。
10.Spring Cloud Netflix主要为微服务架构下的服务治理提供解决方案,包括以下组件:Eureka-服务注册与发现,Zuul-服务网关,Ribbon-负载均衡,Feign-远程服务的客户端代理,Hystrix-断路器(提供服务熔断和限流功能),Hystrix Dashboard-监控面板,Turbine-将各个服务实例上的Hystrix监控信息进行统一聚合。
11.Spring Cloud Alibaba主要为微服务开发提供一站式的解决方案,主要功能组件有:Sentinel-流量控制和服务降级,Nacos-服务注册与发现以及分布式配置中心,RocketMQ-消息驱动,Seata-分布式事务,Dubbo-RPC通信,OSS-阿里云对象存储。
12.Apache Dubbo:RPC+服务治理(服务注册、监控、路由、容错等)。使用Dubbo进行RPC通信时,作为服务提供者,需要提供通信服务接口Maven依赖,供服务消费方在pom.xml文件中引入。
13.Dubbo文件配置:Dubbo采用了Spring配置的扩展来实现透明化的服务发布和服务消费,所以配置文件跟以往XML形式描述Bean差不多,Dubbo配置文件路径为resources/META-INF/spring/file.xml。
14.dubbo:application:用来描述提供方的应用信息,比如应用名称、维护人、版本等,其中应用名称是必填项。
15.dubbo:registry:配置注册中心的地址,如不需要配置中心,可以设置address属性为N/A。
16.dubbo:protocol:配置服务提供者的协议信息,Dubbo支持多种协议来发布服务,默认采用Dubbo协议。
17.dubbo:service:描述需要发布的接口,也就是这个接口可供本网络上的其他进程访问。interface属性表示定义的接口,ref属性表示这个接口的实现。
18.dubbo:reference:生成远程服务代理,id属性和bean标签中的id一样,interface属性表示远程服务接口,url属性表示远程服务地址。
19.Spring Boot集成Apache Dubbo:ApacheDubbo不需要依赖SpringBoot也可以实现微服务,集成 SpringBoot的好处是可以享受到SpringBoot生态的框架和技术支持,也就是基于SpringBoot实现了标准化,并统一了开发运维部署的形态。可以使用Dubbo中提供的@Service注解发布服务,在application.properties文件中添加Dubbo服务的配置信息。启动SpringBoot项目时,需要在启动方法上添加@DubboComponentScan注解,它的作用和Spring Framework提供的@ComponentScan一样,只不过,这里扫描的是Dubbo中提供的@Service注解。可以使用Dubbo提供的@Reference注解来获得远程代理对象。
20.Dubbo集群容错:Dubbo默认提供了6种容错模式,默认为Failover Cluster。配置方式简单,只需要在指定服务的@Service注解上增加一个参数即可,例如cluster=”failfast”。在实际应用中,查询语句容错策略建议使用默认的Failover Cluster,而增删改等操作建议使用Failfast Cluster或者使用Failover Cluster(retries=”0”)策略,防止出现数据重复添加等其他问题。建议在设计接口时将查询接口方法单独做成一个接口提供查询。
21.Failover Cluster:失败自动切换。默认重试次数是2。这种模式通常用于读操作,因为事务型操作会带来数据重复问题。
22.Failfast Cluster:快速失败。只发起一次调用,失败后立即报错,通常用于一些幂等的写操作,比如新增数据。
23.Failsafe Cluster:失败安全。也就是出现异常,直接忽略。
24.Failback Cluster:失败后自动回复。服务调用出现异常时,在后台记录这条失败的请求定时重发。这种模式适合用于消息通知操作,保证请求一定发送成功。
25.Forking Cluster:并行调用集群中的多个服务,只要其中一个成功就返回。可以通过forks属性来设置最大并行数。
26.Broadcast Cluster:广播调用所有的服务提供者,任意一个服务报错则提示服务调用失败。这种机制通常用于通知所有的服务提供者更新缓存或本地资源信息。
27.Dubbo负载均衡:在访问量较大的情况下,通常会通过水平扩容的方式增加多个节点来平衡请求的流量,从而提升服务的整体性能。请求应该分发到集群中哪个节点,取决于负载均衡算法。负载均衡可以分为硬件负载均衡和软件负载均衡,硬件常见的就是F5,软件主流的有Nginx。在Dubbo中提供了4中负载均衡策略,默认是random。配置方式同集群容错策略一样,也是在@Service中增加参数,例如loadbalance=”roundrobin”。
28.Random LoadBalance:随机算法。可以针对性能较好的服务器设置较大的权重值,权重越大,随机的概率也会越大。
29.RoundRobin LoadBalance:轮询。按照公约后的权重设置轮询比例。
30.LeastActive LoadBalance:最少活跃调用书。处理慢的节点将会收到更少的请求。
31.ConsistentHash LoadBalance:一致性Hash。相同参数的请求总是发送到同一个服务提供者。
32.Dubbo服务降级:服务降级是一种系统保护策略,所谓降级,就是把一些非必要的功能在流量较大的时间段暂时关闭。降级有多个层面的分类:按照是否自动化可分为自动降级和人工降级;按照功能可分为读服务降级和写服务降级。人工降级一般具有一定的前置性,而自动降级更多来自于系统出现某些异常(故障降级,限流降级)的时候自动触发“兜底的流畅”。Dubbo提供了一种Mock配置来实现服务降级,也就是说当服务提供方出现网络异常无法访问时,客户端不抛出异常,而是通过降级配置返回兜底数据。Mock配置比较简单,就是在@Reference注解中增加参数mock,mock属性配置了自动降级的接口的具体实现类。
33.Dubbo主机绑定规则:主机绑定表示的是Dubbo服务对外发布的IP地址,默认情况下Dubbo会按照以下顺序来查找并绑定主机IP地址:查找环境变量中DUBBO_IP_TO_BIND属性配置的IP地址;查找dubbo.protocol.host属性配置的IP地址,默认是空;通过LocalHost.getHostAddress()获取本机IP地址;如果配置了注册中心的地址,则使用Socket通信连接到注册中心的地址后,使用for循环通过socket.getLocalAddress().getHostAddress()扫描各个网卡获取网卡IP地址。上述过程中,任意一个步骤检测到合法的IP地址,便会将其返回作为对外暴露的服务IP地址。除获取绑定主机IP地址外,对外发布的端口也是需要注意的,Dubbo框架中针对不同的协议都提供了默认的端口号:Dubbo协议的默认端口号是20880,Webservice协议的默认端口号是80。在实际使用过程中,建议指定一个端口号,避免和其他Dubbo服务的端口产生冲突。
34.服务注册中心的功能:服务地址的管理,服务注册,服务动态感知。
35.限流算法:计数器算法,滑动窗口算法,令牌桶限流算法,漏桶限流算法。
36.计数器算法:在指定周期内累加访问次数,当访问次数达到指定的阀值时,触发限流策略,当进入下一个时间周期时进行访问次数的清零。适用于短信发送的频此限制上。该算法存在临界问题。
37.滑动窗口算法:为了解决计数器算法带来的临界问题而引入的一种限流算法。滑动窗口是一种流量控制技术,在TCP网络通信协议中,就采用了该算法来解决网络拥塞的情况。简单来说,滑动窗口算法的原理是在固定窗口中分割出多个小时间窗口,分别在每个小时间窗口中记录访问次数,然后根据时间将窗口往前滑动并删除过期的小时间窗口。最终只需要统计滑动窗口范围内的所有小时间窗口的计数即可。Sentinel就是采用滑动窗口算法来实现限流的。
38.令牌桶限流算法:令牌桶是网络流量整形和速率限制中最常用的一种算法。对于每一个请求,都需要从令牌桶中获得一个令牌,如果没有获得令牌,则需要触发限流策略。系统会以一个恒定速度往固定容量的令牌桶中放入令牌,如果请求速度大于令牌生成速度,那么令牌很快被取完,后续的请求会被限流;如果请求速度等于令牌生成速度,此时流量处于平稳状态;如果请求速度小于生成速度,说明系统的并发数并不高,令牌桶会被填满,可以应对短时间内新增的突发流量。
39.漏桶限流算法:主要作用是控制数据注入网络的速度,平滑网络上的突发流量。实际上消息中间件就使用了漏桶限流的思想,不管生产者的请求量有多大,消息的处理能力取决于消费者。该算法无法处理短时间内的突发流量。
40.服务熔断与降级:服务熔断是指当某个服务提供者无法正常为服务调用者提供服务时(例如请求超时、服务异常等),为了防止整个系统出现雪崩效应,暂时将出现故障的接口隔离出来,断绝与外部接口的联系,当触发熔断后,后续一段时间内该服务调用者的请求会直接失败,直到目标服务恢复正常。服务降级参考指标:平均响应时间,异常比例,异常数量。
41.分布式限流框架Sentinel:Sentinel是面向分布式服务框架的轻量级流量控制组件,主要以流量为切入点,从限流、流量整形、服务降级、系统负载保护等多个维度来保障微服务的稳定性。
42.Sentinel特性:丰富的应用场景,例如秒杀、消息削峰填谷、集群流量控制等;实时监控;开源生态支持;SPI扩展点支持。
43.Sentinel组成:核心库,控制台。
44.Sentinel资源保护规则:流量控制规则,熔断降级规则,系统保护规则,来源访问控制规则,热点参数规则。
45.Sentinel流量控制统计类型:并发线程数,每秒查询数(Queries Per Second,QPS)。
46.并发线程数:Sentinel并发线程数限流就是统计当前请求的上下文线程数量,如果超出阀值,新的请求就会被拒绝。用来保护业务线程不被耗尽。
47.QPS:每秒查询数,也就是一台服务器每秒能够响应的查询次数。当QPS达到限流的阀值时,救护触发限流策略。
48.QPS流量控制行为:直接拒绝,Warm Up(冷启动/预热),匀速排队,冷启动+匀速排队。
49.调用关系流量策略:根据调用方限流,根据调用链路入口限流,关联流量控制。
50.Sentinel工作原理:Sentinel的核心分为三部分:工作流程、数据结构、限流算法。在Sentinel中,所有的资源都对应一个资源名称(resourceName),每次访问该资源都会创建一个Entry对象,在创建Entry的同时,会创建一系列功能槽(Slot Chain),这些槽会组成一个 责任链,每个槽负责不同的职责:NodeSelectorSlot-负责收集资源的调用链路;ClusterBuilderSlot-负责创建以资源名维度统计的ClusterNode,以及创建每个ClusterNode下按调用来源origin划分的StatisticNode;LogSlot-在出现限流、熔断、系统保护时负责记录日志;AuthoritySlot-权限控制,支持黑名单和白名单两种策略;SystemSlot-控制总的入口流量,限制条件依次是总QPS、总线程数、RT阀值、操作系统当前load1、操作系统当前利用率;FlowSlot-根据限流规则和各个Node中的统计数进行限流判断;DegradeSlot-根据熔断规则和各个Node中的统计数据进行服务降级;StatisticSlot-统计不同维度的请求数、通过数、限流数、线程数等runtime信息,这些数据存储在DefaultNode、OriginNode和ClusterNode中。
51.分布式事务:是指事务的参与者、支持事务的服务器、资源服务器及事务管理器分别位于分布式系统的不同节点上。分布式事务问题也叫分布式数据一致性问题,简单来说就是如何在分布式场景中保证多个节点数据的一致性。分布式事务产生的核心原因在于存储资源的分布性,比如多个数据库,或者MySQL和Redis两种不同存储设备的数据一致性等。
52.X/Open分布式事务模型:X/Open DTP是X/Open这个组织定义的一套分布式事务的标准。这个标准提出了使用两阶段提交(2PC,Two-Phase-Commit)来保证分布式事务的完整性。X/Open DTP中包含三种角色:AP-Application,表示应用程序;RM-Resource Manager,表示资源管理器,比如数据库;TM-Transaction Manager,表示事务管理器,一般指事务协调者,负责协调和管理事务,提供AP编程接口和管理RM。需要注意的是,TM和多个RM之间的事务控制,是基于XA协议来完成的。XA协议是X/Open提出的分布式事务处理规范,也是分布式事务处理的工业标准,它定义了xa_和ax_系列的函数原型及功能描述、约束等。目前Oracle、MySQL、DB2都实现了XA接口,所以他们都可以作为RM。
53.两阶段提交协议:TM实现了多个RM事务的管理,实际上会涉及两个阶段的提交,第一阶段是事务的准备阶段,第二阶段是事务的提交或者回滚阶段。这两个阶段都是由事务管理器发起的。准备阶段:事务管理器(TM)通知资源管理器(RM)准备分支事务,记录事务日志,并告知事务管理器的准备结果。提交/回滚阶段:如果所有的资源管理器(RM)在准备阶段都明确返回成功,则事务管理器(TM)向所有的资源管理器(RM)发起事务提交指令完成数据的变更。反之,如果任何一个资源管理器(RM)明确返回失败,则事务管理器(TM)会向所有资源管理器(RM)发送事务回滚指令。
54.两阶段提交协议的缺点:同步阻塞,过于保守,事务协调者的单点故障,“脑裂”导致数据库不一致问题。
55.三阶段提交协议:是两阶段提交协议的改进版本,它利用超时机制解决了同步阻塞的问题,三阶段提交流程如下:CanCommit(询问阶段),PreCommit(准备阶段),DoCommit(提交/回滚阶段)。
56.三阶段提交-询问阶段:事务协调者向参与者发送事务执行请求,询问是否可以完成指令,参与者只需要回答是或者不是即可,不需要做真正的事务操作,这个阶段会有超时中止机制。
57.三阶段提交-准备阶段:事务协调者根据参与者的反馈结果决定是否继续执行,如果在询问阶段素有参与者都返回可以执行操作,则事务协调者会向所有参与者发送PreCommit请求,参与者收到请求后写redo和undo日志,执行事务操作但是不提交事务,然后返回ACK响应等待事务协调者的下一步通知。如果在询问阶段任意参与者返回不能执行操作的结果,那么事务协调者会向所有的参与者发送事务中断请求。
58.三阶段提交-提交/回滚阶段:这个阶段也会存在两种结果,仍然根据上一步骤的执行结果来决定DoCommit的执行方式。如果每个参与者在PreCommit阶段都返回成功,那么事务协调者会向所有参与者发起事务提交指令。反之,如果参与者中的任意一个返回失败,那么事务协调者就会发起中止指令回滚事务。
59.CAP定理:又叫布鲁尔定理。简单来说它是指分布式系统中不可能同时满足一致性(C:Consistency)、可用性(A:Availability)、分区容错性(P:Partition Tolerance)这三个基本需求,最多同时满足两个。CAP定理证明,在分布式系统中,要么满足CP,要么满足AP,不可能实现CAP或者CA。原因是网络通信并不是绝对可靠的。而在分布式系统中,即便网络出现故障也需要保证系统仍然能够正常对外提供服务,所以在分布式系统中Partition Tolerance是必然存在的,也就是必须要满足分区容错性。
60.AP:对于AP来说,相当于放弃了强一致性,实现最终的一致,这是很多互联网公司解决分布式数据一致性问题的主要选择。
61.CP:放弃了高可用性,实现强一致性。两阶段提交和三阶段提交都采用这种方案。
62.BASE理论:是由于CAP中一致性和可用性不可兼得而衍生出来的一种新思想,BASE理论的核心思想是通过牺牲数据的强一致性来获得高可用性。它有三个特性:Basically Available(基本可用),Soft State(软状态),Eventually Consistent(最终一致性)。
63.基本可用:在分布式系统出现故障时,允许损失一部分功能的可用性,保证核心功能的可用。
64.软状态:允许系统中的数据存在中间状态,这个状态不影响系统的可用性,也就是允许系统中不同节点的数据副本之间的同步存在延时。
65.最终一致性:中间状态的数据在经历一段时间之后,会达到一个最终的数据一致性。
66.分布式事务问题的常见解决方案:TCC补偿型方案,基于可靠性消息的最终一致性方案,最大努力通知型。
67.TCC补偿型方案:TCC(Try-Confirm-Cancel)是一种比较成熟的分布式数据一致性解决方案,它实际上把一个完整的业务拆分为如下三个步骤:Try-这个阶段主要是对数据的校验或者资源的预留;Confirm-确认真正执行的任务,只操作Try阶段预留的资源;Cancel-取消执行,释放Try阶段预留的资源。
68.基于可靠性消息的最终一致性方案:主要利用消息中间件的可靠性机制来实现数据一致性的投递。
69.最大努力通知型:和基于可靠性消息的最终一致性方案类似,是一种比较简单的柔性事务解决方案,也比较适用于对数据一致性要求不高的场景,典型的使用场景是支付宝支付结果通知。
70.分布式事务框架Seata:是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。它提供了AT、TCC、Saga和XA事务模式,为开发者提供了一站式的分布式事务解决方案。
71.AT模式:是Seaga最主推的分布式事务解决方案,它是基于XA演进而来的一种分布式事务模式,所以它同样分为三大模块,分别是TM、RM和TC。其中TM和RM作为Seata的客户端与业务系统集成,TC(Transaction Coordinator,事务协调器)作为Seata的服务器独立部署。TM表示事务管理器,它负责向TC注册一个全局事务,并生成一个全局唯一的XID。在AT模式下,每个数据库资源被当作一个RM(Resource Manager),在业务层面通过JDBC标准的接口访问RM时,Seata会对所有请求进行拦截。每个本地事务进行提交时,RM都会向TC注册一个分支事务,具体执行流程如下:TM向TC注册全局事务,并生成全局唯一的XID;RM向TC注册分支事务,并将其纳入该XID对应的全局事务范围;RM向TC汇报资源的准备状态;TC汇总所有事务参与者的执行状态,决定分布式事务是全部回滚还是提交;TC通知所有RM提交/回滚事务。AT模式和XA一样,也是一个两阶段提交事务模型,不过和XA相比,AT做了很多优化。
72.Saga模式:又称为长事务解决方案,主要描述的是在没有两阶段提交的情况下如何解决分布式事务问题。其核心思想是:把一个业务流程中的长事务拆分为多个本地短事务,业务流程中的每个参与者都提交真实的提交给本地短事务,当其中一个参与者事务执行失败,则通过补偿机制补偿前面已经成功的参与者。
73.Saga的优缺点。和XA或者TCC相比,它的优点是:一阶段直接提交本地事务;没有锁等待,性能较高;在事件驱动的模式下,短事务可以异步执行;补偿机制的实现比较简单。缺点是:Saga并不提供原子性和隔离性支持。
74.Saga的协调模式:事件/编排式,命令/协同式。
75.事件/编排式:把Saga的决策和执行顺序逻辑分布在Saga的每一个参与者中,它们通过交换事件的方式来进行沟通。在基于事件的编排模式中,第一个服务执行完一个本地事务后,发送一个事件。这个事件会被一个或者多个服务监听,监听事件的服务再执行本地事务并发布新的事件,此后一直延续这种事件触发模式,直到该业务流程中最后一个服务的本地事务执行结束,才意味着整个分布式长事务也执行结束。
76.命令/协同式:命令/协同式需要定义一个Saga协调器,把Saga的决策和执行顺序逻辑集中在一个Saga控制类中,负责告诉每一个参与者该做什么,Saga协调器以命令/回复的方式与每项服务进行通信。
77.Seata AT模式:第一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源;第二阶段:提交异步化,非常快速的完成,回滚通过第一阶段的回滚日志进行反向补偿。
78.写隔离:是为了在多个全局事务针对同一张表的同一个字段进行更新操作时,避免全局事务在没有被提交之前被其他全局事务修改。写隔离的主要实现是,在第一阶段本地事务提交之前,确保拿到全局锁。如果拿不到全局锁,则不能提交本地事务。并且获取全局锁的尝试会有一个范围限制,如果超出范围将会放弃全局锁的获取,并且回滚事务,释放本地锁。
79.读隔离:在数据库本地事务隔离级别为提交读(Read Committed)或者以上时,Seata AT事务模式的默认全局事务隔离级别是未提交读(Read Uncommitted)。在该隔离级别,所有事务都可以看到其他未提交事务的执行结果,产生脏读。这在最终一致性事务模型中是运行存在的,并且在大部分分布式事务场景中都可以接受脏读。
80.在微服务架构下,一个业务服务会被拆分成多个微服务,各个服务之间相互通信完成整体的功能。系统间的通信写作通常有两种:Http/RPC通信,优点是通信实时,缺点是服务之间的耦合性高;消息通信:优点是降低了服务之间的耦合性,提高了系统的处理能力,缺点是通信非实时。
81.RocketMQ:是一个低延迟、高可靠、可伸缩、易于使用的分布式消息中间件(也称消息队列),具有高吞吐、低延迟、海量消息堆积等优点,同时提供顺序消息、事务消息、定时消息、消息重试与追踪等功能,非常适合在电商、金融等领域。
82.RocketMQ的应用场景:削峰填谷,异步解耦,顺序收发,分布式事务一致性,分布式缓存同步。
83.Spring Cloud Stream是Spring Cloud体系内的一个框架,用于构建与共享消息传递系统连接的高度可伸缩的事件驱动微服务,其目的是简化消息业务在Spring Cloud应用程序中的开发。应用程序通过Spring Cloud Stream注入的输入通道inputs和输出通道outputs与消息中间件Middleware通信,消息通道通过特定的中间件绑定器Binder实现连接到外部代理。
84.Spring Cloud Stream的实现基于发布/订阅机制,其核心由四部分构成:Spring Framework中的Spring Messaging和Spring Integration,以及Spring Cloud Stream中的Binders和Bindings。
85.Spring Messaging:Spring Framework中的统一消息编程模型,其核心对象有:Message-消息对象,包含消息头Header和消息体Payload;MessageChannel-消息通道接口,用于接收消息,提供send方法将消息发送至消息通道;MessageHandler-消息处理器接口,用于处理消息逻辑。
86.Spring Integration:Spring Framework中用于支持企业集成的一种扩展机制,作用是提供一个简单的模型来构建企业集成解决方案,对Spring Messaging进行了扩展。主要有以下几部分组成:MessageDispatcer-消息分发接口,用于分发消息和添加删除消息处理器;MessageRouter-消息路由接口,定义默认的消息输出通道;Filter-消息的过滤注解,用于配置消息过滤表达式;Aggregator-消息的聚合注解,用于将多条消息聚合成一条;Splitter-消息的分割,用于将一条消息拆分成多条。
87.Binders:目标绑定器,负责与外部消息中间件系统集成的组件。doBindProducer-绑定消息中间件客户端发送消息模块;doBindConsumer-绑定消息中间件客户端接收消息模块。
88.Bindings:外部消息中间件系统与应用程序提供的消息生产者和消费者(由Binders创建)之间的桥梁。
89.Spring Cloud Stream官方提供了Kafka Binder和RabbitMQ Binder,用于集成Kafka和RabbitMQ,Spring Cloud Alibaba中加入了RocketMQ Binder,用于将RocketMQ集成到Spring Cloud Stream。
90.Spring Cloud Stream消息发送/订阅流程:企业发送消息→MessageChannel→AbstractMessageChannel→AbstractSubscribableChannel→Dispatcher→MessageHandlers→企业Binder(RocketMQ Binder)→MessageChannel→AbstractMessageChannel→AbstractSubscribableChannel→Dispatcher→MessageHandler→StreamListenerMessageHandler→@StreamListener业务消息监听。
91.发送普通消息、事务消息、定时消息还是顺序消息,有Message对象的消息头Header中的属性决定,在业务代码创建Message对象时设置。
92.RocketMQ提供了两种消费模式:顺序消费和并发消费。RocketMQ客户端API中顺序消费的默认监听器是DefaultMessageListenerOrderly类,并发消息的默认监听器是DefaultMessageListenerConcurrently类。无论哪种消费模式,监听器收到消息后都会回调RocketMQListener。
93.Kafka是一款高性能的消息中间件,在大数据场景中经常使用,但由于Kafka不支持消费失败重试、定时消息、事务消息,顺序消息也有明显缺陷。常见的消息中间件Kafka、RabbitMQ、RocketMQ等都基于发布/订阅机制,消息发送者(Producer)把消息发送到消息服务器,消息消费者(Consumer)从消息服务器订阅感兴趣的消息。这个过程中,消息发送者和消息消费者都是客户端,消息服务器是服务端,客户端与服务端双方都需要通过注册中心感知对方的存在。
94.RocketMQ部署架构主要分为四部分:Producer,Consumer,Broker,NameServer。
95.Producer:消息发布的角色,主要负责把消息发送到Broker,支持分布式集群方式部署。
96.Consumer:消息消费的角色,主要从Broker订阅消息消费,支持分布式集群方式部署。
97.Broker:消息存储的角色,主要负责消息的存储、投递和查询,以及服务高可用保证,支持分布式集群方式部署。
98.NameServer:服务管理的角色,主要负责管理Broker集群的路由信息,支持分布式集群方式部署。NameServer是一个非常简单的Topic路由注册中心,其角色类似于Dubbo中的ZooKeeper,支持Broker的动态注册与发现。主要包括两个功能:服务注册。NameServer接收Broker集群的注册信息,保存下来作为路由信息的基本数据,并提供心跳检测机制,检查Broker是否还存活。路由信息管理。NameServer保存了Broker集群的路由信息,用于提供给客户端查询Broker的队列信息。Producer和Consumer通过NameServer可以知道Broker集群的路由信息,从而进行消息的投递和消费。
99.Message:消息,系统所传输信息的物理载体,生产和消费数据的最小单位。每条消息必须属于一个Topic,RocketMQ中每条消息拥有唯一的MessageID,且可以携带具有业务标识的Key。
100.Topic:主题,表示一类消息的集合,每个主题都包含若干条消息,每条消息都只能属于一个主题,Topic是RocketMQ进行消息订阅的基本单位。
101.Queue:消息队列,组成Topic的最小单元。默认情况下一个Topic会对应多个Queue,Topic是逻辑概念,Queue是物理存储,在Consumer消费Topic消息时底层实际拉取Queue的消息。
102.Tag:为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同的标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消息的处理逻辑,实现更好的扩展性。
103.UserProperties:用户自定义的属性集合,属于Message的一部分。
104.ProducerGroup:同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后奔溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。
105.ConsumerGroup:同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。值得注意的是,消费者组的消费者实例必须订阅完全相同的Topic。
106.在Kafka中的服务注册与发现通常是使用ZooKeeper来完成的,RocketMQ早期也使用了ZooKeeper做集群的管理,后期改为NameServer了。
107.在Kafka中,Topic是逻辑概念,分区(Partition)是物理概念。1个Topic可以设置多个分区,每个分区可以设置多个副本(Replication),即有一个Master分区、多个Slave分区。
108.在RocketMQ中,Topic也是逻辑概念,队列(Queue)是物理概念(对应Kafka中的分区)。一个Topic可以设置多个队列,每个队列也可以有多个副本,即有一个Master队列、多个Slave队列。
109.Kafka与RocketMQ两者在概念上相似,但又有明显的差异:在Kafka中,Master和Slave在同一台Broker机器上,Broker机器上有多个分区,每个分区的Master/Slave身份是在运行过程中选举出来的(通过ZooKeeper选举出来)。Broker机器具有双重身份,既有Master分区,也有Slave分区。在RocketMQ中,Master和Slave不在同一台Broker机器上,每台Broker机器不是Master就是Slave,Broker的Master/Slave身份是在Broker的配置文件中预先定义好的,在Broker启动之前就已经决定了。
110.Kafka的Master/Slave需要通过ZooKeeper选举出来,而RocketMQ不需要。ZooKeeper具备选举功能,选举机制的原理是少数服从多数,选举机制必须由ZooKeeper集群中的多个实例共同完成,所以多个实例之间必须互相通信,如果实例数很多的话,网络通信就会变得非常复杂且低效。
111.NameServer的设计目标是让网络通信变得简单,从而使性能得到极大的提升。为了避免单点故障,NameServer也必须以集群的方式部署,但集群中的各实例相互不进行通信。NameServer是无状态的,可以任意部署多个实例。Broker向每一台NameServer注册自己的路由信息,因此每一个NameServer实例都保存一份完整的路由信息。NameServer与每台Borker机器保持长连接,间隔30s从路由注册表中将故障机器移除。NameServer为了降低实现的复杂度,并不会立刻通知客户端的Producer和Consumer。
112.RocketMQ的顺序消息分2种情况:局部有序和全局有序。
113.局部有序:指发送同一个队列的消息有序,可以在发送消息时指定队列,在消费消息时按顺序消费。
114.全局有序:设置Topic只有1个队列可以实现全局有序,创建Topic时手动设置。此类场景极少,性能差,通常不推荐使用。
115.RocketMQ中消息发送有三种方式:同步、异步、单向。
116.同步:发送网络请求后会同步等待Broker服务器的返回结果,支持发送失败重试,适用于比较重要的消息通知场景。
117.异步:异步发送网络请求,不会阻塞当前线程,不支持失败重试,适用于对响应时间要求更高的场景。
118.单向:单向发送原理和异步一致,但不支持回调。适用于响应时间非常短、对可靠性要求不高的场景,例如日志收集。
119.顺序消息发送的原理很简单,同一类消息发送到相同的队列即可。为了保证先发送的消息先存储到消息队列,必须使用同步发送的方式,否则可能出现先发的消息后到消息队列,此时消息就乱序了。
120.RocketMQ中除顺序消息外,还支持事务消息和延迟消息,除此之外的消息称之为普通消息。日常开发过程中最常用的是普通消息,这是因为最常用的场景是系统间的异步解耦和流量的削峰填谷,这些场景下尽量保证消息高性能收发即可。
121.较顺序消息而言,普通消息发送时选择消息队列的策略不同。普通消息发送选择队列有两种机制:轮询机制和故障规避机制(也称故障延迟机制)。默认使用轮询机制,一个Topic有多个队列,轮询选择其中一个队列。轮询机制的原理是路由信息TopicPublishInfo中维护了一个计数器sendWhichQueue,每发送一次消息要查询一次路由,计数器就进行“+1”,通过计数器的值index与队列的数量取模计算来实现轮询算法。
122.RocketMQ支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。两者的区别是,在广播消费模式下每条消息会被ConsumerGroup的每个Consumer消费,在集群消费模式下每条消息只会被ConsumerGroup的一个Consumer消费。
123.顺序消费也称为有序消费,原理是同一个消息队列只允许Connsumer中的一个消费线程拉取消费。Consumer中有个消费线程池,多个线程会同时消费消息。在顺序消费的场景下消费线程请求到Broker时会先申请独占锁,获得锁的请求则允许消费。消息消费成功后,会向Broker提交消费进度,更新消费位点信息,避免下次拉取到已消费的消息。顺序消费中如果消费线程在监听器中进行业务处理时抛出异常,则不会提交消费进度,消费进度会阻塞在当前这条消息,并不会继续消费该队列中后续的消息,从而保证顺序消费消息。在顺序消费的场景下,特别需要注意对异常的处理,如果重试也失败,会一直阻塞在当前消息,直到超出最大重试次数,从而在很长一段时间内无法消费后续消息造成队列消息堆积。
124.RocketMQ支持两种消费方式:顺序消费和并发消费。并发消费是默认的消费方式。
125.并发消费也称为乱序消费,其原理是同一个消息队列提供给Consumer中的多个消费线程拉取消费。Consumer中会维护一个消费线程池,多个消费线程可以并发去同一个消息队列中拉取消息进行消费。如果某个消费线程在监听器中进行业务处理时抛出异常,当前消费线程拉取的消息会进行重试,不影响其他消费线程和消息队列的消费进度,消费成功的线程正常提交消费进度。
126.并发消息相比顺序消费,没有资源上的锁竞争过程,消费消息的速度比顺序消费要快。
127.RocketMQ不保证消息不被重复消费,如果业务对消费重复非常敏感,必须要在业务层面进行幂等性处理,具体实现可以通过分布式锁来完成。在所有消息系统中,消费消息有三种模式:at-most-once(最多一次)、at-least-once(最少一次)和exactly-only-once(精确仅一次),分布式消息系统都是在三者之间取平衡,前两者是可行的并且被广泛使用的。
128.at-most-once:消息投递后不论消费是否成功,不会重复投递,有可能会导致消息未被消费,RocketMQ未使用该方式。
129.at-least-once:消息投递后,消费完成后,向服务器返回ACK(消费确认机制),没有消费则一定不会返回ACK消息。由于网络异常、客户端重启等原因,服务器未能收到客户端返回的ACK,则会再次投递,这回导致消息被重复消费,RocketMQ通过ACK来确保消息至少被消费一次。
130.exactly-only-once:必须满足两个条件,才能认为消息是“精确仅一次”:发送消息阶段,不允许发送重复的消息;消息消费阶段,不允许消费重复的消息。在分布式系统环境下,实现该模式需要巨大的开销。RocketMQ为了追求高性能,并不保证此特性,无法避免消息重复,由业务上进行幂等性处理。
131.RocketMQ采用了2PC的方案来提交事务消息。第一阶段Producer向Broker发送预处理消息(也称半消息),此时消息还未被投递出去,Consumer不能消费;第二阶段Producer向Broker发送提交或回滚消息。具体流程如下:发送预处理消息成功后,开始执行本地事务;如果本地事务执行成功,发送提交请求提交事务消息,消息会投递给Consumer;如果本地事务执行失败,发送回滚请求回滚事务消息,消息不会投递给Consumer;如果本地事务状态未知,网络故障或Producer宕机,Broker未收到二次确认的消息。由Broker端发送请求给Producer进行消息回查,确认提交或回滚,如果消息状态一直未被确认,需要人工介入处理。
132.RocketMQ的高性能设计体现在三个方面:数据存储设计、动态伸缩的能力、消息实时投递。数据存储设计包括顺序写盘、消费队列设计、消息跳跃读、数据零拷贝。动态伸缩的能力包括消息队列扩容、Broker集群扩容。
133.RocketMQ以高吞吐量著称,这主要得益于其数据存储方式的设计。数据存储的核心由两部分组成:CommitLog数据存储文件和ConsumeQueue消费队列文件。Producer将消息发送的Broker服务器,Broker会把所有消息都存储在CommitLog文件中,再由CommitLog转发到ConsumeQueue文件提供给各个Consumer消费。
134.一次磁盘请求(读或写)完成过程由三个动作组成:寻道、旋转延迟、数据传输。寻道:磁头移动定位到指定磁道,时间很长,是指找到数据在哪个地方。旋转延迟:等待指定扇区旋转至磁头下,机械硬盘和每分钟多少转有关系,时间很短。数据传输:数据通过系统总线从磁盘传送到内存,时间很短。磁盘读写最慢的动作是寻道,缩短寻道时间就能有效提升磁盘的读写速度,最优的方式就是不用寻道。随即写会导致磁头不停地更换磁道,顺序写几乎不用换磁道或者寻道时间很短。
135.顺序写盘:指写磁盘上的文件采用顺序写的方式。
136.CommitLog文件是负责存储消息数据的文件,所有Topic的消息都会先存在{ROCKETMQ_HOME}/store/commitlog文件夹下的文件中,消息数据写入CommitLog文件是加锁串行追加写入。
137.RocketMQ为了保证消息发送的高吞吐量,使用单个文件存储所有Topic的消息,从而保证消息存储是完全的磁盘顺序写,但这样给文件读取(消费消息)带来了困难(通过设计消费队列ConsumeQueue解决)。
138.当消息到达CommitLog文件后,会通过线程异步几乎实时地将消息转发给消费队列文件。每个CommitLog文件的默认大小是1GB,写满1GB再写新的文件,大量数据I/O都在顺序写同一个CommitLog文件。文件名按照该文件起始的总的字节偏移量offset命名,文件名固定长度为20位,不足20位前面补0。文件名这样设计的目的是在消费信息时,能够根据偏移量offset快速定位到消息存储在某个CommitLog文件,从而加快消息的检索速度。
139.为了解决消息数据文件顺序读写难以读取的问题,RocketMQ中设计了消费队列ConsumeQueue。ConsumeQueue负责存储消费队列文件,在消息写入CommitLog文件时,会异步转发到ConsumeQueue文件,然后提供给Consumer消费。ConsumeQueue文件中并不存储具体的消息数据,只存CommitLog的偏移量offset、消息大小size、消息Tag HashCode。
140.每个Topic在某个Broker下对应多个队列Queue,默认是4个消费队列Queue。每一条记录的大小是20B,默认一个文件存储30万个记录,文件名同样也按照字节偏移量offset命名,文件名固定长度为20位,不足20位前面补0。在集群模式下,Broker会记录客户端每个消费队列的消费偏移量,定位到ConsumeQueue里相应的记录,并通过CommitLog的offset定位到CommitLog文件里的该条消息。
141.消费Broker中存储消息的实际工作就是读取文件,消息队列文件是一种数据结构上的设计。为了高性能读数据,除了磁盘顺序读和消息队列文件的设计,还使用了操作系统中的PageCache机制。
142.RocketMQ读取消息依赖操作系统的PageCache,PageCache命中率越高则读性能越高,操作系统会尽量预读数据,使应用直接访问磁盘的概率降低。消息队列文件的读取流程如下:检查要读的数据是否在上次预读的Cache中;如果没有命中Cache,操作系统从磁盘中读取对应的数据页,并将该数据页之后的连续好几页一起读取Cache中,再将应用需要的数据返回给应用,这种方式称为跳跃读取;如果命中Cache,上次缓存的数据有效,操作系统认为在顺序读盘,则继续扩大缓存的数据范围,将之前缓存的数据页之后的几页数据再读取到Cache中。
143.在网络通信中,通常情况下对文件的读写要多经历一次数据拷贝,例如写文件数据要从用户态拷贝到内核态,再由内核态写入物理文件。所谓零拷贝,指的是用户态与内核态之间不存在拷贝。
144.RocketMQ中的文件读写主要通过Java NIO中的MappedByteBuffer来进行文件映射。利用了Java NIO中的FileChannel模型,可以直接将物理文件映射到缓冲区的PageCache,少了一次数据拷贝过程,提高了读写速度。
145.动态伸缩(水平扩容)能力是分布式应用很重要的能力,RocketMQ中的动态伸缩能力主要体现在消息队列扩容和集群扩容两个方面,需要根据实际场景进行选择。
146.消息队列扩容/缩容:一个Consumer实例可以同时消费多个消息队列中的消息。如果一个Topic的消息量特别大,但Broker集群水位压力还是很低,就可以对该Topic的消息队列进行扩容,Topic的消息队列数跟消费速度成正比。消息队列数在创建Topic时可以指定,也可以在运行中修改。相反,如果一个Topic的消息量特别小,但该Topic的消息队列数很多,则可以对该Topic消息队列缩容。
147.Broker集群扩容/缩容:如果一个Topic的消息量特别大,但Broker集群水位很高,此时就需要对Broker机器扩容。扩容方式很简单,直接加机器部署Broker即可。新的Broker启动后会向NameServer注册,Producer和Consumer通过NameServer发现新Broker并更新路由信息。相反,如果Broker集群水位很低,可以适当减少Broker服务器来节约成本。
148.消息的高性能还体现在消息发送到存储之后能否立即被客户端消费,这涉及消息的实时投递,Consumer消费消息的实时性与获取消息的方式有很大关系。任何一款消息中间件都会有两种获取消息的方式:Push推模式和Pull拉模式。
149.Push推模式:由服务端主动推送给客户端Consumer。优点是客户端Consumer能实时地接收到新的消息数据。缺点是:如果Consumer消费一条消息耗时很长,推送速度大于消费速度,Consumer消费不过来,会出现缓冲区溢出;一个Topic往往会对应多个ConsumerGroup,服务端一条消息会产生多次推送,可能会对服务器造成压力。
150.Pull拉模式:由客户端按照轮询去服务端拉取消息。优点是Consumer可以根据当前消费速度选择合适的时机触发拉取。缺点是拉取的间隔时间不好控制,间隔时间太长,容易造成服务器端消息积压,间隔时间太短,会导致Consumer拉取无效从而浪费网络资源和服务端资源。
151.Push或者Pull模式,单一方式难以应对复杂的消费场景,所以RocketMQ中提供了一种推/拉结合的长轮询机制来平衡推/拉模式各自的缺点。长轮询本质上是对普通Pull模式的优化,即还是以客户端Consumer轮询的方式主动发送拉取请求到服务端Broker,Broker如果检测到有新的消息就立即返回,但如果没有则暂时不返回任何信息,挂起当前请求缓存到本地,Broker后台有个线程去检查刮起请求,等到新消息产生时再返回Consumer。
152.RocketMQ的高可用设计:消息发送的高可用,消息存储的高可用,消息消费的高可用,集群管理的高可用。
153.消息发送高可用设计:RocketMQ采用了一些客户端的高可用方案来解决发送失败的问题,其中最重要的两个设计是重试机制与故障延迟机制。
154.消息存储的高可用:RocketMQ主要通过消息持久化(也称刷盘)、主从复制、读写分离机制来保证。
155.消息消费的高可用: RocketMQ主要通过消费重试机制和消息ACK机制来保证。
156.集群管理的高可用:主要体现在NameServer的设计上,即使只剩一个NameServer节点RocketMQ集群也能正常运行,及时NameServer全部宕机,也不影响已经运行的Broker、Producer和Consumer。
157.消息发送重试机制,在消息发送异常时会尝试再次发送,默认最多重试三次,重试机制仅支持同步发送,不支持异步和单向发送方式。根据发送失败的异常类型处理策略不同,如果是网路异常RomotingException和客户读异常MQClientException会重试,而Broker服务端异常MQBrockerException和线程中断异常InterruptedException则不会重试。
158.故障规避机制:用来解决当Broker出现故障,Producer不能及时感知而导致消息发送失败的问题。默认是不开启的,如果开启了,消息发送失败的时候会将失败的Broker暂时排除在队列选择列表外。规避时间是衰减的,如果Broker一直不可用,会被NameServer检测到并在Producer更新路由信息时进行剔除。
159.同步刷盘:同步刷盘模式下,当消息写到内存后,会等待数据写到磁盘的CommitLog文件。在提交刷盘任务后,会在刷盘队列中等待刷盘,而刷盘线程每间隔10毫秒写一批数据到磁盘。不直接写的主要原因是磁盘I/O压力大、写入性能低,每间隔10毫秒写一次可以提升磁盘I/O效率和写入性能。
160.异步刷盘:RocketMQ默认采用异步刷盘,异步刷盘有两种策略:开启缓冲池和不开启缓冲池。默认不开启,则刷盘线程会每间隔500毫秒尝试去刷盘,这间隔500毫秒仅仅是尝试,实际去刷盘还得满足一些前提条件,即距离上次刷盘时间超过10秒,或者写入内存的数据超过4页(16KB),这样即使服务器宕机,丢失的数据也是在10秒内的或者大小在16KB以内的。当开启缓冲池时,RocketMQ会申请一块和CommitLog文件相同大小的堆外内存用来做缓冲池,数据会先写入缓冲池,提交线程也是每隔500毫秒尝试提交到文件通道等待刷盘,和不开启缓冲池的处理一致。使用缓冲池的目的是多条消息合并写入,从而提高I/O性能。
161.主从复制:RocketMQ采用Broker数据主从复制机制,当消息发送到Master服务器后会将消息同步到Slave服务器,如果Master服务器宕机,消息消费者还可以从Slave拉取消息。复制有两种方式:同步复制和异步复制,通过配置文件{ROCKETMQ_HOME}/conf/broker.conf里的brokerRole参数进行设置。
162.读写分离:读写分离机制也是高性能、高可用架构中常见的设计。RocketMQ的Consumer在拉取消息消费时,Broker会判断Master服务器的消息堆积量以决定Consumer是否从Slave服务器拉取消息消费。默认一开始从Master服务器上拉取消息,如果Master服务器的消息堆积超过了物理内存的40%,则会在返回给Consumer的消息里告知Consumer,下次需要从其他Slave服务器上拉取消息。
163.在Consumer由于业务异常导致消费消息失败时,将消费失败的消息重新发送给Broker保存在重试队列,这样设计的原因是不能影响整体消费进度又必须防止消费失败的消息丢失。重试队列的消息存在一个单独的Topic中,不再原消息的Topic中,Consumer自动订阅该Topic,每个ConsumerGroup各自对应一个重试队列的Topic。
164.死信队列:由于业务逻辑Bug等原因,导致Consumer对部分消息长时间消费重试一直失败,为了保证这部分消息不丢失,同时不能阻塞其他重试消费成功的消息,超过最大重试消费次数之后的消息会进入死信队列。消息进入死信队列后就不再自动消费,需要人工干预处理。死信队列也存在一个单独的Topic中,原理和重试队列一致。
165.消费重试机制:RocketMQ的消费重试机制采用时间衰减的方式,使用了自身定时消费的能力。首次在10秒后重试消费,第二次在30秒后,以此类推,最多默认尝试16次后进入死信队列不再重试。重试消费过程中的间隔时间使用了定时消息,重试的消息数据并非直接写入重试队列,而是先写入定时消息队列,再通过定时消息的功能转发到重试队列。RocketMQ支持定时消息(也称延迟消息),但不支持任意时间精确的延迟消息。
166.ACK机制:广播模式的消费进度保存在客户端本地,集群模式的消费进度保存在Broker上。集群模式中RocketMQ中采用ACK机制确保消息一定被消费。因Consumer发送宕机或断电、断网等情况,导致Broker未受到消费反馈,Consumer重启之后,Broker会再次投递消息,消息的幂等性需要业务自行保证。
167.Broker集群部署是消息存储高可用的基本保障,最直接的表现是Broker出现单机故障或重启时,不会影响RocketMQ整体的服务能力。RocketMQ中的Broker有四种不同的集群搭建方式:单Master模式,多Master模式,异步复制的多Master多Slave模式,同步复制的多Master多Slave模式。
168.各个微服务之间通过轻量级通信机制REST API或者RPC完成通信。
169.网关不仅只是做一个请求的转发及服务的整合,还可以:针对所有请求进行统一鉴权、限流、熔断、日志;协议转换;统一错误码处理;请求转发,并且可以基于网关实现内、外网隔离。
170.统一鉴权认证包含客户端身份认证,访问权限控制两部分。
171.灰度发布:又名金丝雀发布,是指将要发布的功能先开放给一小部分用户使用感,把影响范围控制在一个非常小的范围。网关是所有客户端请求的入口,因此在网关层可以通过灰度规则进行部分流量的路由,从而实现灰度发布。
172.网关的本质应该是对请求进行路由和转发,以及对请求进行前置和后置的过滤(网关会拦截所有的请求来完成一系列的横切工作,比如鉴权、限流)。
173.网关的技术选型:OpenResty,Spring Cloud Zuul,Spring Cloud Gateway。
174.Spring Cloud Gateway是依赖于SpringBoot2.0、Spring WebFlux和Project Reactor等技术开发的网关,它不仅提供了统一的路由请求的方式,还基于过滤连的方式提供了网关最基本的功能。
175.路由(Route):网关的基本组件,由ID、目标URI、Predicate集合、Filter集合组成。
176.谓语(Predicate):Java 8中引入的函数式接口,提供了断言的功能。它可以匹配HTTP请求中的任何内容。如果Predicate的聚合判断结果为true,则意味着该请求会被当前Router进行转发。
177.过滤器(Filter):为请求提供前置和后置的过滤。
178.Spring Cloud Gateway启动时基于Netty Server监听的一个指定的端口(该端口可以通过server.port属性自定义)。当客户端发送一个请求到网关时,网关会根据一系列Predicate的匹配结果来决定访问哪个Route路由,然后根据过滤器链进行请求的处理。过滤器链可以在请求发送到后端服务器之前和之后执行,也就是先执行Pre过滤器链,然后将请求转发到服务器,最后执行Post过滤器链。
179.Predicate是java 8提供的一个函数式接口,它允许接收一个参数并返回一个布尔值,可以用于条件过滤、请求参数的校验。在Spring Cloud Gateway中,Predicate提供了路由规则的匹配机制:指定时间规则匹配路由,Cookie匹配路由,Header匹配路由,Host匹配路由,请求方法匹配路由,请求路径匹配路由。
180.在Spring Cloud Gateway中内置了很多Filter,Filter有两种 实现,分别是GatewayFilter和GlobalFilter。GlobalFilter会应用到所有的路由上,而GatewayFilter只会应用到单个路由或者一个分组的路由上。
181.GatewayFilter:AddRequestParameterGatewayFilterFactory,该过滤器的功能是对所哟匹配的请求添加一个查询参数;AddResponseHeaderGatewayFilterFactory,该过滤器会对所有匹配的请求,在返回结果给客户端之前,在Header中添加相应的数据;RequestRateLimiterGatewayFilterFactory,该过滤器会对访问到当前网关的所有请求进行限流过滤,如果被限流,默认情况下会响应HTTP 429-Too Many Requests;RetryGatewayFilterFactory,该过滤器为请求重试过滤器,当后端服务不可用时,网关会根据配置参数来发起重试请求。
182.GlobalFilter:和GatewayFilter的作用是相同的,只是GlobalFilter针对所有的路由配置生效。GatewayMetricsFilter,提供监控指标;LoadBalancerClientFilter,整合Ribbon针对下游服务实现负责均衡;ForwardRoutingFilter,用于本地forward,请求不转发到下游服务器;NettyRoutingFilter,使用Netty的HttpClient转发HTTP、HTTPS请求。
183.全局过滤器链的执行顺序是,当Gateway接收到请求时,FilteringWebHandler处理器会将所有的GlobalFilter实例及所有路由上配置的GatewayFilter实例添加到一条过滤器链中。该过滤器链里所有的过滤器都会按照@Order注解所指定的数字大小进行排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值