sentinel自定义DataSource实战

本文主要研究一下如何自定义sentinel的DataSource,这里以jdbc为例。

maven

        
            org.springframework.cloud
            spring-cloud-starter-sentinel
            0.2.0.BUILD-SNAPSHOT
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.apache.tomcat
            tomcat-jdbc
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            com.h2database
            h2
            runtime
        
        
            org.springframework.boot
            spring-boot-starter-web
        

扩展AutoRefreshDataSource

public class JdbcDataSource extends AutoRefreshDataSource {

    final String DEFAULT_SQL = "SELECT VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and KEY=?";

    final PropertiesResultSetExtractor extractor = new PropertiesResultSetExtractor();

    JdbcTemplate jdbc;

    String app;

    String key;

    String profile;

    public JdbcDataSource(JdbcTemplate jdbc,String app,String profile,String key,ConfigParser configParser, long recommendRefreshMs) {
        super(configParser, recommendRefreshMs);
        this.jdbc = jdbc;
        this.app = app;
        this.key = key;
        this.profile = profile;
    }

    @Override
    public String readSource() throws Exception {
        List data = (List) jdbc.query(DEFAULT_SQL,
                new Object[] { app, profile, key }, this.extractor);
        if(data.size() > 0){
            return data.get(0);
        }
        return null;
    }

    class PropertiesResultSetExtractor implements ResultSetExtractor> {

        @Override
        public List extractData(ResultSet rs)
                throws SQLException, DataAccessException {
            List result = new ArrayList<>(1);
            while (rs.next()) {
                result.add(rs.getString(1));
            }
            return result;
        }

    }
}
  • 这里以拉模式为例,因而扩展的是AutoRefreshDataSource

数据结构及初始化数据

CREATE TABLE IF NOT EXISTS PROPERTIES (
  KEY         VARCHAR(128),
  VALUE       VARCHAR(4096),
  APPLICATION VARCHAR(128),
  PROFILE     VARCHAR(128),
  PRIMARY KEY (`KEY`, `APPLICATION`, `PROFILE`)
);

INSERT INTO PROPERTIES (APPLICATION, PROFILE, KEY, VALUE)
VALUES ('sentinel-demo', 'jdbc', 'flow', '[
  {
    "resource": "abc",
    "controlBehavior": 0,
    "count": 20.0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  },
  {
    "resource": "abc1",
    "controlBehavior": 0,
    "count": 20.0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]');
INSERT INTO PROPERTIES (APPLICATION, PROFILE, KEY, VALUE)
VALUES ('sentinel-demo', 'jdbc', 'system', '[
  {
    "avgRt": 10,
    "highestSystemLoad": 5.0,
    "maxThread": 10,
    "qps": 20.0
  }
]');

INSERT INTO PROPERTIES (APPLICATION, PROFILE, KEY, VALUE)
VALUES ('sentinel-demo', 'jdbc', 'degrade', '[
  {
    "resource": "abc0",
    "count": 20.0,
    "grade": 0,
    "passCount": 0,
    "timeWindow": 10
  },
  {
    "resource": "abc1",
    "count": 15.0,
    "grade": 0,
    "passCount": 0,
    "timeWindow": 10
  }
]');
  • 这里仿照spring cloud config server的jdbc存储的schema

自动加载

@Component
public class SentinelJdbcAutoConfig implements CommandLineRunner {

    @Value("${spring.application.name}")
    String app;

    @Autowired
    private Environment environment;

    @Autowired
    JdbcTemplate jdbcTemplate;

    int defaultRefreshMs = 10*1000;

    @Override
    public void run(String... args) throws Exception {
        String profile = environment.getActiveProfiles().length > 0 ? environment.getActiveProfiles()[0] : "default";
        // data source for FlowRule
        DataSource> flowRuleDataSource = new JdbcDataSource>(jdbcTemplate,
                app,profile,"flow", new JsonFlowRuleListParser(),defaultRefreshMs);
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

        // data source for DegradeRule
        DataSource> degradeRuleDataSource = new JdbcDataSource>(jdbcTemplate,
                app,profile,"degrade", new JsonDegradeRuleListParser(),defaultRefreshMs);
        DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());

        // data source for SystemRule
        DataSource> systemRuleDataSource = new JdbcDataSource>(jdbcTemplate,
                app,profile,"system", new JsonSystemRuleListParser(),defaultRefreshMs);
        SystemRuleManager.register2Property(systemRuleDataSource.getProperty());
    }
}
  • 这里在启动时通过FlowRuleManager.register2Property,注册了flowRule、degradeRule、systemRule三类规则的数据源

验证

启动之后访问http://localhost:8080/actuator/sentinel,可以看到如下规则:

{
  "DegradeRules": [
    {
      "resource": "abc1",
      "limitApp": "default",
      "count": 15,
      "timeWindow": 10,
      "grade": 0,
      "cut": false,
      "passCount": 0
    },
    {
      "resource": "abc0",
      "limitApp": "default",
      "count": 20,
      "timeWindow": 10,
      "grade": 0,
      "cut": false,
      "passCount": 0
    }
  ],
  "SystemRules": [
    {
      "resource": null,
      "limitApp": null,
      "highestSystemLoad": 5,
      "qps": -1,
      "avgRt": -1,
      "maxThread": -1
    },
    {
      "resource": null,
      "limitApp": null,
      "highestSystemLoad": -1,
      "qps": -1,
      "avgRt": 10,
      "maxThread": -1
    },
    {
      "resource": null,
      "limitApp": null,
      "highestSystemLoad": -1,
      "qps": -1,
      "avgRt": -1,
      "maxThread": 10
    },
    {
      "resource": null,
      "limitApp": null,
      "highestSystemLoad": -1,
      "qps": 20,
      "avgRt": -1,
      "maxThread": -1
    }
  ],
  "FlowRules": [
    {
      "resource": "abc1",
      "limitApp": "default",
      "grade": 1,
      "count": 20,
      "strategy": 0,
      "refResource": null,
      "controlBehavior": 0,
      "warmUpPeriodSec": 10,
      "maxQueueingTimeMs": 500
    },
    {
      "resource": "abc",
      "limitApp": "default",
      "grade": 1,
      "count": 20,
      "strategy": 0,
      "refResource": null,
      "controlBehavior": 0,
      "warmUpPeriodSec": 10,
      "maxQueueingTimeMs": 500
    }
  ],
  "properties": {
    "enabled": true,
    "port": "7080",
    "dashboard": "localhost:9999",
    "filter": {
      "order": -2147483648,
      "urlPatterns": [
        "/*"
      ]
    }
  }
}

查看sentinel的dashboard,可以发现dashboard也能识别出应用自定义的规则。

小结

sentinel datasource提供了灵活的扩展机制,可以自定义数据源来满足不同应用的需求。

doc

  • sentinel-extension

你可能感兴趣的:(sentinel自定义DataSource实战)