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

从浅入深 学习 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 限流。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【全开源】Java洗衣清洁服务同城清洗服务小程序源码

特色功能&#xff1a; 在线预约与支付&#xff1a;用户可以通过洗衣小程序在线预约洗衣服务&#xff0c;并选择支付方式进行支付&#xff0c;如微信支付、支付宝等。这种在线预约和支付的方式极大地方便了用户&#xff0c;提高了服务的便捷性。智能推荐与选择&#xff1a;根据…

探索C++的string:从基础到深入

文章目录 string类string类的接口string的常见构造string类对象的容量操作string类的遍历及访问操作string类对象的修改操作string类的非成员函数 总结 string类 C中的string类是一个非常重要的字符串处理工具&#xff0c;它提供了一种方便且灵活的方式来处理字符串。它位于标…

Vue3专栏项目 -- 一、第一个页面(下)

一、Dropdown 组件&#xff08;下拉菜单组件&#xff09;编码 1、基本功能&#xff1a;展示出下拉按钮和下拉菜单栏的样式 我们可以通过bootstrap来实现这个下拉框&#xff0c;需要注意它这个只是有样式&#xff0c;是没有行为的 然后这个下拉按钮的文字展示是根据用户名称展…

云推流-让ue/unity内容及3D大型模型内容轻松做到网页使用的解决方案

UE&#xff08;Unreal Engine&#xff09;和Unity作为当下最热门的游戏引擎之一&#xff0c;为开发者提供了强大的工具集和平台支持&#xff0c;使得创建高质量、交互式的3D场景变得越来越容易。 然而&#xff0c;当我们把这种较大的资源分享给其他人时&#xff0c;对方可能需要…

qml拖动交换之Gridview

qml拖动交换之Gridview 坐标变换代码 QML中mapToItem和mapFromItem的使用 坐标变换 代码 import QtQuick 2.6 import QtQuick.Window 2.2Window {visible: truewidth: 1024height: 480title: qsTr("Drag Icon")property ListModel dataModel: ListModel {ListEleme…

摩菲Murphy显示器显示表 总线编程器维修PV780B

Murphy仪器维修包括&#xff1a;摩菲数字显示器&#xff1b;摩菲监视仪表&#xff1b;摩菲CAN总线控制器等维修 维修故障包括&#xff1a;黑屏、指示灯无显示&#xff0c;触摸屏上电无反应&#xff0c; 上电蓝屏、白屏&#xff0c;通电几分钟后屏幕变为蓝屏&#xff0c;主板故…

46. UE5 RPG 增加角色受击反馈

在前面的文章中&#xff0c;我们实现了对敌人的属性的初始化&#xff0c;现在敌人也拥有的自己的属性值&#xff0c;技能击中敌人后&#xff0c;也能够实现血量的减少。 现在还需要的就是在技能击中敌人后&#xff0c;需要敌人进行一些击中反馈&#xff0c;比如敌人被技能击中后…

android基础-多线程

多线程&#xff1a; 创建子线程&#xff0c;子线程不允许直接更新UI&#xff0c;试想下如果多个线程去更新UI&#xff0c;则会造成资源错乱&#xff0c;如果枷锁就会使得代码冗余复杂。 android异步处理&#xff1a; 另一种异步多线程方法 doInBackground是在子线程中。

VisualGDB:Linux动态库项目创建、编译及库的使用

此篇接上篇 《VisualGDB:为Linux项目添加系统依赖库》,在本篇中我们重点分享一下如何基于VisualGDB 在VS中创建Linux动态库项目,如何编译及使用创建的动态库。 一、VisualGDB创建Linux动态库项目 如下,我们创建一个Linux下的动态库项目MyMath 二、编译动态库 我们稍微…

Baidu Comate:智能编码,编程效率的革新者

文章目录 一、何为智能编码助手&#xff1f;二、Baidu Comate智能编码助手简介三、Baidu Comate注册四、Baidu Comate体验Comate插件功能1.注释生成代码2.函数注释生成3.行间注释生成4.生成代码解释5. 调优建议 五、插件功能的使用体验感受和建议 &#x1f6a9;结语 一、何为智…

【Linux】如何定位客户端程序的问题

文章目录 1 客户端程序和服务端程序的差别2 问题类型2.1 崩溃(crash)2.2 CPU高2.3 内存高2.4 线程卡死 3 总结 1 客户端程序和服务端程序的差别 客户端程序是运行在终端上&#xff0c;通常都会与业务系统共存&#xff0c;而服务端程序通常会运行在单独的节点上&#xff0c;或者…

短信群发平台:全功能SDK短信接口解决方案

SDK短信接口介绍&#xff1a; 为了满足不同企业的需求&#xff0c;我们提供了一站式SDK短信接口解决方案。这些接口不仅功能强大&#xff0c;而且易于集成到现有的企业系统中&#xff0c;以提供更加安全、高效和便捷的服务。 1.短信验证码接口&#xff1a;用于用户注册、密码修…

PY计算生态是什么?

Python 的计算生态指的是与 Python 相关的广泛的软件、库、框架和工具集合. 它们为各种计算任务提供了丰富的解决方案和支持。Python 作为一种简洁、易学、功能强大的编程语言&#xff0c;在科学计算、数据分析、人工智能、机器学习等领域都有着强大的影响力。以下是 Python 计…

深度学习之视觉特征提取器——GoogleNet/Inception

GoogleNet GoogleNet在2014年中的ImageNet夺冠&#xff0c;将Inception这一结构推向了热潮。从另外一个角度来看&#xff0c;CV魔改网络结构也从中得到启发或者说推动&#xff0c;拓宽了各种魔改的方式。GoogleNet其实只是Inception这一结构大规模集成后得到的模型&#xff0c…

自建WSUS更新服务器完成内网的安全补丁更新

一、适用场景 1、企业内部网络无法访问外网&#xff0c;所以搭建WSUS服务器&#xff0c;可以让内网环境进行更新补丁。 2、校园内部的电脑实训室一般不用外网资源&#xff0c;偶尔开启外网使用时&#xff0c;电脑实训室集体自动更新占用外网资源量大&#xff0c;所以搭建WSUS服…

云动态摘要 2024-05-08

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 [免费试用]即刻畅享自研SaaS产品 腾讯云 2024-04-25 涵盖办公协同、营销拓客、上云安全保障、数据分析处理等多场景 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器ECS试用产品续用…

JavaEE 初阶篇-深入了解 HTTP 协议

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 HTTP 协议概述 2.0 HTTP 请求协议 2.1 请求方式的具体体现 3.0 HTTP 响应协议 3.1 常见的状态码及描述 3.2 常见的响应头 4.0 HTTP 协议解析 4.1 简单实现服务器响…

Linux/Intuition

Intuition Enumeration nmap 使用 nmap 扫描系统常见端口&#xff0c;发现对外开放了 22 和 80&#xff0c;然后扫描这两个端口的详细信息 ┌──(kali㉿kali)-[~/vegetable/HTB/Intuition] └─$ nmap -sC -sV -p 22,80 -oA nmap 10.10.11.15 Starting Nmap 7.93 ( https:…

Springboot+vue项目影城管理系统

摘 要 本论文主要论述了如何使用JAVA语言开发一个影城管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述影城管理系统的当前背景以及系统开发的目的&…

计算机SCI期刊,IF=9.657,1区TOP,2周内出版!

一、期刊名称 Neural Networks 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;7.8 中科院分区&#xff1a;1区TOP 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$3350 三、期刊简介 神…