mysql datasource property_Sentinel数据源(datasource)扩展-数据库

本文介绍了如何将MySQL作为Sentinel数据源的扩展,详细讲述了如何创建自定义的MysqlRefreshableDataSource类,该类继承自AutoRefreshDataSource并实现了从数据库读取FlowRule的方法。此外,还展示了通过JdbcTemplate实现数据库操作的步骤,以及相关的配置和依赖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景

sentinel推模式源码中的数据源是可扩展的,源码中只有几种数据源:redis、Apollo、Nacos、Zookeeper等;

8211e0bf57c9

image.png

拉模式中只有一种

8211e0bf57c9

image.png

二、具体实现

以mysql为例,作为数据库的数据源

1、定义一个MysqlDataSource

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

package com.高振芳.sentinel.controller;

import com.alibaba.csp.sentinel.datasource.AutoRefreshDataSource;

import com.alibaba.csp.sentinel.datasource.Converter;

import com.alibaba.csp.sentinel.log.RecordLog;

import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;

import com.高振芳.sentinel.entity.ResourceRoleQps;

import com.高振芳.sentinel.config.DataSourceUtils;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.RowMapper;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.List;

/**

* @program: sentinel

* @description: sentinel集成sql规则数据源

* @author: Gaozf

* @create: 2020-08-11 10:38

**/

public class MysqlRefreshableDataSource extends AutoRefreshDataSource,List> {

private static final long DEFAULT_REFRESH_MS = 3000;

public MysqlRefreshableDataSource(Converter, List> configParser) {

super(configParser, DEFAULT_REFRESH_MS);

firstLoad();

}

private void firstLoad() {

try {

List newValue = loadConfig();

getProperty().updateValue(newValue);

} catch (Throwable e) {

System.out.println(e);

RecordLog.info("loadConfig exception", e);

}

}

@Override

public List readSource() throws Exception {

JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

return jdbcTemplate.query("select id, app_id, api, limit_qps, create_at from resource_role_qps"

,new RowMapper(){

@Override

public ResourceRoleQps mapRow(ResultSet resultSet, int i) throws SQLException {

return new ResourceRoleQps(resultSet.getLong("id"),

resultSet.getString("app_id"),

resultSet.getString("api"),

resultSet.getLong("limit_qps"),

resultSet.getLong("create_at"));

}

});

}

@Override

public void close() throws Exception {

super.close();

}

}

readSource()方法就是为了从数据源读取所需数据

这里需要注意了:不可以使用注解的方式通过mybatis从数据库拉取数据,因为这个类时不能通过注解进行注入,没有无参构造函数,所以通过注解注入Mapper类去对数据库进行查找是不可以的。我这里实现是通过jdbc的方式。

2、调用、实现

@GetMapping("/gzf1111")

@SentinelResource(value = "gzf1111",blockHandler = "blockMehord")

public String hello(){

ReadableDataSource readableDataSource = new MysqlRefreshableDataSource(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())

);

// 自定义拉取数据源

FlowRuleManager.register2Property(readableDataSource.getProperty());

return "hello world";

}

public String blockMehord(BlockException ex) {

return "熔断";

}

3、JdbcTemplate实现方式

maven依赖

org.springframework.boot

spring-boot-starter-jdbc

com.alibaba

druid-spring-boot-starter

1.1.16

配置文件datasource.properties中数据库配置

driverClassName=com.mysql.cj.jdbc.Driver

url=jdbc:mysql://xxx.xxx.xxx.xxx:3306/sentinel?characterEncoding=utf-8

username=root

password=root

initialSize=5

maxActive=10

maxWait=2000

配置参数说明

8211e0bf57c9

image.png

Jdbc工具类

public class DataSourceUtils {

private static DataSource dataSource;

private static ThreadLocal tl = new ThreadLocal();

//在静态代码块中初始化连接池

static {

Properties properties = new Properties();

try {

//getResourceAsStream(String name) 在模块中查找指定名称的文件,返回该文件的输入流

properties.load(DataSourceUtils.class.getClassLoader().getResourceAsStream("datasource.properties"));

dataSource = DruidDataSourceFactory.createDataSource(properties);

} catch (Exception e) {

e.printStackTrace();

}

}

// 直接可以获取一个连接池

public static DataSource getDataSource() {

return dataSource;

}

// 获取连接对象

public static Connection getConnection() throws SQLException {

Connection con = tl.get();

if (con == null) {

con = dataSource.getConnection();

tl.set(con);

}

return con;

}

// 开启事务

public static void startTransaction() throws SQLException {

Connection con = getConnection();

if (con != null) {

con.setAutoCommit(false);

}

}

// 事务回滚

public static void rollback() throws SQLException {

Connection con = getConnection();

if (con != null) {

con.rollback();

}

}

// 提交并且 关闭资源及从ThreadLocall中释放

public static void commitAndRelease() throws SQLException {

Connection con = getConnection();

if (con != null) {

con.commit(); // 事务提交

con.close();// 关闭资源

tl.remove();// 从线程绑定中移除

}

}

// 关闭资源方法

public static void closeConnection() throws SQLException {

Connection con = getConnection();

if (con != null) {

con.close();

tl.remove();// 从线程绑定中移除

}

}

public static void closeStatement(Statement st) throws SQLException {

if (st != null) {

st.close();

}

}

public static void closeResultSet(ResultSet rs) throws SQLException {

if (rs != null) {

rs.close();

}

}

}

实现原理看另一篇DataSource源码解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值