五 sentinel 集成 gateway

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五 sentinel 集成 gateway相关的知识,希望对你有一定的参考价值。

参考技术A 参考文档:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

在 第四章  的 gateway、 nacosa 的基础上,完成两者的适配。

(1)gateway pom.xml文件

(2) gateway 新建 GatewayConfiguration 类

GatewayConfiguration 

(3)在GatewayConfiguration 中配置限流控制

流量控制

(4)连接 控制台

gateway

(5)至于 -Dcsp.sentinel.app.type=1 ,在gateway 项目 启动的时候 需要加上去。用于标记 使用gateway 进行 网关控制。

(6)nacosa  新加pom.xml依赖

nacosa  pom

(7)nacosa  新加properties配置

nacosa  properties

(8)在 nacosa 项目 新加 TestNacosaController,helloWorld 加上 注解SentinelResource

TestNacosaController

(11)分别启动 nacosa 和gateway,在sentinel 控制台 看到

sentinel 控制台

nacos 服务台 看到

nacos 服务台

(11)访问 http://localhost:9000/nacosa/test/helloWorld 看到

访问

再 http://localhost:9000/nacosa/test/helloWorld2 也出现这个

说明,在gateway 中配置,限流是对 整个 nacosa 生效的

(12)在刚刚的controller 里面,给 helloWorld 方法加了 @SentinelResource 注解,在 sentinel 控制台 nacosa 项目 里加入流程控

sentinel 

(13)再次访问 http://localhost:9000/nacosa/test/helloWorld 出现这个,说明 整个项目的流控与单个流控 是相互生效的

request

项目地址: https://github.com/renzheyizhe/demo (nacosa、gateway)

sentinel实战:springcloud gateway整合 sentinel nacos

前言:

Sentinel: 分布式系统的流量防卫兵,是阿里中间件团队2018年7月开源的,面向分布式服务架构的轻量级流量控制产品,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护系统服务的稳定性

Sentinel 具有以下特征:

丰富的应用场景:秒杀限流,消息削峰填谷、集群流量控制、实时熔断下游不可用应用等

完备的实时监控:Sentinel 同时提供实时的监控功能。可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况

广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、 Dubbo、gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等

Sentinel 分为两个部分:

控制台(Dashboard) 基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器

核心库(Java 客户端) 不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持

控制台特性

  • 实时监控
    支持自动发现集群机器列表、服务健康状态、服务调用通过/拒绝QPS、调用耗时、图表统计

  • 规则管理及推送
    支持在界面配置流控、降级、热点规则,并实时推送

  • 鉴权
    控制台支持自定义鉴权接口,提供基本登录功能

一、整合步骤

1.引入依赖;

在自己原来的springcloud gate工程中加入如下依赖

```xml
com.alibaba.csp sentinel-spring-cloud-gateway-adapter ${alibaba.sentinel.version} com.alibaba.cloud spring-cloud-starter-alibaba-sentinel 2.1.0.RELEASE com.alibaba.csp sentinel-datasource-nacos ${alibaba.sentinel.version} ```

2.bootstarp.yml 配置文件

server:
  port: 80
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080 #sentinel控制台访问路径
        port: 8080
      eager: true #心跳启动
      datasource:
        ds:
          nacos:
            server-addr: 118.31.123.11:8848
            dataId: gateway.json
            groupId: DEFAULT_GROUP
            rule-type: flow
    gateway:
      discovery:
        locator:
          enabled: true
    loadbalancer:
      retry:
        enabled: true

Spring-Cloud-Gateway之Route初始化加载我就不细说。可以直接加配置如下:(我这里没有用)

spring:
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          lower-case-service-id: true
      routes:
        # Add your routes here.
        - id: aliyun_route
          uri: https://www.aliyun.com/
          predicates:
            - Path=/product/**
        - id: httpbin_route
          uri: https://httpbin.org
          predicates:
            - Path=/httpbin/**
          filters:
            - RewritePath=/httpbin/(?<segment>.*), /$\\{segment}
        #认证服务路由
        - id: auth-service
          predicates:
            - Path=/auth-service/**
          uri: lb://spring-cloud-nacos-auth-service
          filters:
            - StripPrefix=1
    sentinel:
      datasource.ds2.file:
        file: "classpath: gateway.json"
        ruleType: gw-flow
      datasource.ds1.file:
        file: "classpath: api.json"
        ruleType: gw-api-group
    nacos:
      discovery:
        server-addr: 192.168.10.200:8848

3.sentinel启动配置类添加,和限流后异常处理

 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 lombok.extern.slf4j.Slf4j;
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 reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
@Slf4j
@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;
    }
    /**
     * 配置 限流后异常处理  JsonSentinelGatewayBlockExceptionHandler重写 SentinelGatewayBlockExceptionHandler
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public JsonSentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new JsonSentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
 
    /**
     * 配置SentinelGatewayFilter
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }
 
}

JsonSentinelGatewayBlockExceptionHandler:

import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.util.function.Supplier;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lxtx.gateway.provider.ResponseProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
 
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@Component
public class JsonSentinelGatewayBlockExceptionHandler implements  WebExceptionHandler{
    @Autowired
    private ObjectMapper objectMapper;
    private List<ViewResolver> viewResolvers;
    private List<HttpMessageWriter<?>> messageWriters;
    private final Supplier<ServerResponse.Context> contextSupplier = () -> {
        return new ServerResponse.Context() {
            public List<HttpMessageWriter<?>> messageWriters() {
                return JsonSentinelGatewayBlockExceptionHandler.this.messageWriters;
            }
 
            public List<ViewResolver> viewResolvers() {
                return JsonSentinelGatewayBlockExceptionHandler.this.viewResolvers;
            }
        };
    };
 
    public JsonSentinelGatewayBlockExceptionHandler(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolvers;
        this.messageWriters = serverCodecConfigurer.getWriters();
    }
 
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (exchange.getResponse().isCommitted()) {
            return Mono.error(ex);
        } else {
            return !BlockException.isBlockException(ex) ? Mono.error(ex) : this.handleBlockedRequest(exchange, ex).flatMap((response) -> {
                return this.writeResponse(response, exchange);
            });
        }
    }
 
    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }
    /** 只需要修改此方法 */
    public Mono<Void> writeResponse(ServerResponse serverWebExchange, ServerWebExchange exchange) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        return unAuth(serverHttpResponse, "访问的人太多了,请稍后再试!");
    }
    private Mono<Void> unAuth(ServerHttpResponse resp, String msg) {
        resp.setStatusCode(HttpStatus.FORBIDDEN);
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        String result = "";
        try {
            result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
        } catch (JsonProcessingException e) {
            log.error(e.getMessage(), e);
        }
        DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Flux.just(buffer));
    }
}

4.在nacos中添加 gateway.json 配置文件

 

5.下载 sentinel 控制台jar 并启动  我下载的是:sentinel-dashboard-1.7.2.jar

云盘:https://pan.baidu.com/s/1nxhH4NDLc5xw9lHeLQzIew   提取码:y11w

启动命令:java  -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dproject.name=sentinel -jar sentinel-dashboard-1.7.2.jar

启动后台 访问:http://127.0.0.1:8080  sentine控制台 密码账号都是:sentinel

6.启动 nacos 和数据库等基础服务后  启动你的 服务提供者和 网关工程 ,然后刷新你的sentinel控制台,你会看到左侧多了一个

 点击流控规则,看nacos配置的规则是否引入到 sentinel中。如果没有请自行检查

然后调用:这个流控规则的接口:如何能正常调用了,再刷新控制台 点击--簇点链路  看资源名中是否有刚刚调用的接口

最后将 流控规则中的 阈值改为0

再次访问该资源接口; 

如果限流成功。说明整合成功!

二、整合--网关流控控制台

1.执行启动命令是时,添加

# 注:通过 Spring Cloud Alibaba Sentinel 自动接入的 API Gateway 整合则无需此参数
-Dcsp.sentinel.app.type=1

如:java -Dcsp.sentinel.app.type=1 -jar -Xmx512m -Xms512m lxtx-uc.jar

本来是想在bootstarp.yml 配置的 结果试了好久不行,如果知道请务必告知 感谢!
2.手动加载网关流控规则
只需修改

手动加载网关规则 GatewayConfiguration.java

package com.lxtx.gateway.config;
 
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 lombok.extern.slf4j.Slf4j;
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 reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
@Slf4j
@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;
    }
    /**
     * 配置 限流后异常处理  JsonSentinelGatewayBlockExceptionHandler重写 SentinelGatewayBlockExceptionHandler
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public JsonSentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler以上是关于五 sentinel 集成 gateway的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud Alibaba——Sentinel服务熔断与限流(五服务熔断)

SpringCloud Alibaba——Sentinel服务熔断与限流(五服务熔断)

Dubbo集成Sentinel实现限流

zuul集成Sentinel最新的网关流控组件

第三章 Dubbo 集成 Sentinel 设计

五分钟带你玩转spring cloud alibaba越玩越溜!实战Spring Cloud Alibaba Sentinel