从浅入深 学习 SpringCloud 微服务架构(十三)SCG 网关中使用 sentinel 限流

一、SCG 网关中使用 sentinel 限流:入门案例

1、基于 Sentinel 的限流:

1) Sentinel 支持对 Spring Cloud Gateway, Zuul 等主流的 API Gateway 进行限流。
2) 从 Sentinel-1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

  • route 维度 : 即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeld
  • 自定义 API 维度 : 用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

3)Sentinel1.6.0 引入了 Sentinel APl Gateway Adapter Common 模块,此模块中包含网关限流的规则
和自定义 API的实体和管理逻辑:

  • GatewayF1owu1e : 网关限流规则,针对 APl Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
  • ApiDefinition : 用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 AP| 叫 my_api,请求 path 模式为 /foo/**和 /baz/**的都归到 my_api 这个 API 分组下面。限流的时候可以针对这个自定义的 API分组维度进行限流。

2、SCG 网关中使用 sentinel 限流:入门案例:环境搭建。

2.1 在子工程(子模块) api_gateway_service 的 pom.xml 中导入 Sentinel 限流 依赖坐标。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring_cloud_demo</artifactId>
        <groupId>djh.it</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>api_gateway_service</artifactId>

    <dependencies>
        <!-- springcloudgateway 的内部是通过 netty + webflux 实现。
            webflux 实现和 springmvc 存在冲突,需要注销掉父工程中的 web 依赖,在各子模块中导入 web 依赖。
          -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- 引入 EurekaClient 依赖坐标 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 配置 SCG 网关 filter 限流 依赖坐标:redis 监控依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 配置 SCG 网关 filter 限流 依赖坐标:redis 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <!-- sentinel 网关限流 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
            <version>1.6.3</version>
        </dependency>
    </dependencies>
</project>
<!-- spring_cloud_demo\api_gateway_service\pom.xml -->
2.2、在子工程 api_gateway_service(子模块)中,创建 Sentinel 限流 配置类 GatewayConfiguration.java
/**
 *   spring_cloud_demo\api_gateway_service\src\main\java\djh\it\gateway\GatewayConfiguration.java
 *
 *   2024-5-8 创建 Sentinel 限流 配置类 GatewayConfiguration.java
 */

package djh.it.gateway;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import javax.annotation.PostConstruct;
import java.util.*;

@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;
    }

    //配置限流的异常处理器:SentinelGatewayBlockExceptionHandler
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //配置限流过滤器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数,用于指定资源的限流规则:1)资源名称(路由id),2)配置统计时间,3)配置限流阈值。
    @PostConstruct
    public void initGatewayRules(){
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("product-service").setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }
}

2.3、在子工程 api_gateway_service(子模块)中,修改 application.yml 配置文件,
##  spring_cloud_demo\api_gateway_service\src\main\resources\application.yml

server:
  port: 8088  # 启动端口 命令行注入。
spring:
  application:
    name: api-gateway-service  #spring应用名, # 注意 FeignClient 不支持名字带下划线
  redis:  # 引入 redis
    host: localhost
    pool: 6379
    database: 0
  # 配置 SpringCloudGateway 的路由
  cloud:
    gateway:
      routes:  # 配置路由,路由Id,路由到微服务的 uri, 断言(判断条件)
        - id: product-service   # 保持唯一
          uri: lb://service-product  # lb://  根据微服务名称从注册中心拉取服务请求路径。
          predicates:   # 断言(判断条件)设置
            - Path=/product-service/**  # 将当前请求转发到 http://127.0.0.1/product/1
          filters:  # 配置路由过滤器 http://localhost:8088/product-service/product/1  --> http://127.0.0.1:9001/product/1
            - RewritePath=/product-service/(?<segment>.*), /$\{segment}  # 路径重写的过滤器。
eureka:  # 配置 Eureka
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
    instance:
      prefer-ip-address: true  # 使用ip地址注册。

3、重新启动 父工程 spring_cloud_demo 下 全部子项目(eureka,product,order,gateway)的启动类,进行测试:

1)浏览器地址栏输入(正常访问):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

2)浏览器地址栏输入(快速多刷新几次,发现不能正常访问):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

二、SCG 网关中使用 sentinel 限流:限流异常提示

1、SCG 网关中使用 sentinel 限流,自定义异常提示

当触发限流后页面显示的是 Blocked bySentinel: FlowException。为了展示更加友好的限流提示 Sentinel 支持自定义异常处理。

可以在 Gatewayca11backmanager 注册回调进行定制:

setB1ockHandler : 注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 B1ockRequestHandler。

默认实现为 Defau1tBlockRequestHandler 当被限流时会返回类似于下面的错误信息 : B1ocked by sentine1:FlowException 。

2、在子工程 api_gateway_service(子模块)中,修改 Sentinel 限流 配置类 GatewayConfiguration.java 添加 自定义限流 处理器方法。

/**
 *   spring_cloud_demo\api_gateway_service\src\main\java\djh\it\gateway\GatewayConfiguration.java
 *
 *   2024-5-8 创建 Sentinel 限流 配置类 GatewayConfiguration.java
 */

package djh.it.gateway;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

@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;
    }

    //配置限流的异常处理器:SentinelGatewayBlockExceptionHandler
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //配置限流过滤器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数,用于指定资源的限流规则:1)资源名称(路由id),2)配置统计时间,3)配置限流阈值。
    @PostConstruct
    public void initGatewayRules(){
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("product-service").setCount(1).setIntervalSec(1));
//        rules.add(new GatewayFlowRule("order_api").setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }

    // 自定义限流 处理器方法
    @PostConstruct
    public void initBlockHandlers(){
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map = new HashMap<>();
                map.put("code",001);
                map.put("message", "对不起,接口限流了");
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .body(BodyInserters.fromObject(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

//    @PostConstruct
//    private void initCustomizedApis(){
//        Set<ApiDefinition> definitions = new HashSet<>();
//        ApiDefinition api1 = new ApiDefinition("product_api")
//                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
//            add(new ApiPathPredicateItem().setPattern("/product-service/product/**")
//                    .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
//                 }});
//        ApiDefinition api2 = new ApiDefinition("order_api")
//                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
//                    add(new ApiPathPredicateItem().setPattern("/order-service/order"));
//                }});
//        definitions.add(api1);
//        definitions.add(api2);
//        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
//    }
}

3、重新启动 父工程 spring_cloud_demo 下 全部子项目(eureka,product,order,gateway)的启动类,进行测试:

1)浏览器地址栏输入(正常访问):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

2)浏览器地址栏输入(快速多刷新几次,不能正常访问,异常页面是我们自定义的方法):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

三、SCG 网关中使用 sentinel 限流:自定义分组限流

1、在子工程 api_gateway_service(子模块)中,修改 Sentinel 限流 配置类 GatewayConfiguration.java 添加 自定义 API 限流分组方法。

/**
 *   spring_cloud_demo\api_gateway_service\src\main\java\djh\it\gateway\GatewayConfiguration.java
 *
 *   2024-5-8 创建 Sentinel 限流 配置类 GatewayConfiguration.java
 */

package djh.it.gateway;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

@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;
    }

    //配置限流的异常处理器:SentinelGatewayBlockExceptionHandler
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    //配置限流过滤器
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }

    //配置初始化的限流参数,用于指定资源的限流规则:1)资源名称(路由id),2)配置统计时间,3)配置限流阈值。
    @PostConstruct
    public void initGatewayRules(){
        Set<GatewayFlowRule> rules = new HashSet<>();
//        rules.add(new GatewayFlowRule("product-service")
//                .setCount(1)
//                .setIntervalSec(1));
        rules.add(new GatewayFlowRule("product-api")
                .setCount(1).setIntervalSec(1));
        rules.add(new GatewayFlowRule("order_api")
                .setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }

    // 自定义限流 处理器方法
    @PostConstruct
    public void initBlockHandlers(){
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map map = new HashMap<>();
                map.put("code",001);
                map.put("message", "对不起,接口限流了");
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .body(BodyInserters.fromObject(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }

    //自定义API限流分组方法:1)定义分组,2)对小组配置限流规则。
    @PostConstruct
    private void initCustomizedApis(){
        Set<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition api1 = new ApiDefinition("product-api")
                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
            add(new ApiPathPredicateItem().setPattern("/product-service/product/**")  // 以 /product-service/product/ 开头的所有 url
                    .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
                 }});
        ApiDefinition api2 = new ApiDefinition("order_api")
                .setPredicateItems(new HashSet<ApiPredicateItem>(){{
                    add(new ApiPathPredicateItem().setPattern("/order-service/order"));  // 完成匹配 /order-service/order
                }});
        definitions.add(api1);
        definitions.add(api2);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }
}


2、重新启动 父工程 spring_cloud_demo 下 全部子项目(eureka,product,order,gateway)的启动类,进行测试:

1)浏览器地址栏输入(正常访问):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

2)浏览器地址栏输入(快速多刷新几次,不能正常访问,返回异常页面是我们自定义的方法):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

四、SCG 网关高可用:概述

1、网关高可用

高可用 HA(High Availability) 是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。

我们都知道,单点是系统高可用的大敌,单点往往是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。

方法论上,高可用保证的原则是“集群化”,或者叫“冗余”:只有一个单点,挂了服务会受影响;如果有冗余备份,挂了还有其他 backup 能够顶上。

2、我们实际使用 Spring Cloud Gateway 的方式如下图:

在这里插入图片描述

3、不同的客户端使用不同的负载将请求分发到后端的 Gateway,Gateway 再通过 HTTP 调用后端服务,最后对外输出。因此为了保证 Gateway 的高可用性,前端可以同时启动多个 Gateway 实例进行负载,在 Gateway 的前端使用 Nginx 或者 F5 进行负载转发以达到高可用性。

五、SCG 网关高可用:ngnix 结合网关集群构造高可用网关

1、在 idea 的 Run Dashboard 面板上,复制一个 GatewayServerApplication 网关服务,重命名为:GatewayServerApplication(2) 并在 application.yml 配置文件修改端口号为:8089

在这里插入图片描述

如果找不到 idea 的 Run Dashboard 面板上,请查看:
# IDEA2019 如何打开 Run Dashboard 运行仪表面板

2、重新启动 父工程 spring_cloud_demo 下 全部子项目(eureka,product,order,gateway,gateway2)的启动类,进行测试:

1)浏览器地址栏输入(正常访问):
http://localhost:8088/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

2)浏览器地址栏输入(也可以正常访问):
http://localhost:8089/product-service/product/1 就转发到 http://127.0.0.1:9001/product/1

在这里插入图片描述

3、安装一个 Nginx,并在安装目录下的 conf 目录下,找到配置文件 nginx.conf 打开并编辑它。

在这里插入图片描述

# D:\Program Files\nginx-1.8.1\conf\nginx.conf


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
	
	# 集群配置
	upstream gateway {
		server 127.0.0.1:8088;
		server 127.0.0.1:8089;
	}

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        #location / {
        #   root   html;
        #    index  index.html index.htm;
        #}
		
		# 当请求到 127.0.0.1 就转发到 gateway
		location  / {
			proxy_pass http://gateway;
		}
		
		# 路由到订单服务
		#location  /api-product {
		#	proxy_pass http://127.0.0.1:9001/;
		#}
		
		
		
		# 路由到商品服务
		#location  /api-order {
		#	proxy_pass http://127.0.0.1:9002/;
		#}
		
		

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

在这里插入图片描述

4、启动 Nginx 服务,并重新启动 父工程 spring_cloud_demo 下 全部子项目(eureka,product,order,gateway,gateway2)的启动类,进行测试:

浏览器地址栏输入(也能正常访问):
http://localhost/product-service/product/1

在这里插入图片描述

就相当于访问转发到

http://localhost:8088/product-service/product/1
http://localhost:8089/product-service/product/1

5、如果在 idea 的 Run Dashboard 面板上,停掉一个 GatewayServerApplication 如:8088

在这里插入图片描述

浏览器地址栏输入(也能正常访问):
http://localhost/product-service/product/1

在这里插入图片描述

但是,http://localhost:8088/product-service/product/1 就不能正常访问了。

在这里插入图片描述

上一节关联链接请点击:
# 从浅入深 学习 SpringCloud 微服务架构(十二)网关限流算法和 SCG 网关 filter 限流。

GitHub 加速计划 / sentine / Sentinel
22.24 K
7.98 K
下载
alibaba/Sentinel: Sentinel 是阿里巴巴开源的一款面向分布式服务架构的流量控制、熔断降级组件,提供实时监控、限流、降级和系统保护功能,适用于微服务治理场景。
最近提交(Master分支:3 个月前 )
195150bc * fix issue 2485 which occur oom when using async servlet request. * optimize imports * 1. fix the same issue in the webmvc-v6x 2. improve based on review comments 2 个月前
b78b09d3 2 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐