springcloud04——网关gateway、熔断器 sentinel

目录

[注册中心 nacos | eurekaServer |zookeeper(dubbo)](#注册中心 nacos | eurekaServer |zookeeper(dubbo))

[配置中心 nacos | config Server](#配置中心 nacos | config Server)

[远程服务调用 httpClient | RestTemplate | OpenFeign](#远程服务调用 httpClient | RestTemplate | OpenFeign)

[负载均衡服务 ribbon | loadbalancer](#负载均衡服务 ribbon | loadbalancer)

[网关 zuul | gateway](#网关 zuul | gateway)

[熔断器 hystrix | sentinel](#熔断器 hystrix | sentinel)

网关

sentinel

流控

压测工具

1、作用

2、熔断

3、降级

配置启动sentinel

注册微服务到sentinel

测试流控

降级测试

流控模式详解

[Sentinel 流控效果详解](#Sentinel 流控效果详解)

[hystrix 熔断器](#hystrix 熔断器)


注册中心 nacos | eurekaServer |zookeeper(dubbo)

配置中心 nacos | config Server

远程服务调用 httpClient | RestTemplate | OpenFeign

负载均衡服务 ribbon | loadbalancer

网关 zuul | gateway

熔断器 hystrix | sentinel

网关

1、统一项目入口 不需要关注每一个微服务的ip和端口,客户端只需要网关的ip和端口

2、路由功能 转发请求到达目标服务

网关的配置文件,通过路由鉴权(断言匹配,路由地址匹配,路径匹配),满足规则,转发请求到目标服务

复制代码
- id: provider
#          uri: http://localhost:8080/  #静态路由
          uri: lb://provider    #动态路由
          predicates:   #断言匹配
            - Path=/pro/**
          filters:
            - RewritePath=/pro/(?<segment>.*), /p/$\{segment}
#            - StripPrefix=1  #删除前缀路径  删除一层
#            - PrefixPath=/p
            - AddRequestParameter=name,zhangsan

3、过滤无效请求,减少对目标服务器的压力,可以同时起到安全性作用

4、负载均衡服务器 负载均衡算法(轮询、随机) nginx(反向代理和负载均衡服务器)

5、局部过滤器

修改请求路径 StripPrefix=1 删除一层路径

  • RewritePath=/pro/(?<segment>.*), /p/${segment} 重写路径

添加请求头 AddRequestHeader

添加请求参数 AddRequestparameter=key,value

6、全局过滤器

复制代码
package com.hl.filter;
​
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
​
/*
全局过滤器
 */
@Component
public class GlobalGatewayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("filter.........");
        //放行,继续到达下一个过滤器
        return chain.filter(exchange);
    }
    //数字越小,执行越往前
    @Override
    public int getOrder() {
        return 0;
    }
}
  • GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。

  • Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。

sentinel

限流、降级

资源Sentinel中的核心概念之一。我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。最常用的资源是我们代码中的Java方法。Sentinel提供了@SentinelResource注解用于定义资源,并提供了AspectJ的扩展用于自动定义资源、处理BlockException等。

流控

  • QPS(每秒请求数量):当调用该api的QPS达到阈值的时候,进行限流

  • 线程数:当调用该api的线程数达到阈值的时候,进行限流

压测工具

压力测试工具,jmeter

1、作用

  • 为什么要使用熔断和降级

在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,比如超时、异常等,需要保证在一个依赖出问题的情况下,不会导致整体服务失败。

2、熔断

暂时中断程序,稍后可继续访问。

3、降级

走降级方案,返回之前指定的失败给用户。(柔性失败)

避免服务整体崩溃,系统宕机。让当前方法失败,返回失败响应给调用者。

配置启动sentinel

1、下载安装包 https://github.com/alibaba/Sentinel/releases

2、启动(win+r cmd)

复制代码
java  -Dserver.port=8718  -jar 安装包路径/安装包名称
​
 
java  -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:\IDEA2024\sentinel-dashboard-1.8.0.jar

默认用户名:sentinel

密码: sentinel

注册微服务到sentinel

配置文件:

复制代码
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=localhost:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
# spring.cloud.nacos.config.namespace=
spring.config.import=nacos:product.yml?refresh=true
​
​
​
# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
spring.application.name=product
​
​
​
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=public
​
​
# 应用服务 WEB 访问端口
server.port=8088
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8718
# 取消Sentinel控制台懒加载
# 默认情况下 Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包
# 配置 sentinel.eager=true 时,取消Sentinel控制台懒加载功能
spring.cloud.sentinel.eager=true
# 如果有多套网络,又无法正确获取本机IP,则需要使用下面的参数设置当前机器可被外部访问的IP地址,供admin控制台使用
# spring.cloud.sentinel.transport.client-ip=

测试流控

复制代码
@RestController
@RequestMapping("/demo")
public class DemoController {
​
    @Autowired
    private DemoService demoService;
​
    @GetMapping("/bonjour/{name}")
    public String apiSayHelloLocal(@PathVariable String name) throws Exception {
        for(int i = 1;i<10;i++){
            String s1 = demoService.bonjour(name);
            System.out.println(s1);
        }
        return ff;
    }

@Service
public class DemoService {
    @SentinelResource(value = "DemoService#bonjour",
            defaultFallback = "bonjourFallback")
    public String bonjour(String name) throws Exception {
        return "Bonjour, " + name;
    }
​
    public String bonjourFallback(Throwable t) {
        if (BlockException.isBlockException(t)) {
            return "Blocked by Sentinel: " + t.getClass().getSimpleName();
        }
        return "Oops, failed: " + t.getClass().getCanonicalName();
    }
}

降级测试

java 复制代码
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
​
package com.hl.product.demos.sentinel;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
​
/**
 * @author Eric Zhao
 */
@RestController
@RequestMapping("/demo")
public class DemoController {
​
    @Autowired
    private DemoService demoService;
​
    @GetMapping("/bonjour/{name}")
    public String apiSayHelloLocal(@PathVariable String name) throws Exception {
        boolean flag = true;
        String s0 = demoService.bonjour(name,flag);
        System.out.println(s0);
​
        flag = false;
        for(int i = 1;i<10;i++){
            String s1 = demoService.bonjour(name,flag);
            System.out.println(s1);
        }
        System.out.println("---------------");
        flag = true;
        String ff = demoService.bonjour(name,flag);
        System.out.println(ff);
​
        return ff;
    }
​
​
}
java 复制代码
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
​
package com.hl.product.demos.sentinel;
​
import org.springframework.stereotype.Service;
​
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
​
/**
 * @author Eric Zhao
 */
@Service
public class DemoService {
    @SentinelResource(value = "DemoService#bonjour",
            defaultFallback = "bonjourFallback")
    public String bonjour(String name,Boolean flag) throws Exception {
        if(flag == false){
            throw new Exception("异常。。。。。。");
        }
        return "Bonjour, " + name;
    }
​
    public String bonjourFallback(Throwable t) {
        if (BlockException.isBlockException(t)) {
            return "Blocked by Sentinel: " + t.getClass().getSimpleName();
        }
        return "Oops, failed: " + t.getClass().getCanonicalName();
    }
}
java 复制代码
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hl.product.demos.sentinel;

import java.io.PrintWriter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;

/**
 * @author Eric Zhao
 */
@Configuration
public class SentinelWebConfig {

    @Bean
    public BlockExceptionHandler sentinelBlockExceptionHandler() {
        return (request, response, e) -> {
            // 429 Too Many Requests
            response.setStatus(429);

            PrintWriter out = response.getWriter();
            out.print("Oops, blocked by Sentinel: " + e.getClass().getSimpleName());
            out.flush();
            out.close();
        };
    }
}

流控模式详解

  1. 直接模式

    • 概念:直接模式是最基本的流控模式。它是对当前资源(接口或方法)本身的请求进行流量控制。当请求到达被保护的资源时,Sentinel 会直接根据设置的规则(如 QPS 阈值、并发线程数阈值等)来判断是否允许该请求通过。

    • 示例 :假设有一个用户登录接口/login,设置其 QPS(每秒查询率)的直接流控阈值为 100。这意味着当每秒请求该/login接口的次数超过 100 时,Sentinel 就会开始进行流量控制,可能会对超出的请求进行限流(如直接拒绝、排队等待等处理方式)。

    • 应用场景:适用于对单一资源的流量进行简单直接的控制,比如限制某个核心 API 接口的访问频率,以防止该接口被过度调用而导致系统崩溃或性能下降。

  2. 关联模式

    • 概念:关联模式是一种相对复杂的流控方式。它主要用于当两个资源之间存在关联关系时,通过对其中一个资源的流量控制来间接控制另一个资源的流量。当关联的资源 A 达到流控阈值时,就会对目标资源 B 进行流量控制。

    • 示例 :考虑一个电商系统,有一个商品详情接口/product/detail和一个购买接口/product/buy。这两个接口是关联的,因为用户在查看商品详情后可能会进行购买。如果设置/product/detail接口与/product/buy接口为关联模式,并且当/product/detail的 QPS 达到某个阈值(如 50)时,开始对/product/buy接口进行流量控制,比如限制/product/buy接口的 QPS 为 30。这样可以防止在商品详情页被大量访问时,购买接口被过度请求而导致库存系统等后端服务压力过大。

    • 应用场景:常用于存在先后调用关系或者关联关系的资源之间,例如在一个业务流程中,前一个步骤的操作频繁可能会导致后一个步骤的服务压力过大,通过关联模式可以提前控制后一个步骤的流量。

  3. 链路模式

    • 概念:链路模式主要是从调用链路的角度进行流量控制。它会根据请求的调用链路来判断是否进行流量控制。在微服务架构或者复杂的分布式系统中,一个请求可能会经过多个服务和方法的调用链路。Sentinel 链路模式可以针对特定的调用链路进行流控,而不是简单地基于资源本身。

    • 示例 :假设有一个分布式系统,包括服务 A、服务 B 和服务 C。服务 A 调用服务 B,服务 B 又调用服务 C。在服务 B 中有一个方法methodB,在链路模式下,可以针对从服务 A - 服务 B - 服务 C 这个特定链路中对methodB进行流量控制。如果在其他链路中也调用了methodB,只要不是这个特定的链路,就不受这个链路模式下的流控规则限制。

    • 应用场景:特别适用于微服务架构和复杂的分布式系统,能够精确地对特定的调用链路进行流量管理,避免因为某个链路的流量过大而影响整个系统的稳定性,同时又不会影响其他链路对相同资源的正常调用。

Sentinel 流控效果详解

Sentinel 流控效果主要有快速失败、Warm Up 和排队等待三种,它们的区别如下:

  1. 快速失败(Fail Fast)

    • 概念

      • 当请求流量超过设定的阈值时,直接拒绝超出的请求。这种方式能够快速地对超出流量进行限制,以保护后端服务。
    • 示例

      • 假设对一个 API 接口设置的 QPS(每秒查询率)阈值为 100,当每秒请求数达到 101 时,第 101 个及之后的请求会立即被拒绝,并返回相应的限流错误信息,如 HTTP 状态码为 429(Too Many Requests)。
    • 应用场景

      • 适用于对系统资源消耗较大,且对请求的实时性要求不是特别高的接口。例如,一些批量数据处理接口,当流量过载时,直接拒绝新请求可以避免系统因过度负载而崩溃。同时,对于一些非关键业务的接口,快速失败可以简单有效地控制流量,确保核心业务的稳定运行。
  2. Warm Up(预热)

    • 概念

      • 预热模式是一种渐进式的流量控制方式。它会根据设定的预热时长和阈值,在系统启动或者流量突然增加时,缓慢地增加允许通过的流量,直到达到设定的最大阈值。这样可以避免系统在冷启动或者流量突发时,因为瞬间的高负载而出现性能问题。
    • 示例

      • 假设设置一个接口的 QPS 阈值为 100,预热时长为 5 分钟。系统启动时,开始允许通过的 QPS 可能只有 20,然后随着时间逐渐增加,在 5 分钟后达到 100。如果在预热期间流量就超过了当前允许的阈值,超出部分会被拒绝。
    • 应用场景

      • 常用于系统冷启动后需要逐步加载资源(如缓存预热、数据库连接池初始化等)的场景。同时,对于一些具有性能瓶颈,需要一定时间来适应高流量的服务,如数据库密集型的接口或者计算资源消耗大的算法接口,Warm Up 模式可以让系统有一个缓冲阶段,平稳地过渡到高流量状态。
  3. 排队等待(Rate Limiter)

    • 概念

      • 当请求流量超过阈值时,不是直接拒绝请求,而是让请求进行排队等待。Sentinel 会按照请求的到达顺序,将超出阈值部分的请求放入队列中,当系统有能力处理新请求时,再从队列中取出请求进行处理。这样可以保证请求在一定程度上的公平性,避免大量请求被直接拒绝。
    • 示例

      • 设一个接口的 QPS 阈值为 100,队列长度为 200。当每秒请求数达到 120 时,其中 20 个请求会被放入队列中排队等待。如果系统处理速度能够跟上,这些排队的请求会在后续得到处理。
    • 应用场景

      • 适用于对请求响应时间要求相对不那么严格,且希望尽可能处理所有请求的场景。比如,对于一些异步任务处理的接口,或者消息队列消费者接口,排队等待可以确保请求不会因为瞬间流量高峰而丢失,同时可以在一定程度上平滑流量,提高系统整体的资源利用率。

hystrix 熔断器

熔断和降级

熔断(目标服务不让访问,暂时中断)

降级(目标资源服务访问时,走降级方法,备份方法,返回特定信息给调用者,避免无限制等待)

熔断器 有三个状态: 打开 半开 关闭

相关推荐
wno7045 小时前
Spring Cloud Hystrix Dashboard仪表盘
spring·spring cloud·hystrix
BUG指挥官8 小时前
Redis已接入AI
数据库·人工智能·spring boot·redis·spring cloud
wno70419 小时前
Spring Cloud Hystrix服务容错
spring·spring cloud·hystrix
苏渡苇1 天前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
java·后端·spring·spring cloud·springboot·性能监控
YOU OU2 天前
Spring Cloud Consul
spring cloud·consul·java-consul
重生之我是Java开发战士2 天前
【Spring Cloud】Eureka服务注册发现与LoadBalancer负载均衡
spring cloud·eureka·负载均衡
谢亮_vipxieliang2 天前
ValidX vs Google Guava Preconditions:验证 vs 断言
java·spring boot·后端·spring cloud·hibernate·guava
夏天拐跑了西瓜3 天前
Spring Cloud 微服务实战(八):Hystrix熔断降级——从服务雪崩到断路器模式
spring cloud·hystrix·微服务
重生之我是Java开发战士4 天前
【Spring Cloud】认识微服务与工程搭建
spring·spring cloud·微服务
墨着染霜华5 天前
SpringCloud Gateway线上Nginx代理后自定义下划线请求头丢失(app_name/app_version获取不到)完美解决
nginx·spring cloud·gateway