sentinel实战:springcloud gateway整合 sentinel nacos
Posted IT管理圈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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实战:springcloud gateway整合 sentinel nacos的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud系列——流量控制组件Sentinel实战
sentinel实战:springcloud gateway整合 sentinel nacos
SpringCloud实战(十八)-Sentinel 熔断策略
SpringCloud实战(十八)-Sentinel 熔断策略