Sentinel的gateway规则持久化改造
Sentinel的gateway规则持久化改造每天多学一点点~话不多说,这就开始吧…文章目录Sentinel的gateway规则持久化改造1. 前言2. 源码改造2.1老规矩,去掉sentinel-dashboard 工程的pom中test2.2复制 test下 NacosConfig类并修改2.3新增 pulisher 推送规则 和 provider 拉取规则2.4修改GatewayFlowRu
Sentinel的gateway规则持久化改造
每天多学一点点~
话不多说,这就开始吧…
文章目录
1. 前言
上篇写过 Sentinel规则持久化改造(pull+push+Ahas),但一般springcloud项目都是与zuul,gateway等网关结合使用,今儿总结下 sentinel 与 gateway的持久化改造。
以sentinel 1.7.0 版本 为例 sentinel git地址
2. 源码改造
2.1 老规矩,去掉sentinel-dashboard 工程的pom中test
<!-- 去掉test -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<!-- <scope>test</scope>-->
</dependency>
2.2 复制 test下 NacosConfig类并修改
修改 Converter<List 中的 FlowRuleEntity规则
在上篇基础上,加入网关的API和FlowRule
@Configuration
public class NacosConfig {
/**
* 流控规则
*
* @return
*/
@Bean
public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
return s -> JSON.parseArray(s, FlowRuleEntity.class);
}
/**
* 授权规则
*
* @return
*/
@Bean
public Converter<List<AuthorityRuleEntity>, String> authorRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<AuthorityRuleEntity>> authorRuleEntityDecoder() {
return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
}
/**
* 降级规则
*
* @return
*/
@Bean
public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
return s -> JSON.parseArray(s, DegradeRuleEntity.class);
}
/**
* 热点参数 规则
*
* @return
*/
@Bean
public Converter<List<ParamFlowRuleEntity>, String> paramRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<ParamFlowRuleEntity>> paramRuleEntityDecoder() {
return s -> JSON.parseArray(s, ParamFlowRuleEntity.class);
}
/**
* 系统规则
*
* @return
*/
@Bean
public Converter<List<SystemRuleEntity>, String> systemRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<SystemRuleEntity>> systemRuleEntityDecoder() {
return s -> JSON.parseArray(s, SystemRuleEntity.class);
}
/**
* 网关API
*
* @return
* @throws Exception
*/
@Bean
public Converter<List<ApiDefinitionEntity>, String> apiDefinitionEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<ApiDefinitionEntity>> apiDefinitionEntityDecoder() {
return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
}
/**
* 网关flowRule
*
* @return
* @throws Exception
*/
@Bean
public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
return JSON::toJSONString;
}
@Bean
public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
}
@Bean
public ConfigService nacosConfigService() throws Exception {
return ConfigFactory.createConfigService("47.111.191.111");
}
}
2.3 新增 pulisher 推送规则 和 provider 拉取规则
**GetWayApiNacosProvider 拉取API **
@Component("getWayApiNacosProvider")
public class GetWayApiNacosProvider implements DynamicRuleProvider<List<ApiDefinitionEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<String , List<ApiDefinitionEntity>> converter;
@Override
public List<ApiDefinitionEntity> getRules(String appName) throws Exception {
String rules = configService.getConfig(appName+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX
,NacosConfigUtil.GROUP_ID,3000);
if(StringUtil.isEmpty(rules)){
return new ArrayList<>();
}
return converter.convert(rules);
}
}
GetWayApiNacosPublisher 推送API
@Component("getWayApiNacosPublisher")
public class GetWayApiNacosPublisher implements DynamicRulePublisher<List<ApiDefinitionEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<List<ApiDefinitionEntity>, String> converter;
@Override
public void publish(String app, List<ApiDefinitionEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
configService.publishConfig(app+ NacosConfigUtil.GETWAY_API_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID,converter.convert(rules));
}
}
GateWayFlowRulesNacosProvider 拉取规则
@Component("gateWayFlowRulesNacosProvider")
public class GateWayFlowRulesNacosProvider implements DynamicRuleProvider<List<GatewayFlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<String, List<GatewayFlowRuleEntity>> converter;
@Override
public List<GatewayFlowRuleEntity> getRules(String appName) throws Exception {
String rules = configService.getConfig(appName + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, 3000);
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return converter.convert(rules);
}
}
GateWayFlowRulesNacosPunlisher 推送规则
@Component("gateWayFlowRulesNacosPunlisher")
public class GateWayFlowRulesNacosPunlisher implements DynamicRulePublisher<List<GatewayFlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Autowired
private Converter<List<GatewayFlowRuleEntity>, String> converter;
@Override
public void publish(String app, List<GatewayFlowRuleEntity> rules) throws Exception {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
}
configService.publishConfig(app + NacosConfigUtil.GETWAY_FLOW_DATA_ID_POSTFIX,
NacosConfigUtil.GROUP_ID, converter.convert(rules));
}
}
2.4 修改GatewayFlowRuleController 和 GatewayApiController
- 注入上文我们自己写的 GetWayApiNacosProvider 和 GetWayApiNacosPublisher
//添加我们自己写的ruleProvider
@Autowired
@Qualifier("gateWayFlowRuleNacosProvider")
private DynamicRuleProvider<List<GatewayFlowRuleEntity>> ruleProvider;
//添加我们自己写的 publisher
@Autowired
@Qualifier("gateWayFlowRuleNacosPubisher")
private DynamicRulePublisher<List<GatewayFlowRuleEntity>> rulePublisher;
- 以 @GetMapping("/list.json") 为例,修改代码
// 原生方法 拉取网关微服务
// List<GatewayFlowRuleEntity> rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();
// 现修改 ---> 去配置中心拉取
List<GatewayFlowRuleEntity> rules = ruleProvider.getRules(app);
其他 Mapping 同理
- 新增方法,发布到nacos上
GatewayApiController 类
/**
* api 推送 到 nacos
* @param app
* @throws Exception
*/
private void publishApis(String app) throws Exception {
List<ApiDefinitionEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app,rules);
}
GatewayFlowRuleController 类
/**
* 把配置推给nacos中
*
* @param app
* @throws Exception
*/
private void publishRules(String app) throws Exception {
List<GatewayFlowRuleEntity> rules = repository.findAllByApp(app);
rulePublisher.publish(app, rules);
}
- 修改GatewayApiController 和 GatewayFlowRuleController 的 @PostMapping("/new.json") @PostMapping("/save.json") @PostMapping("/delete.json") 都是一样的改造
entity = repository.save(entity); // 保存到内存中
// 推送给微服务
// publishRules(entity.getApp(), entity.getIp(), entity.getPort());
// 现通过 自己的publisher推送到配置中心
publishRules(entity.getApp());
- 修改 NacosConfigUtil
public final class NacosConfigUtil {
public static final String GROUP_ID = "SENTINEL_GROUP";
public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
public static final String DEGRAD_DATA_ID_POSTFIX = "-degrade-rules";
public static final String AUTH_DATA_ID_POSTFIX = "-authority-rules";
public static final String SYS_DATA_ID_POSTFIX = "-system-rules";
public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";
public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";
public static final String GETWAY_API_DATA_ID_POSTFIX = "-getway-api";
public static final String GETWAY_FLOW_DATA_ID_POSTFIX = "-getway-flow";
/**
* cc for `cluster-client`
*/
public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config";
/**
* cs for `cluster-server`
*/
public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config";
public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config";
public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set";
private NacosConfigUtil() {}
}
此时,GatewayFlowRuleController 已经改造完毕。喜大普奔23333
2.5 修改端口
如果是集群,修改为nginx的地址
3. 微服务网关改造
- 加入依赖
<!-- sentilen用 nacos 做 持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
- yml配置
# 新增持久化配置
server:
port: 8888
spring:
application:
name: gateway-sentinel
cloud:
gateway:
discovery:
locator:
lower-case-service-id: true
enabled: true
routes:
- id: product_center
uri: lb://product-center
predicates:
- Path=/product/**
- id: order_center
uri: lb://order-center
predicates:
- Path=/order/**
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:9999
datasource:
# 名称随意
gw-flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-gateway-flow # 在修改的sentinel 源码中定义的规则名
groupId: SENTINEL_GROUP
rule-type: gw-flow
gw-api-group:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-gateway-api # 在修改的sentinel 源码中定义的规则名
groupId: SENTINEL_GROUP
rule-type: gw-api-group
main:
allow-bean-definition-overriding: true
4. 持久化测试
启动 订单微服务工程(啥也没有,就是一个接口查db) 和网关微服务工程,启动sentinel源码 地址 http://localhost:9999/#/login
先访问一次网关接口 http://localhost:8888/product/selectProductInfoById/1
http://localhost:9999/#/dashboard (sentinel 控制台)
配置流控
再看nacos
多次访问 网关接口被限流了
最后,重启 gateway or sentinel 规则还在~ 在nacos或者sentinel控制台 改规则,两边都能同步
继续多次刷网关接口,显示被限流
大功告成~
5.结语
世上无难事,只怕有心人,每天积累一点点,fighting!!!
更多推荐
所有评论(0)