sentinel 通过sdk的方式接入不同的数据来源

主要用于定制化sentinel 管理控制页面,通过sdk方式对接不同的配置数据来源

一、需求背景

云原生服务治理平台提供了一站式的服务限流、降级等服务治理功能。服务治理提供agent和sdk的接入方式,本文主要介绍sdk接入方式。

二、架构设计

sentinel 通过sdk的方式接入不同的数据来源_第1张图片

关键组件说明:

  • Sentinel sdk: 服务治理的限流、降级功能依托sentinel实现。使用sentinel的sdk实现扩展redis数据源

  • 服务治理dashboard: 服务治理自己的控制台,用以替换sentinel原生的dashboard,实现可以在服务治理的页面管控服务限流、降级等规则配置

  • Redis服务订阅: 通过redis的订阅特性,实现配置规则修改后可以推送数据到客户端,实现动态的规则修改

流程:

  • 客户端启动的时候完成redis订阅,第一次接口访问后开始发送健康心跳
  • 在服务治理平台上修改配置规则后,发送到redis
  • 客户端收到redis channel推送来的消息,动态的修改SentinelProperty 属性,完成动态规则修改

三、接入说明

1、pom引入

<!-- 和dashboard通信 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.1</version>
</dependency>
<!-- sentinel  redis扩展 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-redis</artifactId>
    <version>1.8.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.1</version>
</dependency>

2、编写 Sentinel redis 扩展配置类

import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.redis.RedisDataSource;
import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class RedisSentinelConfig implements InitializingBean {


    private String flowRuleKey = "sentinel.rules.flow.ruleKey";
    private String flowChannel = "sentinel.rules.flow.channel";
    private String degradeRuleKey = "sentinel.rules.degrade.ruleKey";
    private String degradeChannel = "sentinel.rules.degrade.channel";


    public void initData(String app) {

        RedisConnectionConfig config = RedisConnectionConfig.builder()
                .withRedisSentinel("ip",8001)
                .withRedisSentinel("ip",8001)
                .withSentinelMasterId("mymaster")
                .build();

        Converter<String, List<FlowRule>> flowConfigParser = buildFlowConfigParser();
        ReadableDataSource<String, List<FlowRule>> flowRedisDataSource = new RedisDataSource<>(config,
                getRedisName(flowRuleKey,app), getRedisName(flowChannel,app), flowConfigParser);
        FlowRuleManager.register2Property(flowRedisDataSource.getProperty());

        Converter<String, List<DegradeRule>> degradeConfigParser = buildDegradeConfigParser();
        ReadableDataSource<String, List<DegradeRule>> degradeRedisDataSource = new RedisDataSource<>(config,
                getRedisName(degradeRuleKey,app), getRedisName(degradeChannel,app), degradeConfigParser);
        DegradeRuleManager.register2Property(degradeRedisDataSource.getProperty());
    }

    public String getRedisName(String key,String app){
        return key+":"+app;
    }

    private Converter<String, List<FlowRule>> buildFlowConfigParser() {
        return source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {});
    }

    private Converter<String, List<DegradeRule>> buildDegradeConfigParser() {
        return source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {});
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        String property = System.getProperty("project.name");
        if (property == null || property.split("&").length < 2) {
            throw new Exception("启动参数 project.name 未完整配置");
        }
        if (System.getProperty("csp.sentinel.dashboard.server") == null) {
            throw new Exception("启动参数 csp.sentinel.dashboard.server 未配置");
        }
        //自定义的app 名称
        initData(property.split("&")[0]);
    }
}

3、Jvm 启动参数

-Dproject.name=app&sysCode&clusterDel  -Dcsp.sentinel.dashboard.server=localhost:8082 

project.name参数说明:
app 应用名称,initData函数的入参也是这个
sysCode 系统编码
clusterDel k8s部署单元名称,如果和app一样可以不填

csp.sentinel.dashboard.server 地址为云原生平台提供的控制台地址

四、使用说明

基本使用: https://sentinelguard.io/zh-cn/docs/basic-api-resource-rule.html

开源框架适配: https://sentinelguard.io/zh-cn/docs/open-source-framework-integrations.html

你可能感兴趣的:(sentinel,redis,java)