Sentinel 服务流控(上)

开课吧樵夫2022-01-04 18:09

  流量控制也称为限流。Sentinel 实现流控的原理是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对再来的请求进行进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

  服务流控是为了在高并发场景下不至于将系统压垮。一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:

resource 资源名,即限流规则的作用对象
count 限流阈值
grade 限流阈值类型(QPS 或并发线程数)
limitApp 流控针对的调用来源,若为default则不区分调用来源
strategy 调用关系限流策略
controlBehavior 流量控制效果(直接拒绝、Warm Up、匀速排队)

  流控规则设置

  Sentinel流控规则设置方式一共有三种,分别是:

  动态设置流控规则【Dashboard+注解】

  代码设置流控规则【注解】

  代码设置流控规则【非注解】

  动态设置流控规则【Dashboard+注解】

  复制consumer-nacos-sentinel-circuitbreaking工程重命名为consumer-nacos-sentinel-flowcontrol

  修改PetsController.java 

// 跨服务根据id查询
@GetMapping("/get/{id}")
// 该注解表明当前方法是一个由Sentinel管理的资源,value属性用于指定该资源的名称
// blockHandler 指定流控兜底方法
@SentinelResource(value = "qpsFlowRule", blockHandler = "getHandleFlow")
public Pets getHandle(@PathVariable("id") int id) {
    String url = SERVICE_PROVIDER + "/provider/pets/get/" + id;
    Pets pets = restTemplate.getForObject(url, Pets.class);
    return pets;
}

public Pets getHandleFlow(int id, BlockException be) {
    System.out.println("be.getMessage() = " + be.getMessage());
    Pets pets = Pets.builder().name("flow-controller = " + id).build();
    return pets;
}

  运行程序, dashboard 设置流控规则。

Sentinel 服务流控(上)

  测试效果:每秒发送两个请求。

Sentinel 服务流控(上)

  代码设置流控规则【注解】- 推荐使用

  流控规则直接定义在代码中,当应用启动时完成流控规则的创建与初始化。这个流控规则在Dashboard中也是可以查看到并且进行编辑的,编辑后以动态编辑的规则为准。

  首先修改启动类。

package com.javafamily;

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.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

// 配置开启feign
@EnableFeignClients
@SpringBootApplication
public class FlowControlConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(FlowControlConsumerApplication.class, args);
        // 初始化流控规则
        initFlowRule();
    }

    public static void initFlowRule() {
        List<FlowRule> flowRules = new ArrayList<>();
        FlowRule qpsRule = FlowControlConsumerApplication.qpsFlowRule();
        flowRules.add(qpsRule);
        FlowRuleManager.loadRules(flowRules);
    }

    private static FlowRule qpsFlowRule() {
        //创建流控规则对象
        FlowRule qpsRule = new FlowRule();
        //设置流控资源名称
        qpsRule.setResource("qpsFlowRule");
        //设置流控规则【QPS和线程数】
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //设置QPS数为1
        qpsRule.setCount(1);
        //值为default,表示对请求来源不做限定
        qpsRule.setLimitApp("default");
        return qpsRule;
    }
}

  再来查看控制台。

Sentinel 服务流控(上)

  最后进行测试。

Sentinel 服务流控(上)

  代码设置流控规则【非注解】

  流控规则在代码中的应用,一般是通过@SentinelResource 指定的。但也可以通过代码指定。只不过这种方式不提倡使用。

  修改PetsController.java

// 跨服务根据id查询
@GetMapping("/get/{id}")
public Pets getHandle(@PathVariable("id") int id) {
    Entry entry = null;
    try {
        entry = SphU.entry("qpsFlowRule");
        String url = SERVICE_PROVIDER + "/provider/pets/get/" + id;
        return restTemplate.getForObject(url, Pets.class);
    } catch (BlockException e) {
        Pets pets = new Pets();
        pets.setName("我是被限流处理的结果!");
        return pets;
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
}

  运行程序后,一定要记得配置流控规则,最后测试效果。