SpringCloudAlibaba组件集成

SpringCloudAlibaba组件集成

Nacos服务注册与发现

1.Nacos认识与安装

1.1.什么是Nacos

Nacos和Eureka有着相同的能力,甚至更为强大,作为Dubbo 生态系统中重要的注册中心实现。官方对它有如下定义:

Nacos致力于帮助您发现,配置和管理微服务。它提供了一组简单有用的功能,使您能够实现动态服务发现,服务配置,服务元数据和流量管理。
Nacos使构建,交付和管理微服务平台变得更容易,更快捷。它是通过微服务或云原生方法支持以服务为中心的现代应用程序体系结构的基础架构。

Nacos不仅是服务发现组件,同时也是一个配置管理组件,也就是说它不仅可以用来取代Eureka作为注册中心, 也可以用来取代Spring Cloud Config 做配置统一管理。

1.2.Nacos服务端安装

官方提供了Nacos的服务端供我们下载使用,我们启动Nacos后将我们的微服务注册进入Nacos即可。

下载地址:https://github.com/alibaba/nacos/releases

启动Nacos:解压后,

  • windows执行bin目录下的startup命令 :startup.cmd -m standalone
  • linux 执行 :sh startup.sh -m standalone

访问Nacos,端口8848:http://127.0.0.1:8848/nacos/index.html ,用户名和密码都是:nacos

2.项目结构搭建

2.1.服务调用流程

这里要演示的案例是两个服务的通信,用户服务(user-server)作为服务提供者需要编写接口返回User实体对象,订单服务(order-server)作为消费者需要调用用户服务获取User实体对象,浏览器调用订单服务,订单服务调用用户服务或到User实体后返回给容器,用户和订单都注册到Nacos中,如下:
在这里插入图片描述

注意:这里的订单服务和用户服务都用到了User实体,所以为了让User实体共用,我们为User实体抽取了一个公共的user-common模块,用户服务和订单服务都去依赖这个模块即可使用User实体。

2.2.项目结构搭建

我们根据上面的图例来搭建项目环境,这里使用多模块方式演示,搭建父工程,提供者服务,消费者服务,以及公共的user-common模块,结构如下:

springcloudalibaba-parent
pom.xmlspringcloudalibaba-order-common			//公共的order实体,服务调用传输对象springcloudalibaba-order-server-10020	//提供者服务springcloudalibaba-user-server-10010		//消费者服务

父工程搭建
搭建父工程springcloudalibaba-parent并管理相关依赖,Spring boot版本为2.1.3.RELEASE,Spring Cloud 版本为Greenwich.SR1,Alibaba版本为2.1.0.RELEASE ,父工程的pom如下:

<!--公共的一些配置--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><!--SpringBoot--><parent><groupId> org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version></parent><!--SpringCloud--><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.1.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR3</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!--导入lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency></dependencies>

3.服务注册到Nacos

3.1.导入依赖

修改springcloudalibaba-user-server-1010导入服务发现依赖

 <dependency><groupId>com.alibaba.cloud </groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--加入WEB依赖是为了方便后面写Controller--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2.主配置类

创建配置类加上@EnableDiscoveryClient注解开启服务发现功能,代码如下

//服务注册与发现
@SpringBootApplication
@EnableDiscoveryClient
public class UserServerApplication1010 {public static void main(String[] args) {SpringApplication.run(UserServerApplication1010.class) ;}
}
3.3.配置文件

配置文件主要配置端口,服务名,已经nacos注册中心地址

server:port: 1010
spring:application:name: user-servercloud:nacos:discovery:server-addr: 127.0.0.1:8848	#注册中心地址

4.服务通信

服务通信可以使用Ribbon,OpenFeign,甚至Dubbo,使用方式和在SpirngCloudNetflix中没有任何区别。

Nacos配置管理

1.Nacos配置中心

1.1.概述

Nacos作为Spring Cloud Alibaba的一个重要组件,它不仅可以用作服务注册与发现,也可以用来替代Spring Cloud Config作为统一配置文件管理,而且他的使用更为简单和人性化。

1.2.Nacos添加配置

第一步:打开Nacos监控面板 - 进入配置列表 -点击 “+” 图标添加配置 如下:
在这里插入图片描述

第二步:填写Data ID,选择YAML,编辑配置文件内容

在这里插入图片描述

这里定义了一个名字为application-user-dev.yaml的配置,使用的是YAML格式。

  • Data ID : 非常重要,可以看做是配置的文件的名字,在程序中拉取配置文件的时候需要指定Data ID。

  • Group : 分组,默认是 DEFAULT_GROUP , 可以针对不同的项目指定不同的配置组。

2.客户端接入配置中心(重要)

2.1.导入依赖

修改工程 springcloudalibaba-user-server-1010 ,添加配置中心依赖nacos-config。

     <!--配置中心客户端--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency> 
2.2.编写Controller

下面的Controller用来做配置刷新测试,temp.notify对应了配置文件中的配置项目。@RefreshScope注解是用来做配置自动刷新。那么当我们修改了Nacos中的配置文件,Controller中读取到的配置temp.notify将会自动变化。

@RefreshScope  //刷新配置
@RestController
public class UserController {@Value("${temp.notify}")private String notify;@GetMapping("/user/{id}")public User getById(@PathVariable Long id){System.out.println("测试配置notify="notify);return new User(id,"zs:"+id, "我是zs");}
}
2.3.修改yml配置

注意,将原来的配置文件修改成bootstrap.yml,然后增加如下内容:

server:port: 1010
spring:profiles:active: devapplication:name: user-servercloud:nacos:discovery:server-addr: localhost:8848 #注册中心config:server-addr: localhost:8848 #配置中心file-extension: yaml # 配置文件的后缀名prefix: application-user #配置前缀 ,默认使用sring.application.namegroup: DEFAULT_GROUP #默认分组#如何查找配置文件:application-user + dev + yaml=application-user-dev.yaml 正好和Nacos配置的DataId一致

提示:客户端是如何从Nacos中找到配置文件的呢?

  • spring.cloud.nacos.config.server-addr :配置了Nacos的地址
  • spring.cloud.nacos.config.file-extension:指定了配置文件的格式为YAML,默认是properties,
  • spring.cloud.nacos.config.prefix:配置前缀,如果不配置前缀默认会把 服务名即spring.application.name的值作为前缀
  • spring.cloud.nacos.config.group :分组名,默认是DEFAULT_GROUP对应了Nacos配置中的Group
  • spring.profiles.active:配置了环境为dev .该配置可以实现多配置多环境管理

根据如上配置,那么config客户端会将:前缀+环境+后缀 拼接成的文件名“application-user-dev.yaml” 去Nacos上查找是否有对应Data ID的配置文件。

2.4.测试

启动Nacos,启动 springcloudalibaba-user-server-1010 工程 , 修改Nacos中的配置文件内容,然后访问 http://localhost:1010/user/11 ,观察控制台打印的 “notify”的值会发生变化。

2.5.注意细节
  • 云端配置文件的后缀应该是 yaml而不是yml
  • 客户端配置需要指定:spring.profiles.active=dev 环境名
  • 客户端配置 :前缀 + 环境名 + 后缀应该和云端配置文件的DataId一致

3.命名空间

命名空间可以用来隔离不同项目的配置文件,在Nacos中配置了命名空间后,那么Java客户端需要指定命名空间后才能拉取到该命名空间下的配置文件。

server:port: 1010
spring:profiles:active: devapplication:name: user-servercloud:nacos:discovery:server-addr: localhost:8848 #注册中心config:server-addr: localhost:8848 #配置中心file-extension: yaml #配置文件格式prefix: application-user #配置前缀 ,默认使用sring.application.namegroup: DEFAULT_GROUP #默认分组namespace: 8ef8c1e5-6d20-4efc-80c8-2b2c05541fa3 #命名空间的ID

对应配置而言,可以通过namespace,group,dataid的不同区分不同环境!

  • 区分项目 namespace
  • 区分环境 group(采纳)/dataid(上个项目)

对于服务发现而言,不同组不能相互调用。

  • 区分项目 namespace
  • 区分环境:开发环境(dev-group) 测试环境,线上环境 通过组来区分就欧克

Sentienl限流

Sentinel Server服务端

Sentinel 提供了现成的服务端供我们使用,点我下载地址,下载之后通过命令行启动

java -jar -Dserver.port=1111 sentinel-dashboard-1.6.0.jar

注意:只有1.6.0及以上版本才有这个登录页面。默认用户名和密码都是sentinel。对于用户登录的相关配置可以在启动命令中增加下面的参数来进行配置:

  • -Dsentinel.dashboard.auth.username=sentinel: 用于指定控制台的登录用户名为 sentinel;

  • -Dsentinel.dashboard.auth.password=123456: 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel

  • -Dserver.servlet.session.timeout=7200: 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

  • -Dserver.port=1111:配置端口

Sentinel 客户端接入
1.导入依赖

修改用户服务 springcloudalibaba-user-server-1010 ,加入sentinel依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.配置Sentinel

修改yml配置,添加senticel服务控制台地址

spring:cloud:sentinel:transport:dashboard: localhost:1111
3.资源限流

Sentinel为我们提供了 @SentinelResource 注解标记需要限流的资源。 修改UserController,代码如下:

    @GetMapping("/user/{id}")//限流降级@SentinelResource(value="user",blockHandler="exceptionHandler")public User getById(@PathVariable Long id){System.out.println(notify);return new User(id,"zs:"+id, "我是zs");}// 限流与阻塞处理 : 参数要和 被降级的方法参数一样public User exceptionHandler(@PathVariable Long id, BlockException ex) {ex.printStackTrace();System.out.println("限流了...");return new User(-1L,"限流了","限流了");}

提示:这里通过@SentinelResource的value属性为资源取名为 “user” ,后续我们可以根据该资源名来进行限流。

同时这里通过 blockHandler 属性我配置了一个限流降级方法,即当“user”资源触发限流了会调用blockHandler指向的降级方法返回托底数据,不至于抛出默认的限流异常信息给客户端(一串英文用户也看不懂) ,需要注意的是:降级方法要和被限流的方法参数一致,然后加上 BlockException异常对象。

当然,也可以通过 blockHandlerClass 属性把降级方法写在一个专门的类中,里面方法必须是static,如:

@SentinelResource(value="user",blockHandler="exceptionHandler"
,blockHandlerClass=ExceptionUtil.Class)

降级类

public final class ExceptionUtil {public static User exceptionHandler(Long id ,lockException ex) {//...}
}
Sentinel设置限流策略

启动应用 springcloudalibaba-user-server-1010 ,然后通过浏览器访问 http://localhost:1010/user/11 ,然后登录Sentinel控制台,在“实时监控”列表中可以看到资源的相关监控信息的
在这里插入图片描述

在 “族点链路” 列表中可以看到资源的调用链 ,并且可以通过“流控”按钮设置流控规则
在这里插入图片描述

也可以在“流量控制”菜单中我们可以针对资源进行限流规则的设置。如下:
在这里插入图片描述

这里我添加了一个流控规则,资源名对应客户端 @SentinelResource(value="user".. 注解的资源,通过QPS限流(每秒请求数量),阈值是 1 ,意思是“user”这个资源每秒只能有1个请求进来,多余的请求会触发限流,返回降级数据。

限流测试

通过浏览器频发访问 “user”资源,当QPS大于1就会触发限流,效果如下:
在这里插入图片描述

Sentinel流控模式

直接

Sentinel默认的流控处理就是【直接->快速失败】,QPS(query peer seconds)达到阈值,当前资源直接失败。

关联-你关联的到达一定并发,限制自己

关联的资源达到某个阈值,限流自己,如:限流的资源是/user/delete ,关联的资源是/user/list,当/user/list达到阈值,限流user/delete , 举例: 支付并发太高,可以限制下单的流量 下单关联支付,支付并发过高,限制下单

链路-你调用的到达一定并发,限制自己

限流线路调用链路的入口,如 /user/list 资源中 调用了 /dept/list ,对/dept/list添加限流,当/dept/list达到阈值,其实限流的是/user/list,因为他是访问的入口

Sentinel流控效果
快速失败

快速失败:(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)是默认的流控方式,当流量达到阀值直接返回异常,QPS达到任何规则阈值后,后续请求就会立即拒绝,并抛出FlowException 异常。简单理解:并发太高,直接请求拒绝

Warm Up预热

Warm Up预热:(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,根据codeFactor(默认3)的值,从(阀值/codeFactor)为初始阀值,经过预热时长,才到达设置的QPS的阀值,即预热/冷启动方式。简单理解:慢慢的增大处理并发的能力

提示:初始的QPS阈值为 100 / 3 =33 ,10秒后 QPS阈值达到 100.

当系统长期并发不高,流量突然增加可能会直接把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值的上限,给系统一个预热的时间,避免冷系统被压垮。

排队等待

排队等待(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER),忽然增加的请求并发量达到了限流阈值后续请求会被拒绝,有时候我们可能更希望后续的请求可以加入队列进行排队,慢慢执行,而不是直接拒绝请求,这种方式后严格控制请求通过的时间间隔,也即是让请求以均匀的速度通过,对应的是漏桶算法,这种方式主要用于处理间隔性突发的流量,例如消息队列。 简单理解:突发流量处理不过来,让请求排队。

热点限流

还有一种特殊的动态限流规则,用于限制动态的热点资源 , 比如对同一个用户的请求频率做限定,比如对参数进行限定,比如对参数的值做限定(比如对商品ID为1的资源做限流)。

参数限流

参数限流就是 对资源的参数进行限流,我们来编写一个方法,接受两个参数:p1,和p2并设置好限流降级。

//限流降级
@SentinelResource(value="/parameterLimit",blockHandler="parameterLimitHandler")
@GetMapping(value="/parameterLimit")
public String parameterLimit(@RequestParam("p1") String p1 ,@RequestParam("p2") String p2){return "parameterLimit方法调用成功...";
}
// 限流与阻塞处理
public String parameterLimitHandler(@RequestParam("p1") String p1 ,@RequestParam("p2") String p2,BlockException ex) {return "限流了...";
}

配置热点规则 , 对第一个参数限流 , 当第一个参数超过了1的QPS就熔断降级。
在这里插入图片描述

参数值限流

对某一个参数的值满足某种条件的时候就进行限流,如下配置

在这里插入图片描述

意思是第一个参数的值为 haha 的时候限流阈值为10 , 超过 QPS > 10的并发就限流。

举例:应用场景比如说商品名称为“华为p40”的商品并发特别高,我们可以针对参数商品名为“华为p40”的商品进行限流。

系统规则
配置全局限流规则

系统规则可以看做是总的限流策略,所有的只要都要受到系统规则的限制。

Gateway使用Sentinel限流

Spring Cloud Gateway 作为微服务的网关,它是微服务的访问入口,当请求的流量洪峰到来我们可以在Gateway网关层通过Sentinel对请求进行流控,把好第一道关。

导入依赖

这里我们需要导入sentinel基础依赖和 sentinel-gateway 整合依赖

<!--    限流和gataway使用-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId></dependency><dependency>	<groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
配置Sentinel地址

修改yml配置,增加Sentinel服务地址

spring:cloud:sentinel:transport:dashboard: localhost:1111
配置限流规则

启动Gateway,登录sentinel控制台,对url资源进行流控限制,配置方式和前面的配置方式一样,

限流算法

Spring Cloud Alibaba Sentinel底层采用了以下几种流行的限流算法:

  1. 直接计数(Direct Count):基于固定时间窗口的计数器算法,根据单位时间内的请求数量进行限流。这是最简单直接的一种算法,但不支持动态参数调整。
  2. 滑动窗口(Sliding Window):通过滑动时间窗口内的请求数量来判断是否进行限流,支持按时间窗口和请求个数进行配置。Sentinel使用双向队列存储时间窗口内的请求记录,并根据请求的时间戳进行滑动。
  3. 令牌桶(Token Bucket):基于令牌桶算法,使用令牌桶中的令牌数量来控制单位时间内的请求速率。Sentinel底层实现了一个简化版的令牌桶算法,可以动态调整令牌生成速率和桶容量。
  4. 漏桶(Leaky Bucket):基于漏桶算法,通过固定速率的流出速度来控制单位时间内的请求速率。Sentinel底层实现了一个简化版的漏桶算法,可以动态调整漏桶的流出速率和桶容量。

此外,Sentinel还支持系统自适应限流算法,该算法会根据系统的负载情况自动调整限流策略,例如根据平均响应时间、QPS等指标进行动态调整。

以上是Spring Cloud Alibaba Sentinel底层常用的限流算法。可以根据具体场景和需求选择适合的算法进行配置。

Sentinel熔断

资源熔断降级

修改springcloudalibaba-user-1010工程,修改UserController ,通过@SentinelResource注解的fallback 属性指定降级方法。

  	// 限流降级public User exceptionHandler(@PathVariable Long id, BlockException ex) {ex.printStackTrace();System.out.println("限流了...");return new User(-1L,"限流了","限流了");}// 熔断降级,参数和返回值与源方法一致public User getByIdfallback(@PathVariable Long id){System.out.println(notify);return new User(id,"zs:"+id, "熔断托底了");}@GetMapping("/user/{id}")//限流降级@SentinelResource(value="user",blockHandler="exceptionHandler",fallback = "getByIdfallback")public User getById(@PathVariable Long id){int i = 1 / 0;	//方法异常,触发熔断return new User(id,"zs:"+id, "我是zs");}

提示:方法中通过 int i = 1 / 0; 模拟异常,然后会熔断触发降级调用降级方法 。 通过 fallback 属性指定熔断的降级方法 ,熔断方法参数也要和被熔断方法参数一致。

注意:这里可以通过 @SentinelResource注解的 exceptionsToTrace 属性忽略异常,即针对某个异常不熔断

2.2.配置降级策略

在Sentinel控制台,在族点链路菜单中找到“user”资源,然后点击“降级”按钮添加降级策略,如下:
在这里插入图片描述

这里的降级策略为“RT”,大概意思是:如果并发数大于5 (QPS > 5) ,然后平均响应时间大于200毫秒,那么接下来的2秒钟之内对该资源的请求会被熔断降级。

2.3.测试熔断

启动springcloudalibaba-user-1010工程,访问 http://localhost:1010/user/2 ,浏览器返回:
在这里插入图片描述

这里已经返回了托底数据,其实是因为“user”资源方法中抛出了异常,触发了熔断降级。

3.熔断规则

资源在什么情况下会触发熔断降级?调用异常,达到流控,调用超时 都会触发熔断降级,在上面的案例中我们看到资源的降级策略有 RT,异常比例,异常数三种方式,我们可以通过这三种方式来定义资源是否稳定,决定是否要进行熔断降级。

3.1.平均响应RT

平均响应时间 (DEGRADE_GRADE_RT):当资源的平均响应时间超过阈值(DegradeRule 中的 count,以 ms 为单位)之后,资源进入准降级状态。如果接下来 1s 内持续进入 5 个请求(即 QPS >= 5),它们的 RT 都持续超过这个阈值,那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。

总结一下:RT其实就是平均相应时间太长资源熔断。

3.2.异常比例

异常比例(DEGRADE_GRADE_EXCEPTION_RATIO):每秒请求量 > 5 ,当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

总结一下:异常比例就是按照资源的请求失败率来熔断。

3.3.异常数

异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。

总结一下:异常数就是按照 一分钟的异常的数量 来熔断。

3.4.慢调用比例

熔断策略慢调用比例是以慢调用数量的比例作为阈值,首先需要设置最大 RT(即最大的响应时间,用于鉴定是否是慢调用),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数大于设置的最小请求数,并且慢调用的比例大于比例阈值,则接下来的请求会自动熔断,熔断时间为设置的熔断时长。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若在HALF-OPEN状态下有一个请求响应时间小于 最大RT 则结束熔断,否则继续熔断。

4.openFeign整合Sentinel熔断

Spring Cloud Alibaba是Spring Cloud的一个子项目,OpenFeign是Spring Cloud的客户端负载均衡器,使用Spring Cloud Alibaba依然可以很方便的集成OpenFeign,如果要使用OpenFeign作为服务客户端负载均衡,那么我们需要考虑OpenFeign开启Sentinel进行服务熔断降级。

4.1.开启Sentinel

OpenFeign与Sentinel组件集成除了引**入sentinel-starter**依赖关系之外,还需要在属性文件中启用Sentinel支持:feign.sentinel.enabled=true

feign:sentinel:enabled: true #熔断
4.2.给Feign接口降级

这里跟Feign开启Hystrix降级一样,还是可以使用fallback属性

@FeignClient(value = "user-server",fallback = UserClientFallback.class)
public interface UserClient {@GetMapping("/user/{id}")User getById(@PathVariable Long id);
}
4.3.编写降级类
@Component
public class UserClientFallback implements UserClient {    @Override    public User getById(Long id) {        return new User(-1L,"无此用户","无此用户");    }
}

服务网关SpringCloud Gateway

Spring Cloud Gataway的特点

在Spring Cloud官方定义了SpringCloud Gateway 的如下特点:

  • 基于 Spring 5,Project Reactor , Spring Boot 2.0
  • 默认集成 Spring Cloud DiscoveryClient
  • 默认集成 Hystrix 断路器
  • Predicates(断言) 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters
  • 支持动态路由、限流、路径重写
Spring Cloud Gataway的核心概念

Spring Cloud Gataway有几个核心组成:

  • Filter(过滤器):

Spring Cloud Gateway的Filter和Zuul的过滤器类似,可以在请求发出前后进行一些业务上的处理 ,这里分为两种类型的Filter,分别是Gateway Filter网关filter和Global Filter全局Filter, 他们的区别在后续会讲到。

  • Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。说白了就是把url请求路由到对应的资源(服务),或者说是一个请求过来Gateway应该怎么把这个请求转发给下游的微服务,转发给谁。

  • Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。简单理解就是处理HTTP请求的匹配规则,在什么样的请情况下才能命中资源继续访问。

Spring Cloud Gateway的工作方式

Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种,下面是官方的执行流程图:
在这里插入图片描述
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链来运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。

Spring Cloud Gataway入门

工程名:springcloud-gateway-server-1110 ,导入gataway基础依赖

 <dependencies><dependency><groupId>com.alibaba.cloud </groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--拉取配置中心--><dependency><groupId>com.alibaba.cloud </groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies>
2.2.主配置类
//服务注册与发现
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayServerApplication1110 {public static void main(String[] args) {SpringApplication.run(GatewayServerApplication1110 .class);}
}
2.3.yml配置
server:port: 7010
spring:application:name: gateway-servicecloud:nacos:discovery:server-addr: 127.0.0.1:8848	#注册中心地址namespace: 0f800d23-c0dd-4eb8-b0c0-1de010bab3efgroup: sbgateway:discovery:locator:enabled: false #false 不开放服务名访问方式lower-case-service-id: true #服务名小写routes:- id: xxxx #指定服务名uri: lb://order-service #去注册中心找这个服务名predicates: #断言,匹配访问的路径- Path=/services/order/**    #服务访问路径filters:- StripPrefix=2    #请求转发的时候会去掉 /user访问路径- id: yyyy #指定服务名uri: lb://user-service #去注册中心找这个服务名predicates: #断言,匹配访问的路径- Path=/services/user/**    #服务访问路径filters:- StripPrefix=2    #请求转发的时候会去掉 /user访问路径

这里除了要注册到nacos以外,还需要配置Gataway的路由

  • spring.cloud.gateway.discovery.locator.enabled=false: 不开放服务名访问方式
  • spring.cloud.gateway.discovery.locator.lower-case-service-id: true 忽略服务名大小写,大写小写都可以匹配
  • spring.cloud.gateway.routes.id : 指定了路由的服务名,可以自己定义
  • spring.cloud.gateway.routes.uri=lb://user-server : 去注册中心找服务,采用负载均衡的方式请求。其实就是找要调用的服务。
  • spring.cloud.gateway.routes.predicates: 断言,这里使用的Path=/user/**,即匹配访问的路径如果匹配/user/就可以将请求路由(分发)到user-server这个服务上。
  • spring.cloud.gateway.routes.filters :这里使用StripPrefix=1主要是处理前缀 /user ,访问目标服务的时候会去掉前缀访问。这个需要根据url情况来定义。
Predicate断言工厂
什么是断言工厂

什么是断言工程,在Spring Cloud Gateway官方文档有如下解释:

Spring Cloud Gateway将路由作为Spring WebFlux HandlerMapping基础架构的一部分进行匹配。Spring Cloud Gateway包括许多内置的路由断言工厂。所有这些断言都与HTTP请求的不同属性匹配。您可以将多个路由断言工厂与逻辑and语句结合使用。

这里不难理解,其实断言工厂就是用来判断http请求的匹配方式。比如我们再上面案例中配置的:“Path=/user/**” ,就是使用的是 “Path Route Predicate Factory” 路径匹配工厂,意思是http请求的资源地址必须是 /user 才会被匹配到对应的路由,然后继续执行对应的服务获取资源。

在Spring Cloud Gateway中,针对不同的场景内置的路由断言工厂,比如

  • Query Route Predicate Factory:根据查询参数来做路由匹配
  • Path Route Predicate Factory: 更加路径来匹配
  • RemoteAddr Route Predicate Factory:根据ip来做路由匹配
  • Header Route Predicate Factory:根据请求头中的参数来路由匹配
  • Host Route Predicate Factory:根据主机名来进行路由匹配
  • Method Route Predicate Factory :根据方法来路由匹配
  • Cookie Route Predicate Factory:根据cookie中的属性值来匹配
  • Before Route Predicate Factory:指定时间之间才能匹配
  • After Route Predicate Factory: 指定时间之前才能匹配
  • Weight Route Predicate Factory: 根据权重把流量分发到不同的主机
Gateway 的 Filter 过滤器
Gateway filter

针对单个路由的Filter, 它允许以某种方式修改HTTP请求或HTTP响应。过滤器可以作用在某些特定的请求路径上。Gateway内置了很多的GatewayFilter工厂。如果要使用这些Filter只需要在配置文件配置GatewayFilter Factory的名称。下面拿一个内置的Gateway Filter举例:

AddRequestHeader GatewayFilter Factory
该Filter是Gateway内置的,它的作用是在请求头加上指定的属性。配置如下:

spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgfilters:- AddRequestHeader=X-Request-red, blue

spring.cloud.gateway.routes.filters配置项配置了一个AddRequestHeader ,他是“AddRequestHeader GatewayFilter Factory”的名称,意思是在请求头中添加一个“X-Request-red”的属性,值为blue

其他的Filter可以去看 AbstractGatewayFilterFactory 的实现类。

自定义Gateway Filter-局部过滤器

在Spring Cloud Gateway自定义过滤器,过滤器需要实现GatewayFilter和Ordered这两个接口。我们下面来演示自定义filter计算请求的耗时。

public class RequestTimeFilter implements GatewayFilter, Ordered {private static final Log log = LogFactory.getLog(GatewayFilter.class);private static final String COUNT_Start_TIME = "countStartTime";@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//开始时间exchange.getAttributes().put(COUNT_Start_TIME, System.currentTimeMillis());//执行完成之后return chain.filter(exchange).then(Mono.fromRunnable(() -> {//开始时间Long startTime = exchange.getAttribute(COUNT_Start_TIME);//结束时间Long endTime=(System.currentTimeMillis() - startTime);if (startTime != null) {log.info(exchange.getRequest().getURI().getRawPath() + ": " + endTime + "ms");}}));}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}

提示: getOrder返回filter的优先级,越大的值优先级越低 , 在filterI方法中计算了请求的开始时间和结束时间

最后我们还需要把该Filter配置在对应的路由上,配置如下:

@Configuration
public class FilterConfig {//配置TokenCheckFilter作用于那个访问规则上@Beanpublic RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route(r -> r.path("/user/**")  // 只有/user/**的请求才会经过RequestTimeFilter.filters(f -> f.stripPrefix(1).filter(new RequestTimeFilter()).addResponseHeader("X-Response-test", "test")).uri("lb://user-server").order(0).id("test-RequestTimeFilter")).build();}
}

提示:这里将 RequestTimeFilter 添加到 “/user/**”这里路由上,当请求包含/user就会触发Filter的执行。

自定义GlobalFilter(重点)-全局过滤器

GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。
这里我们模拟了一个登陆检查的Filter.

@Component
public class TokenFilter implements GlobalFilter , Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//从请求头中获取tokenHttpHeaders headers = exchange.getRequest().getHeaders();List<String> strings = headers.get("token");//如果没有拦截if (strings==null|| strings.size()<1){exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}//否则放行return chain.filter(exchange);}@Overridepublic int getOrder() {return -200;}
}

如果请求参数中没有 authToken ,就返回没有权限的状态。

Gateway跨域配置

所谓的跨域是因为浏览器的同源(同一个域)策略限制,其实就是同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互 ,在前后端分离的项目架构中就会出现跨域问题,因为Gateway 网关是微服务的访问入口,所以我们只需要在Gateway配置跨域即可:官方文档

spring:cloud:globalcors: #跨域配置cors-configurations:'[/**]':allowedOrigins: "https://docs.spring.io" #允许的站点allowedMethods:	#允许的请求方式- GET- POST- DELETE- PUT- HEAD- CONNECT- TRACE- OPTIONSallowHeaders:	#允许的请求头- Content-Type

提示:运行跨域访问的站点:https://docs.spring.io ,同时把常见的请求方式都开放。

Gateway超时

超时配置在微服务调用和数据读取的时候显得尤为重要,下面演示Gateway中的全局超时设置:

spring:cloud:gateway:httpclient:connect-timeout: 1000response-timeout: 5s

指定路由超时配置:

spring:cloud:gateway: routes:- id: per_route_timeoutsuri: https://example.orgpredicates:- name: Pathargs:pattern: /delay/{timeout}metadata:response-timeout: 200connect-timeout: 200

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/353360.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kettle从入门到精通 第七十一课 ETL之kettle 再谈http post,轻松掌握body中传递json参数

场景&#xff1a; kettle中http post步骤如何发送http请求且传递body参数&#xff1f; 解决方案&#xff1a; http post步骤中直接设置Request entity field字段即可。 1、手边没有现成的post接口&#xff0c;索性用python搭建一个简单的接口&#xff0c;关键代码如下&#…

JCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断

JJCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断 目录 JJCR一区 | Matlab实现GAF-PCNN、GASF-CNN、GADF-CNN的多特征输入数据分类预测/故障诊断分类效果格拉姆矩阵图GAF-PCNNGASF-CNNGADF-CNN 基本介绍程序设计参考资料 分类效果 格拉姆…

NVIDIA新模型Nemotron-4:98%的训练数据是合成生成的,你敢信?

获取本文论文原文PDF&#xff0c;请公众号 AI论文解读 留言&#xff1a;论文解读 标题&#xff1a;Nemotron-4 340B Technical Report 模型概述&#xff1a;Nemotron-4 340B系列模型的基本构成 Nemotron-4 340B系列模型包括三个主要版本&#xff1a;Nemotron-4-340B-Base、…

序列化与反序列化漏洞实例

实验环境&#xff1a; 本次的序列化与反序列化漏洞为2021年强网杯上的一道比赛题目&#xff0c;我使用phpstudy集成环境将其测试环境搭建在了本地&#xff0c;如下。涉及的几个页面php为&#xff1a; index.php function.php myclass.php index.php : <?php // inde…

二叉树、二叉查找树、平衡二叉树及各种旋转机制

二叉树 大体构型&#xff1a; 树里每个结点存储的有&#xff1a;所有树都是这样 二叉树的度&#xff1a;任意节点度<2 二叉树的属性&#xff1a; 二叉树的遍历顺序&#xff1a; 前&#xff1a; 中&#xff1a; 后&#xff1a; 二叉查找树&#xff1a;每个节点最多2子节点&…

最新Prompt预设词分享,DALL-E3文生图+文档分析

使用指南 直接复制使用 可以前往已经添加好Prompt预设的AI系统测试使用&#xff08;可自定义添加使用&#xff09; 支持GPTs SparkAi SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。支持GPT-4o…

SAP STO跨公司间转储含POD交货后台配置简介

在前面的博文中我们演示了STO跨公司间转储含POD的前台的操作。本文将演示后台的配置的操作步骤 1、首先是客户和供应商的设置 关联方的既要是供应商也试试客户 2、设置装运条件 路径&#xff1a;SPRO—>物料管理—>采购—>采购订单—>设置库存调拨订单—>定义…

TestProject Python SDK入门

2024软件测试面试刷题&#xff0c;这个小程序&#xff08;永久刷题&#xff09;&#xff0c;靠它快速找到工作了&#xff01;&#xff08;刷题APP的天花板&#xff09;-CSDN博客跳槽涨薪的朋友们有福了&#xff0c;今天给大家推荐一个软件测试面试的刷题小程序。​编辑https://…

[Qt的学习日常]--常用控件3

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、显示类控…

【Linux Vim的保姆级教程】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

温湿度采集与OLED显示

目录 一、什么是软件I2C 二、什么是硬件I2C 三、STM32CubeMX配置 1、RCC配置 2、SYS配置 3、I2C1配置 3、I2C2配置 4、USART1配置 5、TIM1配置 6、时钟树配置 7、工程配置 四、设备链接 1、OLED连接 2、串口连接 3、温湿度传感器连接 五、每隔2秒钟采集一次温湿…

前端技术回顾系列 11|TS 中一些实用概念

在微信中阅读,关注公众号:CodeFit。 创作不易,如果你觉得这篇文章对您有帮助,请不要忘了 点赞、分享 和 关注 我的公众号:CodeFit,为我的持续创作提供动力。 上文回顾:泛型在类和接口中的应用 上一篇文章我们回顾了 泛型 在 类 和 接口 中的应用。 通过使用泛型,我们…

【Linux环境下Hadoop部署—Xshell6】解决“要继续使用此程序,您必须应用最新的更新或使用新版本。”

问题描述 打开xshell使用&#xff0c;弹出&#xff1a; 解决方案&#xff1a; 修改安装目录下面的 nsilense.dll 文件 用二进制编辑器&#xff08;notepad的HEX-Editor插件&#xff09;打开Xshell/Xftp安装目录下的 nslicense.dll。 HexEdit插件安装&#xff1a; 1.下载HexEdi…

springboot与flowable(7):流程变量

一、启动时添加流程变量 拿第一个流程图举例&#xff0c;创建一个新的流程定义。 Testvoid contextLoads() {DeploymentBuilder deployment repositoryService.createDeployment();deployment.addClasspathResource("process01/FirstFlow.bpmn20.xml");deployment.…

算法设计与分析 实验3 回溯法求地图填色问题

目录 一、实验目的 二、背景知识 三、实验内容 四、算法思想 未优化的回溯算法 节点选择-最小剩余值准则&#xff08;MRV&#xff09; 节点选择-最多约束准则&#xff08;DH&#xff09; 颜色选择-最少约束选择 数据结构的选择 向前探查 颜色轮换&#xff08;贪心置…

专业技能篇---计算机网络篇

文章目录 前言计算机网络基础一、网络分层模型 HTTP一、从输入URL到页面显示发生了什么&#xff1f;二、Http的状态码有哪些&#xff1f;三、 HTTP与HTTPS有什么区别&#xff1f;四、URI 和 URL 的区别是什么?五、Cookie和Session有什么区别&#xff1f;六、GET与POST 前言 主…

shell脚本之函数

一、1.函数&#xff1a;将命令序列按照固定的表达格式写在一起 2.函数作用&#xff1a;可以重复使用的命令序列&#xff0c;大的工程分割成若干个小块&#xff0c;依次执行&#xff0c;提高代码的可读性。 3.函数的两种格式 4.return作用&#xff1a;只能写在函数内部&#xff…

Facebook:数字时代的文化交流平台

在当今信息爆炸的数字时代&#xff0c;Facebook已经成为了一个不可或缺的社交媒体平台&#xff0c;不仅在个人生活中起到了联系社交的作用&#xff0c;更在全球范围内促进了文化交流和理解。本文将深入探讨Facebook作为文化交流平台的重要性&#xff0c;并分析其在数字时代如何…

个人博客测试用例设计

个人博客测试用例设计 个人博客测试用例 分别从功能、性能、安全、兼容及界面分别展开 个人博客测试用例

文库小程序搭建部署:实现资源共享正向反馈

文档库相信大家应该不陌生&#xff0c;日常我们的工作模板、会议模板、求职时的简历模板、教育界的教学模板等来源方式都出自于文档库&#xff0c;随着互联网的发展和工作需求&#xff0c;文档模板开启了新型的知识变现新途径&#xff0c;通过文库小程序&#xff0c;我们不仅能…