生产环境Sentinel改造实践(二):规则管理推送改造
前文介绍了Sentinel相关的核心概念,本文开始动手对规则管理推送进行改造。
这里挑选流控规则模式改造为示例
Sentinel Dashboard 改造
在
com.alibaba.csp.sentinel.dashboard.rule.nacos新建NacosConfig.javapackage com.alibaba.csp.sentinel.dashboard.rule.nacos; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.List;
import java.util.Properties; /**
* @wiki https://github.com/eacdy/Sentinel-Dashboard-Nacos
* add by tam
*/
@Configuration
public class NacosConfig { @Bean
public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
return JSON::toJSONString;
} @Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
return s -> JSON.parseArray(s, FlowRuleEntity.class);
} @Bean
public ConfigService nacosConfigService() throws Exception {
NacosProperties nacosProperties = nacosProperties();
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, nacosProperties.getServerAddr());
if (!nacosProperties.getNamespace().isEmpty()) {
properties.put(PropertyKeyConst.NAMESPACE, nacosProperties.getNamespace());
}
return ConfigFactory.createConfigService(properties);
} @Bean
@ConfigurationProperties(prefix = "spring.cloud.sentinel.datasource.nacos")
public NacosProperties nacosProperties() {
return new NacosProperties();
} @Getter
@Setter
public static class NacosProperties {
private String serverAddr;
private String namespace;
private String groupId;
}
}
这里主要接收三个参数
serverAddr: nacos服务器地址,namespace:nacos命名空间,groupId:nacos分组在
application.properties里新增配置spring.cloud.sentinel.datasource.nacos.server-addr=172.16.1.20:8848
spring.cloud.sentinel.datasource.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.nacos.namespace=wuyan_local
同级目录下新增
NacosConfigUtil.javapackage com.alibaba.csp.sentinel.dashboard.rule.nacos; import com.alibaba.csp.sentinel.dashboard.util.JSONUtils;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.RuleEntity;
import com.alibaba.fastjson.JSON;
import com.alibaba.csp.sentinel.slots.block.Rule;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors; /**
* @wiki https://github.com/eacdy/Sentinel-Dashboard-Nacos
* add by tam
*/
@Component
public class NacosConfigUtil {
@Autowired
private NacosConfig.NacosProperties nacosProperties; public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";
public static final String DEGRADE_DATA_ID_POSTFIX = "-degrade-rules";
public static final String SYSTEM_DATA_ID_POSTFIX = "-system-rules";
public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-flow-rules";
public static final String AUTHORITY_DATA_ID_POSTFIX = "-authority-rules";
public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gateway-flow-rules";
public static final String GATEWAY_API_DATA_ID_POSTFIX = "-gateway-api-rules";
public static final String DASHBOARD_POSTFIX = "-dashboard";
public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map"; /**
* 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"; /**
* 将规则序列化成JSON文本,存储到Nacos server中
*
* @param configService nacos config service
* @param app 应用名称
* @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX
* @param rules 规则对象
* @throws NacosException 异常
*/
public <T> void setRuleStringToNacos(ConfigService configService, String app, String postfix, List<T> rules) throws NacosException {
AssertUtil.notEmpty(app, "app name cannot be empty");
if (rules == null) {
return;
} List<Rule> ruleForApp = rules.stream()
.map(rule -> {
RuleEntity rule1 = (RuleEntity) rule;
//System.out.println(rule1.getClass());
Rule rule2 = rule1.toRule();
//System.out.println(rule2.getClass());
return rule2;
})
.collect(Collectors.toList()); // 存储,给微服务使用
String dataId = genDataId(app, postfix);
configService.publishConfig(
dataId,
nacosProperties.getGroupId(),
JSON.toJSONString(ruleForApp)
); // 存储,给控制台使用
configService.publishConfig(
dataId + DASHBOARD_POSTFIX,
nacosProperties.getGroupId(),
JSONUtils.toJSONString(rules)
);
} /**
* 从Nacos server中查询响应规则,并将其反序列化成对应Rule实体
*
* @param configService nacos config service
* @param appName 应用名称
* @param postfix 规则后缀 eg.NacosConfigUtil.FLOW_DATA_ID_POSTFIX
* @param clazz 类
* @param <T> 泛型
* @return 规则对象列表
* @throws NacosException 异常
*/
public <T> List<T> getRuleEntitiesFromNacos(ConfigService configService, String appName, String postfix, Class<T> clazz) throws NacosException {
String rules = configService.getConfig(
genDataId(appName, postfix) + DASHBOARD_POSTFIX,
//genDataId(appName, postfix),
nacosProperties.getGroupId(),
3000
);
if (StringUtil.isEmpty(rules)) {
return new ArrayList<>();
}
return JSONUtils.parseObject(clazz, rules);
} private static String genDataId(String appName, String postfix) {
return appName + postfix;
}
注意这里的
dataId完整的为 【appId(即客户端spring.application.name配置应用名)+-flow-rules】这个很重要,客户端在集成nacos的sentinel配置时这个要对应
在
com.alibaba.csp.sentinel.dashboard.rule.nacos.flow目录下新建FlowRuleNacosProvider.javapackage com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.List; /**
* @author Eric Zhao
* @since 1.4.0
* add by tam
*/
@Component("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> { @Autowired
private ConfigService configService; @Autowired
private NacosConfigUtil nacosConfigUtil; @Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
return nacosConfigUtil.getRuleEntitiesFromNacos(
this.configService,
appName,
NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
FlowRuleEntity.class
);
}
}
这个类主要从Nacos拉取规则信息
在
com.alibaba.csp.sentinel.dashboard.rule.nacos.flow目录下新建FlowRuleNacosPublisher.javapackage com.alibaba.csp.sentinel.dashboard.rule.nacos.flow; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.util.List; /**
* @author Eric Zhao
* @since 1.4.0
* add by tam
*/
@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> { @Autowired
private ConfigService configService; @Autowired
private NacosConfigUtil nacosConfigUtil; @Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
nacosConfigUtil.setRuleStringToNacos(
this.configService,
app,
NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
rules
);
}
}
修改
com.alibaba.csp.sentinel.dashboard.controller.v2.FlowControllerV2类@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
主要增加
@Qualifier("flowRuleNacosProvider")和@Qualifier("flowRuleNacosPublisher")
Sentinel接入客户端
项目如果是SpringCloud项目在pom文件里引入
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
在bootstrap.properties新增如下配置
server.port=8002
spring.application.name=qetesh-openapi
spring.cloud.nacos.discovery.server-addr=172.16.1.20:8848
spring.cloud.nacos.discovery.namespace=wuyan_local
spring.cloud.sentinel.transport.dashboard=localhost:8888
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds1.nacos.dataId=${spring.application.name}-flow-rules
spring.cloud.sentinel.datasource.ds1.nacos.namespace=wuyan_local
spring.cloud.sentinel.datasource.ds1.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
注意三个参数 serverAddr,namespace,groupId 和Dashboard的保持一致
并且spring.cloud.sentinel.datasource.ds1.nacos.rule-type 值为flow(流控)
在启动类增加如下代码
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableDiscoveryClient
public class QeteshOpenapiApplication {
public static void main(String[] args) {
SpringApplication.run(QeteshOpenapiApplication.class, args);
}
@RestController
static class TestController {
@SentinelResource("ken2")
@GetMapping("/hello")
public String hello() {
return "itweek.top";
}
}
}
启动项目访问接口,在DashBoard里就能看到相关的配置

在流控规则里新增如下配置,


这时在nacos也会有相应的配置

多次访问接口会出现 即代表流控规则限流成功

生产环境Sentinel改造实践(二):规则管理推送改造的更多相关文章
- React 与 Redux 在生产环境中的实践总结
React 与 Redux 在生产环境中的实践总结 前段时间使用 React 与 Redux 重构了我们360netlab 的 开放数据平台.现将其中一些技术实践经验总结如下: Universal 渲 ...
- Redash(开源轻量级商业智能) 生产环境部署及实践 (without docker)
一直在调研一个轻量级开源的 BI 系统.之前我们生产环境使用的 aliyun 的 QuickBi,也调研了另外一个 airflow 的开源商业智能 superset.不得不承认 QuickBI 正在日 ...
- 生产环境 tidb部署实践
TiDB 简介 TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytic ...
- 前端通信:SSE设计方案(二)--- 服务器推送技术的实践以及一些应用场景的demo(包括在线及时聊天系统以及线上缓存更新,代码热修复案例)
距离上一篇博客,这篇文章的发布大概过了整整三个月.我也从饿了么度过了试用期,成为了正式员工.刚进来恰好遇到项目底层改造和迁移,将项目从angular全部迁移到vue上,所以适应这边的节奏和业务的开发任 ...
- 阿里巴巴微服务与配置中心技术实践之道 配置推送 ConfigurationManagement ConfigDrivenAnyting
阿里巴巴微服务与配置中心技术实践之道 原创: 坤宇 InfoQ 2018-02-08 在面向分布式的微服务系统中,如何通过更高效的配置管理方式,帮助微服务系统架构持续"无痛"的演进 ...
- AndroidStudio离线打包MUI集成JPush极光推送并在java后端管理推送
1.AndroidStudio离线打包MUI 如何离线打包请参看上篇随笔<AndroidStudio离线打包MUI> 2.集成极光推送 官方文档:https://docs.jiguang. ...
- Win10环境下使用Flask配合Celery异步推送实时/定时消息(Socket.io)/2020年最新攻略
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_163 首先得明确一点,和Django一样,在2020年Flask 1.1.1以后的版本都不需要所谓的三方库支持,即Flask-Ce ...
- git 分支管理 推送本地分支到远程分支等
1.创建本地分支 local_branch git branch local_branch 2.创建本地分支local_branch 并切换到local_branch分支 git checkout - ...
- Spring Cloud Alibaba学习笔记(7) - Sentinel规则持久化及生产环境使用
Sentinel 控制台 需要具备下面几个特性: 规则管理及推送,集中管理和推送规则.sentinel-core 提供 API 和扩展接口来接收信息.开发者需要根据自己的环境,选取一个可靠的推送规则方 ...
- Dubbo Mesh 在闲鱼生产环境中的落地实践
本文作者至简曾在 2018 QCon 上海站以<Service Mesh 的本质.价值和应用探索>为题做了一次分享,其中谈到了 Dubbo Mesh 的整体发展思路是“借力开源.反哺开源” ...
随机推荐
- 鲲鹏(ARM64)+麒麟(Kylin v10)离线部署 KubeSphere
作者:社区用户-天行1st 本文将详细介绍,如何基于鲲鹏 CPU(ARM64) 和操作系统 Kylin V10 SP2/SP3,利用 KubeKey 制作 KubeSphere 和 Kubernete ...
- KubeSphere Meetup 北京站火热报名中 | 搭载 CIC 2021 云计算峰会
"CIC 2021 云计算峰会"是一场 Top 级行业盛会,将汇聚 800 家青云QingCloud 企业客户信息化负责人,采取线上线下相结合的方式,与会规模将超过 10000 人 ...
- 使用 KubeSphere 实现微服务的灰度发布
前言 今天来说一说,在 KubeSphere 中两个 " 小姐姐 " 如何来回切换,这是什么意思哩?其实就是互联网产品中常用的灰度发布方式. 互联网产品需要快速迭代上线,既要保证新 ...
- Oracle 数据泵 定时全库备份&&删除备份文件【注意点】
一.概述 在给客户部署的数据泵备份&&删除过期备份脚本时,脚本删除部分未生效,导致存储空间占用非常大. 手动执行该删除命令时,执行成功: 最后发现需要增加 find.rm 等命令的PA ...
- 使用flask进行Mock Server模拟接口操作及问题解决
1.flask介绍 flask是一个轻量级的python web 微框架 2.Mock Server介绍 Mock Server是一个开源的模拟服务器,它可以定义和记录API交互,支持各种http方法 ...
- 云开发实践:从 0 到 1 带你玩 AI
今天我们将深入分析云开发的 AI 能力.这次的讨论焦点不再是之前提到的云端IDE编写代码的能力,而是更为广泛和实际的内容--如何利用云平台提供的各种模块化能力,快速高效地开发.今天的主题依然围绕AI展 ...
- java内存区域——daicy
Java虚拟机 运行时数据区 主要分为五部分:方法区,堆(这两块是所有线程共享的区域),程序计数器,本地方法栈,虚拟机栈(vm stack)(这三块为线程隔离区域) 程序计数器(Program Cou ...
- Lock Less Java Object Pool
It has been a while since I wrote anything, I have been busy with my new job that involves doing som ...
- PowerShell一键下载Nuget某个包的所有版本
一转眼好几年没有写博客了,来博客园冒个泡,最近由于工作需要,内网办公,幸运的是只需要上传一个*.nupkg一个包信息就可以在私有nuget下载到了,下面就用PowerShell编写下载脚本,需要注意的 ...
- 关于com组件的方法,以AE的IFieldsEdit为例
今天,有小伙伴问我,为什么在调用IFieldsEdit接口时,VS无法自动显示出AddFiled方法,而这个方法是确实存在的 在此,做下解答,因为这个方法被隐藏了.TypeLibFunc属性,被用来指 ...