欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > SpringCloud Alibaba

SpringCloud Alibaba

2025/2/25 23:30:05 来源:https://blog.csdn.net/qq_67177419/article/details/144829719  浏览:    关键词:SpringCloud Alibaba

目录

Spring Cloud Alibaba 参考文档

Nacos:

例:

基于nocos服务的提供者: 

基于nocos服务的消费者: 

Nocos作为配置中心配置: 

Namespace-Group-DataId:

Sentinel:

作用:

下载运行:

流控模式:

直接:

关联:

​编辑

链路:

流控效果: 

预热warm up:

排队等待: 

熔断:

慢调用比例:

异常比例:

异常数:

@SentinelResource

资源名称限流+自定义限流返回: 

热点: 

普通正常限流: 

参数例外项:

授权:

持久化:

依赖: 

yml:

添加Nacos业务配置规则:

GateWay和Sentinel集成实现服务限流 

1. 类和注解

2. 成员变量和构造函数

3. SentinelGatewayBlockExceptionHandler Bean

4. SentinelGatewayFilter Bean

5. doInit() 方法

6. initBlockHandler() 方法

7. 核心流程概述

8. 作用与总结



Nacos:

Nacos = Eureka+Config +Bus 

Nacos = Spring Cloud Consul 

官网-下载:点击跳转 

启动Nacos服务器:

startup.cmd -m standalone 

例:

基于nocos服务的提供者: 

 依赖:

 <!--nacos-discovery-->
        
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

yml:

server:port: 9001spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址

配置controller:

package com.atguigu.cloud.controller;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class PayAlibabaController
{@Value("${server.port}")private String serverPort;@GetMapping(value = "/pay/nacos/{id}")public String getPayInfo(@PathVariable("id") Integer id){return "nacos registry, serverPort: "+ serverPort+"\t id"+id;}
}

nocos控制台:http://localhost:8848/nacos

可以查看到服务已经被注册进来。

基于nocos服务的消费者: 

依赖:

 <!--nacos-discovery-->
        
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--loadbalancer-->
        
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
 

yml:

server:
  port83

spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
#消费者将要去访问的微服务名称(nacos微服务提供者叫什么你写什么)
service-url:
  nacos-user-service: http://nacos-payment-provider
 

配置config:

package com.atguigu.cloud.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class RestTemplateConfig {@Bean@LoadBalanced//赋予RestTemplate负载均衡的能力public RestTemplate restTemplate(){return new RestTemplate();}
}

 运行结果:

Nocos作为配置中心配置: 

依赖:

 <!--bootstrap-->
        
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <!--nacos-config-->
        
<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency

application.yml:

 server:
  port3377

spring:
  profiles:
    active: dev 表示开发环境
       
#active: prod # 表示生产环境
       
#active: test # 表示测试环境

bootstrap.yml:

# nacos 配置
spring:
   application:
     name: nacos-config-client
   cloud:
     nacos:
       discovery:
         server-addr: localhost:8848  #Nacos 服务注册 中心地址
      
config:
         server-addr: localhost:8848  #Nacos 作为 配置中心 地址
        
file-extension: yaml  # 指定 yaml 格式的配置

# nacos 端配置文件 DataId 的命名规则是:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
本案例的 DataID :nacos-config-client-dev.yaml

为什么需要写2个yml:

Nacos同Consul一样,在项目初始化时,要保证先从配置中心进行配置拉取,

拉取配置之后,才能保证项目的正常启动,为了满足动态刷新和全局广播通知

 

springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application

nocos的dataid配置公式:

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} 

Namespace-Group-DataId:

 Namespace:

Group:

 

DataId:

 

prod对应上面的

nacos-config-client-prod.yaml

 的prod。

修改config,添加上指定的namespace喝group,如果不指定会使用默认的配置:

Sentinel:

官网:home | Sentinel 

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

作用:

从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性 

下载运行:

下载好jar包后,通过 java -jar 包名 运行 

通过yml将服务注册进nacos和sentinel:

server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848         #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口

sentinel采用的是懒加载,即没有流量就不加载,有流量才加载:

流控模式:

直接:

关联:

链路:

yml:

web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路

 通过C,D 2个链路去调用service

配置sentinel:

 通过C去调用service,会受到限流。

流控效果: 

预热warm up:

 

预热5秒钟,最高阈值为6,预热时为 最高阈值的1/3 --->2 

排队等待: 

注:

每秒钟允许处理一个请求,当请求发出5秒后没被处理就会被拒绝。

比如第一秒发出20个请求,现在的设置5秒内处理的请求数量是6个,其他的15个就会被拒绝掉。

熔断:

慢调用比例:

进入熔断状态判断依据:在统计时长内,实际请求数目>设定的最小请求数    且      实际慢调用比例>比例阈值 ,进入熔断状态。   

例 :

/*** 新增熔断规则-慢调用比例* @return*/
@GetMapping("/testF")
public String testF()
{//暂停几秒钟线程try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }System.out.println("----测试:新增熔断规则-慢调用比例 ");return "------testF 新增熔断规则-慢调用比例";
}

每次调用设置为1s

但是在配置时我们配置的时间是200毫秒,所有会被熔断

使用jmeter发送10个请求:

再次访问该地址,会发现进入熔断状态:

异常比例:

异常比例(ERROR_RATIO ):当单位统计时长(statInterva1Ms)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是[0.0,1.0],代表 0%-100%。 

异常数:

异常数(ERROR COUNT ):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

@SentinelResource

SentinelResource是一个流量防卫防护组件注解,

用于指定防护资源,对配置的资源进行流量控制、熔断降级等功能。 

资源名称限流+自定义限流返回: 

@GetMapping("/rateLimit/byResource")@SentinelResource(value = "byResourceSentinelResource",blockHandler = "handleException")public String byResource(){return "按资源名称SentinelResource限流测试OK";}public String handleException(BlockException exception){return "服务不可用@SentinelResource启动"+"\t"+"o(╥﹏╥)o";}

@SentinelResource(value = "byResourceSentinelResource", blockHandler = "handleException")

  • 这是 Sentinel 提供的注解,主要用于配置资源限流、降级、熔断等策略。
    • value = "byResourceSentinelResource":资源名称,用于标识当前方法的限流资源。Sentinel 使用这个资源名称来监控和控制该方法的流量。
    • blockHandler = "handleException":指定一个方法来处理限流(或熔断)触发时的异常。具体来说,当资源超出流量限制时,Sentinel 会调用这个 blockHandler 方法来处理业务逻辑。

 看到这,我们很容易联想到服务降级,那blockHandler和fallback有什么区别呢?

blockHandler,主要针对sentinel配置后出现的违规情况处理

fallback,程序异常了JVM抛出的异常服务降级

热点: 

 何为热点

热点即经常访问的数据,很多时候我们希望统计或者限制某个热点数据中访问频次最高的TopN数据,并对其访问进行限流或者其它操作

普通正常限流: 

现在设置的是对第一个参数进行限流,没有设置对第二个参数进行限流。

http://localhost:8401/testHotKey?p1=abc  每秒频次超过1会限流

http://localhost:8401/testHotKey?p1=abc&p2=33含有参数P1,当每秒访问的频率超过1次时,会触发Sentinel的限流操作

http://localhost:8401/testHotKey?p2=abc 没有热点参数P1,不断访问则不会触发限流操作

参数例外项:

 我们期望p1参数当它是某个特殊值时,到达某个约定值后【普通正常限流】规则突然例外、失效了,它的限流值和平时不一样。

假如当p1的值等于5时,它的阈值可以达到200或其它值

授权:

在某些场景下,需要根据调用接口的来源判断是否允许执行本次请求。此时就可以使用Sentinel提供的授权规则来实现,Sentinel的授权规则能够根据请求的来源判断是否允许本次请求通过。

在Sentinel的授权规则中,提供了 白名单与黑名单 两种授权类型。白放行、黑禁止

例:

@Component
public class MyRequestOriginParser implements RequestOriginParser
{@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getParameter("serverName");}
}

 配置:

表示serverName带有test,test2的参数 会被限流

持久化:

 将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

依赖: 

<!--SpringCloud ailibaba sentinel-datasource-nacos -->
        
<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency

yml:
server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848         #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路datasource:ds1:nacos:server-addr: localhost:8848dataId: ${spring.application.name}groupId: DEFAULT_GROUPdata-type: jsonrule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType

查看源码可知,rule-type对应的就是:

流量控制规则 FlowRule
熔断降级规则 DegradeRule
访问控制规则 AuthorityRule
系统保护规则 SystemRule
热点规则 ParamFlowRule。           

所有我们需要使用什么就配置什么,这里我配置的是flow    流量控制规则

添加Nacos业务配置规则:

[

    {

        "resource": "/rateLimit/byUrl",

        "limitApp": "default",

        "grade": 1,

        "count": 1,

        "strategy": 0,

        "controlBehavior": 0,

        "clusterMode": false

    }

]


 

resource:资源名称;
limitApp:来源应用;
grade:阈值类型,0表示线程数,1表示QPS;
count:单机阈值;
strategy:流控模式,0表示直接,1表示关联,2表示链路;
controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
clusterMode:是否集群。

GateWay和Sentinel集成实现服务限流 

@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer){this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {// Register the block exception handler for Spring Cloud Gateway.return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@Bean@Order(-1)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@PostConstruct //javax.annotation.PostConstructpublic void doInit() {initBlockHandler();}//处理/自定义返回的例外信息private void initBlockHandler() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("pay_routh1").setCount(2).setIntervalSec(1));GatewayRuleManager.loadRules(rules);BlockRequestHandler handler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {Map<String,String> map = new HashMap<>();map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("errorMessage", "请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));}};GatewayCallbackManager.setBlockHandler(handler);}}

 解析:

这段代码配置了 Spring Cloud GatewaySentinel 的整合,目的是在网关层面使用 Sentinel 进行流量控制,并自定义限流触发后的响应。下面是逐行解析:

1. 类和注解

@Configuration
public class GatewayConfiguration {
  • @Configuration:表示该类是一个 Spring 配置类,Spring 会扫描这个类,并将其中的 @Bean 方法注册到 Spring 容器中。

2. 成员变量和构造函数

private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;
}
  • viewResolversserverCodecConfigurer:这两个成员变量分别用于 Spring WebFlux 的视图解析器和编解码器配置。
  • 构造函数注入:viewResolversProvider 是一个 ObjectProvider,它可以提供 Spring 配置的视图解析器列表(如果有的话),如果没有则返回一个空列表。serverCodecConfigurer 用于配置 WebFlux 的编解码器。

3. SentinelGatewayBlockExceptionHandler Bean

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
  • @Bean:将这个方法返回的对象注册为 Spring 的 Bean。
  • @Order(Ordered.HIGHEST_PRECEDENCE):该注解设置了 SentinelGatewayBlockExceptionHandler 的优先级为最高,意味着它会优先于其他的 GlobalFilter 处理请求。
  • SentinelGatewayBlockExceptionHandler 是一个处理 Sentinel 限流或熔断异常的处理器,在请求被限流或阻止时,会触发该处理器。

4. SentinelGatewayFilter Bean

@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();
}
  • @Bean:这段代码注册了一个 SentinelGatewayFilter 实例,它是一个 GlobalFilter,用于在 Spring Cloud Gateway 中进行全局的限流控制。
  • @Order(-1):设置该过滤器的优先级为负值,确保它在其他过滤器之前执行。

5. doInit() 方法

@PostConstruct
public void doInit() {initBlockHandler();
}
  • @PostConstruct:表示 doInit() 方法会在 Spring 完成依赖注入之后自动执行。这个方法调用了 initBlockHandler(),用于初始化限流规则和限流后的处理逻辑。

6. initBlockHandler() 方法

private void initBlockHandler() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("pay_routh1").setCount(2).setIntervalSec(1));GatewayRuleManager.loadRules(rules);BlockRequestHandler handler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {Map<String, String> map = new HashMap<>();map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("errorMessage", "请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));}};GatewayCallbackManager.setBlockHandler(handler);
}
  • 设置限流规则

    • GatewayFlowRule("pay_routh1"): 创建一个名为 "pay_routh1" 的限流规则,限定该路由每秒最多允许 2 个请求。
    • setCount(2).setIntervalSec(1): 设置请求频率为每秒最多 2 次请求。
    • GatewayRuleManager.loadRules(rules): 将规则加载到 Sentinel 中。
  • 设置限流后的处理逻辑

    • BlockRequestHandler:这是 Sentinel 在流控规则触发时执行的回调方法。当请求触发限流时,handleRequest 方法会被调用。
    • handleRequest():如果流量被控制(例如请求频率过高),返回一个 HttpStatus.TOO_MANY_REQUESTS(HTTP 429)错误,并包含一个 JSON 格式的错误消息,通知客户端请求频繁。

7. 核心流程概述

  1. 请求到达 Gateway:客户端发送请求到 Spring Cloud Gateway。
  2. SentinelGatewayFilter 处理请求:请求进入 SentinelGatewayFilter,Sentinel 会根据定义的流量控制规则判断请求是否需要限流。
  3. 流量超限:如果请求超过了流量限制(例如每秒 2 次),则触发限流。
  4. 触发 BlockRequestHandler:当流控规则触发时,BlockRequestHandler 被调用,返回 429 错误和错误消息,告知客户端请求过于频繁。

8. 作用与总结

  • 流量控制:这段代码利用 Sentinel 和 Spring Cloud Gateway 实现了对请求的流量控制,防止系统被过高的请求负载压垮。
  • 限流响应:当请求被限流时,定义了自定义的错误响应,确保客户端能够收到清晰的错误信息。
  • 全局配置:通过 GlobalFilterSentinelGatewayBlockExceptionHandler,全局管理了 Sentinel 的限流规则和错误处理逻辑。

总体来说,这段代码配置了 Spring Cloud GatewaySentinel 的结合,处理请求的限流和熔断,并定义了当流控规则被触发时返回的错误响应。

注:文章可能有不完整,或有误的地方,如有问题还请评论区斧正。 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词