sentinel-网关

Sentinel 使用-单机版

  • pom.xml
<!-- https://mvnrepository.com/artifact/com.alibaba.csp/sentinel-core -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.6.3</version>
</dependency>
  • @SentinelResource标记,blockHandler指定熔断后的处理方法
  • 注意:创建熔断规则时指定的资源名称必须和@SentinelResource#value的值对应,不然被拒掉的请求没有降级的业务服务
@GetMapping("/test/sentinel")
@SentinelResource(value = "createOrder", blockHandler = "blockMethod")
public Object testSentinel(@AuthenticationPrincipal String username) {
	log.info("user is " + username);
	return username;
}

public Object blockMethod(@AuthenticationPrincipal String username, BlockException exception) {
	log.info("block by " + exception.getClass().getSimpleName());
	return username;
}
  • 配置限流和熔断规则
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhang3
 * className org._33web.api.order.sentinel.SentinelConfig
 * date 2019/12/29 0029 22:59
 * version 1.0
 * description (this is an class) Sentinel 资源管理
 */
@Component
public class SentinelConfig implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        //限流规则
        FlowRule rule = new FlowRule();
        rule.setResource("createOrder");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(1);
        List<FlowRule> rules = new ArrayList<>();
        rules.add(rule);
        FlowRuleManager.loadRules(rules);

        //熔断规则
        DegradeRule degradeRule = new DegradeRule();
        degradeRule.setResource("createOrder");
        degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        degradeRule.setCount(10);
        degradeRule.setTimeWindow(10);
        List<DegradeRule> degradeRules = new ArrayList<>();
        degradeRules.add(degradeRule);
        DegradeRuleManager.loadRules(degradeRules);
    }
}

Sentinel-dashboard

  • 简述: Sentinel 是面向分布式服务架构的轻量级流量控制组件

  • 可视化、集中化、动态化管理分布式服务架构下微服务的限流、熔断、降级规则

github 下载源代码

选择非master分支的1.7版本

sentinel-dashboard.jar 执行命令

  • 可以自定义成docker 镜像
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.3.jar

web控制台

  • sentinel-dashboard web 控制台: http://ip:8080/#/login ,默认账号密码:sentinel/sentinel

controller改造

  • 将FlowControllerV1.java 的请求导向FlowControllerV2.java

  • 将DegradeController.java 的请求导向DegradeControllerV2.java

  • 参考代码下载 http://119.23.50.122/ms/sentinel-dashboard/v2.zip

Sentinel-dashboard Docker安装

docker run -d \
-p 8000:8000 \
-v /etc/localtime:/etc/localtime:ro \
--name group_sentinel-dashboard-server_1 docker.io/sentinel-dashboard-server:1.0

配置中心 zookeeper 篇

修改sentinel-dashboard

基本配置

  • 修改pom.xml 注释掉 scope#test
<!--for Zookeeper rule publisher sample-->
<dependency>
	<groupId>org.apache.curator</groupId>
	<artifactId>curator-recipes</artifactId>
	<version>${curator.version}</version>
	<!--<scope>test</scope>-->
</dependency>
  • 修改application.properties
#登录用户名和密码
# If auth.enabled=false, Sentinel console disable login
auth.username=root
auth.password=root

# 端口
server.port=8000
  • 复制代码
将/test/java/com.alibaba.csp.sentinel.dashboard.rule.zookeeper包整个
复制到
/main/java/com.alibaba.csp.sentinel.dashboard.rule.zookeeper

改造zookeeper的默认实现

  • 修改代码参考 http://119.23.50.122/ms/sentinel-dashboard/zookeeper.zip

流控规则 FlowControllerV2

  • 在FlowControllerV2.java中,改为flowRuleZookeeperProvider和flowRuleZookeeperPublisher
@Autowired
@Qualifier("flowRuleZookeeperProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleZookeeperPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

降级规则 DegradeControllerV2

  • 在DegradeControllerV2.java中,改为degradeRuleZookeeperProvider和degradeRuleZookeeperPublisher
@Autowired
@Qualifier("degradeRuleZookeeperProvider")
private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;
@Autowired
@Qualifier("degradeRuleZookeeperPublisher")
private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;

Sentinel 客户端整合

  • 1、限流 (拒绝掉该请求,不做其他处理)
  • 2、熔断 (配置熔断,并指定熔断后的处理方法)
  • 3、热点数据 (通过请求参数配置)

组件选择

  • sentinel、sentinel-dashboard、zookeeper、spring boot

基本配置

  • pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
	<version>0.9.0.RELEASE</version>
</dependency>

<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-zookeeper</artifactId>
	<version>1.5.2</version>
</dependency>
  • application.yml
spring:
  application:
    name: api-service-order
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8000
        port: 8100

sentinel:
  zookeeper:
    address: 192.168.0.10:2181
    path: /sentinel_rule_config

加载规则

  • sentinel客户端配置,加载流控规则、熔断规则等
import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author zhang3
 * description sentinel 客户端配置,用于加载流控规则、熔断规则等
 */
@Component
public class SentinelClientConfig {

    @Value("${sentinel.zookeeper.address}")
    private String zkServer;

    @Value("${sentinel.zookeeper.path}")
    private String zkPath;

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

    @PostConstruct
    public void loadRules() {
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(zkServer, buildAppName("flow") ,
                source -> JSON.parseArray(source, FlowRule.class));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

        ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new ZookeeperDataSource<>(zkServer, buildAppName("degrade") ,
                source -> JSON.parseArray(source, DegradeRule.class));
        DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());

    }

    public String buildAppName(String ruleName) {
        return zkPath+"/" + appName + "_" + ruleName;
    }

}

示例

  • @SentinelResource标记,blockHandler指定熔断后的处理方法
  • 注意:创建熔断规则时指定的资源名称必须和@SentinelResource#value的值对应,不然被拒掉的请求没有降级的业务服务
@GetMapping("/test/sentinel")
@SentinelResource(value = "createOrder", blockHandler = "blockMethod")
public Object testSentinel(@AuthenticationPrincipal String username) {
    log.info("user is " + username);
    return username;
}

public Object blockMethod(@AuthenticationPrincipal String username, BlockException exception) {
    log.info("block by " + exception.getClass().getSimpleName());
    return username;
}
  • 关于@SentinelResource
@SentinelResource注解最主要的两个用法:限流控制和熔断降级的具体使用案例介绍完了。
另外,该注解还有一些其他更精细化的配置,比如忽略某些异常的配置、默认降级函数等等,
具体可见如下说明:
1、value:资源名称,必需项(不能为空)

2、entryType:entry 类型,可选项(默认为 EntryType.OUT)

3、blockHandler / blockHandlerClass: blockHandler对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

4、fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

5、defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
返回值类型必须与原函数返回值类型一致;
方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。

6、exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

配置中心 Nacos 篇

修改sentinel-dashboard

基本配置

  • 修改pom.xml 注释掉 scope#test
<!--for Nacos rule publisher sample-->
<dependency>
	<groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
	<!--<scope>test</scope>-->
</dependency>
  • 修改application.properties
#登录用户名和密码
# If auth.enabled=false, Sentinel console disable login
auth.username=root
auth.password=root

# 端口
server.port=8000
  • 复制代码
将/test/java/com.alibaba.csp.sentinel.dashboard.rule.nacos包整个
复制到
/main/java/com.alibaba.csp.sentinel.dashboard.rule.nacos

改造Nacos的默认实现

  • 修改代码参考 http://119.23.50.122/ms/sentinel-dashboard/nacos.zip

流控规则 FlowControllerV2

  • 在FlowControllerV2.java中,改为flowRuleNacosProvider和flowRuleNacosPublisher
@Autowired
@Qualifier("flowRuleNacosProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleNacosPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

降级规则 DegradeControllerV2

  • 在DegradeControllerV2.java中,改为degradeRuleNacosProvider和degradeRuleNacosPublisher
@Autowired
@Qualifier("degradeRuleNacosProvider")
private DynamicRuleProvider<List<DegradeRuleEntity>> ruleProvider;
@Autowired
@Qualifier("degradeRuleNacosPublisher")
private DynamicRulePublisher<List<DegradeRuleEntity>> rulePublisher;

sentinel 网关整合

  • spring-cloud-gateway 官方文档 https://cloud.spring.io/spring-cloud-gateway/reference/html/
  • gateway routes配置 https://www.jianshu.com/p/c8ac84e820cc

组件选择

  • sentinel、sentinel-dashboard 、nacos、spring-cloud-gateway

搭建网关

  • pom.xml
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!-- sentinel/sentinel-dashboard nacos  -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.7.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  • application.yml
server:
  port: 9080

spring:
  application:
    name: test-gateway
  cloud:
    gateway:
      routes:
        - id: host_route
          uri: http://192.168.0.2:9090/
          predicates:
            - Host=app-web.33web.org:${server.port}
        - id: host2_route
          uri: http://192.168.0.2:9091/
          predicates:
            - Host=user.33web.org:${server.port}
    sentinel:
      transport:
        dashboard: localhost:8000
        port: 8100

加载规则

import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.PropertyKeyConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;


/**
 * @author zhang3
 * description 初始化Sentinel 网关 相关配置
 */
@Configuration
@Slf4j
public class SentinelConfig {

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

    public static final String GROUP_ID = "SENTINEL_GROUP";

//    private static final String NACOS_SERVER_ADDR = "172.17.0.1:8848";
//    private static final String NACOS_NAMESPACE = "146fdeb6-b082-42d6-9d9b-47cdf79ec55d";

    private static final String NACOS_SERVER_ADDR = "192.168.0.10:8848";
    private static final String NACOS_NAMESPACE = "d400a63f-301b-4951-acfb-d98cc0b0a425";

    @PostConstruct
    public void loadRules() {
        Properties properties = new Properties();
        //指定ip地址
        properties.put(PropertyKeyConst.SERVER_ADDR, NACOS_SERVER_ADDR);

        //设置命名空间(namespace)
        properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE);

        //网关熔断
        ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new NacosDataSource<>(properties, SentinelConfig.GROUP_ID, buildAppName("degrade") ,
                source -> JSON.parseArray(source, DegradeRule.class));
        DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());

        //网关流控
        ReadableDataSource<String, Set<GatewayFlowRule>> gatewayRuleDataSource = new NacosDataSource<>(properties, SentinelConfig.GROUP_ID, buildAppName("gateway_flow") ,
                source -> new HashSet<>(JSON.parseArray(source, GatewayFlowRule.class)));
        GatewayRuleManager.register2Property(gatewayRuleDataSource.getProperty());

        //Api流控
//        ReadableDataSource<String, Set<ApiDefinition>> ApiDataSource = new NacosDataSource<>(properties, SentinelConfig.GROUP_ID, buildAppName("gateway_api") ,
//                source -> new HashSet<>(JSON.parseArray(source, ApiDefinition.class)));

        ReadableDataSource<String, Set<ApiDefinition>> ApiDataSource = new NacosDataSource<>(properties, SentinelConfig.GROUP_ID, buildAppName("gateway_api") ,
                source -> {
                    List<String> apis = JSON.parseArray(source, String.class);
                    HashSet<ApiDefinition> sets = new HashSet<>();
                    for(String api : apis) {
                        ApiDefinition entity = JSON.parseObject(api, ApiDefinition.class);
                        entity.getPredicateItems().clear();
                        JSONObject jsonObject = JSON.parseObject(api);
                        String items = jsonObject.getString("predicateItems");
                        List<ApiPathPredicateItem> list = JSON.parseArray(items, ApiPathPredicateItem.class);
                        entity.getPredicateItems().addAll(list);
                        sets.add(entity);
                    }
                    return sets;
                });
        GatewayApiDefinitionManager.register2Property(ApiDataSource.getProperty());
    }


    private String buildAppName(String ruleName) {
        return appName + "_" + ruleName;
    }
}

启动参数

  • 增加启动参数(VM),指定网关启动参数,即app.type=1
-Dcsp.sentinel.app.type=1
  • 其他启动配置 https://github.com/alibaba/Sentinel/wiki/启动配置项

sentinel 客户端整合

组件选择

  • sentinel、sentinel-dashboard、nacos、spring boot

集成sentinel

  • pom.xml
        <!-- sentinel/sentinel-dashboard nacos  -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.7.1</version>
        </dependency>
  • application.yml
server:
  port: 9090

spring:
  application:
    name: test-web
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8000
        port: 8100

加载规则

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
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.nacos.api.PropertyKeyConst;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;

/**
 * @author zhang3
 * description 初始化Sentinel 应用 相关配置
 */
@Configuration
public class SentinelConfig {

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

    @PostConstruct
    public void loadRules() {
        Properties properties = new Properties();
        //指定ip地址
        properties.put(PropertyKeyConst.SERVER_ADDR, "192.168.0.10:8848");
        //设置命名空间(namespace)
        properties.put(PropertyKeyConst.NAMESPACE, "d400a63f-301b-4951-acfb-d98cc0b0a425");

        String groupId = "SENTINEL_GROUP";

        //应用流控
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId, buildAppName("flow") ,
                source -> JSON.parseArray(source, FlowRule.class));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

        //应用熔断
        ReadableDataSource<String, List<DegradeRule>> degradeRuleDataSource = new NacosDataSource<>(properties, groupId, buildAppName("degrade") ,
                source -> JSON.parseArray(source, DegradeRule.class));
        DegradeRuleManager.register2Property(degradeRuleDataSource.getProperty());
    }


    private String buildAppName(String ruleName) {
        return appName + "_" + ruleName;
    }

}

示例

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhang3
 * description TODO
 */
@RestController
@RequestMapping
@Slf4j
public class TestController {

    @Autowired
    TestService testService;

    @GetMapping("test/say")
    public void testSay(String msg, @RequestParam(defaultValue = "0") Integer error) {
        if (error == 1) {
            throw new RuntimeException("测试异常");
        }
        testService.testSentinel();
        log.info("invoke test-say: " + msg);
    }
}

@Component
@Slf4j
class TestService {

    @SentinelResource(value = "testSay")
    public void testSentinel() {
        log.info("invoke testSentinel method");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z先生09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值