五 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工程中加入如下依赖
```xml2.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服务熔断与限流(五服务熔断)
五分钟带你玩转spring cloud alibaba越玩越溜!实战Spring Cloud Alibaba Sentinel