sentinel:如何自定义mysql数据源?mybatis

背景

反复阅读sentinel的官方文档,发现:
1、默认情况下sentinel的限流规则是写在内存里的,一旦重启,规则就会丢失
2、限流规则的持久化,提供了以下几个推荐的方式,主要分为推和拉模式:
在这里插入图片描述
公司一般不会直接暴露redis、ZooKeeper等给业务同学使用,看了下redis的demo是需要输入用户名密码等,无法与公司的系统融合

再考虑到使用mysql相对比较简单,容易理解,于是选择使用拉模式定时从数据库中读取数据

具体实现

然而sentinel官网并没有提供拉模式读取mysql数据库的demo,于是只能参照拉模式读取文件的方式修改一下使用:

1、定义MySQLDataSource

需要继承AutoRefreshDataSource,然后这是一个模板类,第一个参数表示从DataSource中读取的数据格式是啥样,第二个参数表示最后需要转换成啥样(在这里分别是从数据库读取出来的List<OpenApiAppIdApiQps>, 和转换后的List<FlowRule>

@Service
public class MysqlRefreshableDataSource extends AutoRefreshDataSource<List<OpenApiAppIdApiQps>, List<FlowRule>> {

    private static final long DEFAULT_REFRESH_MS = 3000;

    @Autowired
    private OpenApiAppIdApiQpsMapper readOpenApiAppIdApiQpsMapper;

    public MysqlRefreshableDataSource(Converter<List<OpenApiAppIdApiQps>, List<FlowRule>> configParser) {
        super(configParser, DEFAULT_REFRESH_MS);
        firstLoad();
    }

    private void firstLoad() {
        try {
            List<FlowRule> newValue = loadConfig();
            getProperty().updateValue(newValue);
        } catch (Throwable e) {
            RecordLog.info("loadConfig exception", e);
        }
    }

    @Override
    public List<OpenApiAppIdApiQps> readSource() {
        return readOpenApiAppIdApiQpsMapper.selectAll();
    }

    @Override
    public void close() throws Exception {
        super.close();
    }
}

然后readSource()函数是用来自定义怎么读取规则数据源,在这里是直接读取数据表里的全部数据

附数据表

CREATE TABLE `openapi_appid_api_qps`
(
    `id`          bigint     PRIMARY KEY  NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `app_id` varchar(36)             NOT NULL DEFAULT '' COMMENT 'appid',
    `api`         varchar(36)     NOT NULL DEFAULT '' COMMENT 'appid有权限访问的api',
    `limit_qps` bigint NOT NULL DEFAULT 0 COMMENT 'api对某个appid的限流qps',	
    `create_at`   bigint                   NOT NULL DEFAULT 0 COMMENT '创建时间戳',
    `update_at`   bigint                  NOT NULL DEFAULT 0 COMMENT '更新时间戳',
    UNIQUE INDEX uk_appid_api (`app_id`, `api`)
) ENGINE = InnoDB DEFAULT CHARSET utf8mb4 COMMENT 'api对某个appid的限流qps对应表';

2、自定义如何实现数据源到flowRule的转换

在这里是通过stream直接做的对象转换:

@Configuration
public class SentinelConfiguration {

    @Autowired
    private MysqlRefreshableDataSource mysqlRefreshableDataSource;

    @Bean
    public Converter converter() {
        return (Converter<List<OpenApiAppIdApiQps>, List<FlowRule>>) source ->
                source.stream().map(openApiAppIdApiQps -> {
                    FlowRule flowRule = new FlowRule();
                    flowRule.setResource(openApiAppIdApiQps.getApi());
                    flowRule.setCount(openApiAppIdApiQps.getLimitQps());
                    flowRule.setLimitApp(openApiAppIdApiQps.getAppId());
                    flowRule.setGrade(1);
                    flowRule.setStrategy(0);
                    flowRule.setControlBehavior(0);
                    return flowRule;
                }).collect(Collectors.toList());
    }

    @PostConstruct
    public void doInit() {
        // 自定义限流参数
        WebCallbackManager.setRequestOriginParser(request -> {
            String origin = request.getParameter("appid");
            return origin != null ? origin : "";
        });
        // 自定义限流返回的响应
        WebCallbackManager.setUrlBlockHandler((request, response, ex) -> {
            Message message = Message.error(IExceptionCode.OPENAPI_TOO_MANY_REQ_EXCEPTION, "请求过于频繁");
            response.setContentType("application/json;charset=UTF-8");
            Gson gson = new GsonBuilder()
                    .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
                    .create();
            response.getOutputStream().write(gson.toJson(message).getBytes());
        });
        // 自定义拉取数据源
        FlowRuleManager.register2Property(mysqlRefreshableDataSource.getProperty());
    }
}

注意还需要在PostConstruct的时候注册一下数据源(上面的最后一行)

 FlowRuleManager.register2Property(mysqlRefreshableDataSource.getProperty());

这样,就会在Bean PostConstruct的时候,注册我们自定义的数据源了。mysqlRefreshableDataSource通过Autowired自动导入。

如此一来,我们就实现了定时从mysql读取规则数据了。

相关原理

to be continued

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值