[Sentinel (1)] Introduction and use of Sentinel

1. What is Sentinel

Sentinel is an open source project of Ali. It provides multiple dimensions such as flow control, circuit breaker degradation, and system load protection to ensure stability between services.

Official website: https://github.com/alibaba/Sentinel/wiki

Main features of Sentinel:
Insert picture description here

The difference between Sentinel and Hystrix

For the difference between Sentinel and Hystrix, see: https://yq.aliyun.com/articles/633786/

In general:

The thread pool isolation commonly used by Hystrix will cause the overhead of thread up and down switching to be relatively large; the semaphore isolation used by Hystrix controls the number of concurrent calls to a certain resource, and the effect is good, but slow calls cannot be automatically downgraded; Sentinel uses the number of concurrent threads The flow control provides the function of signal isolation;

In addition, Sentinel supports more fuse degradation dimensions, which can perform flow control and fuse for a variety of indicators, and provides real-time monitoring and control panels, which are more powerful.

Second, the code example

Let's follow the Quick Start Demo provided on the official website to see how to use Sentinel to achieve current limiting and downgrading.
See the code for this article: github code

note:

  • JDK >= 1.7;
  • Sentinel version is 1.7.0;

Introduce the Sentinel jar package:

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

1. Current limit

For the use and introduction of current limiting, see: Sentinel Flow Control

The principle of Flow Control is to monitor the QPS of application traffic or the number of concurrent threads and other indicators. When the specified threshold is reached, the traffic is controlled to prevent the system from being overwhelmed by instantaneous traffic peaks and ensure high application availability.

Write a simple example below to see how to use Sentinel to achieve current limiting.

First, write a simple order query interface for subsequent interface current limiting examples:

@Component
public class OrderQueryService {
    
    

    public String queryOrderInfo(String orderId) {
    
    
        System.out.println("获取订单信息:" + orderId);
        return "return OrderInfo :" + orderId;
    }
}

@Controller
@RequestMapping("order")
public class OrderController {
    
    
    @Autowired
    private OrderQueryService orderQueryService;

    @RequestMapping("/getOrder")
    @ResponseBody
    public String queryOrder1(@RequestParam("orderId") String orderId) {
    
    

        return orderQueryService.queryOrderInfo(orderId);
    }
}

Under normal circumstances, calling the order query interface in OrderController will return order information. How to control the QPS accessed by the interface to be below 2? Sentienl current limiting provides the following implementation methods:

How Sentienl is used.

First, you need to define the current limiting rules, such as which interface to limit the current, how much QPS is limited, and what is the limiting caller app, etc.:

public void initFlowQpsRule() {
    
    
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule1 = new FlowRule();
        rule1.setResource(KEY);
        // QPS控制在2以内
        rule1.setCount(2);
        // QPS限流
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setLimitApp("default");
        rules.add(rule1);
        FlowRuleManager.loadRules(rules);
    }

There are many ways to implement current limiting, and this article only lists two common ones:

(1) Current limit implementation method 1: Define resources by throwing exceptions

This method is highly intrusive to the code, and the code needs try-catchto be packaged through the style API where the interface is called :

		/**
     * 限流实现方式一: 抛出异常的方式定义资源
     *
     * @param orderId
     * @return
     */
		@RequestMapping("/getOrder1")
    @ResponseBody
    public String queryOrder2(@RequestParam("orderId") String orderId) {
    
    

        Entry entry = null;
        // 资源名
        String resourceName = KEY;
        try {
    
    
            // entry可以理解成入口登记
            entry = SphU.entry(resourceName);
            // 被保护的逻辑, 这里为订单查询接口
            return orderQueryService.queryOrderInfo(orderId);
        } catch (BlockException blockException) {
    
    
            // 接口被限流的时候, 会进入到这里
            log.warn("---getOrder1接口被限流了---, exception: ", blockException);
            return "接口限流, 返回空";
        } finally {
    
    
            // SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
            if (entry != null) {
    
    
                entry.exit();
            }
        }

    }

Test, when QPS> 2, the interface returns:

View log output:

Insert picture description here

Note here that Sentinel's default log output file location is:/{userhome}/logs/csp/

When the interface is throttling, let's see what log Sentinel outputs:

The log format is: timestamp | the first resource that occurred in the second | resource name, reason for interception, source of interface calls, | caller of the intercepted resource, number of intercepted

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-dWZtliaM-1575117332202)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191124103313950.png)]

For a description of the log, see Sentienl log.

(2) Current limiting realization method 2: Annotation method defines resources

The above-mentioned try-catchstyle API can achieve current limiting, but it is too intrusive to the code. It is recommended to use annotations to achieve this. If not noted below, it will be implemented by default by means of annotations.

For the use of annotations, see: Sentinel Annotation Use

First, you need to introduce a jar package that supports annotations:

<dependency>
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-annotation-aspectj</artifactId>
     <version>${sentinel.version}</version>
</dependency>

Sentinel aspect configuration:

@Configuration
public class SentinelAspectConfiguration {
    
    

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
    
    
        return new SentinelResourceAspect();
    }
}

In the interface OrderQueryService, use annotations to implement the current limit of the order query interface:

    /**
     * 订单查询接口, 使用Sentinel注解实现限流
     *
     * @param orderId
     * @return
     */
    @SentinelResource(value = "getOrderInfo", blockHandler = "handleFlowQpsException",
            fallback = "queryOrderInfo2Fallback")
    public String queryOrderInfo2(String orderId) {
    
    

        // 模拟接口运行时抛出代码异常
        if ("000".equals(orderId)) {
    
    
            throw new RuntimeException();
        }

        System.out.println("获取订单信息:" + orderId);
        return "return OrderInfo :" + orderId;
    }

    /**
     * 订单查询接口抛出限流或降级时的处理逻辑
     *
     * 注意: 方法参数、返回值要与原函数保持一致
     * @return
     */
    public String handleFlowQpsException(String orderId, BlockException e) {
    
    
        e.printStackTrace();
        return "handleFlowQpsException for queryOrderInfo2: " + orderId;
    }

    /**
     * 订单查询接口运行时抛出的异常提供fallback处理
     *
     * 注意: 方法参数、返回值要与原函数保持一致
     * @return
     */
    public String queryOrderInfo2Fallback(String orderId, Throwable e) {
    
    
        return "fallback queryOrderInfo2: " + orderId;
    }
  • blockHandler = "handleFlowQpsException"Used to deal with Sentinel current limiting/fuse and other errors;
  • fallback = "queryOrderInfo2Fallback"Used to deal with all the exceptions of the business code in the interface (such as business code exceptions, sentinel current limiting fuse exceptions, etc.);

Note: The method name and parameters in the above two processing methods must be consistent with the protected function.

test:

		/**
     * 限流实现方式二: 注解定义资源
     *
     * @param orderId
     * @return
     */
    @RequestMapping("/getOrder2")
    @ResponseBody
    public String queryOrder3(@RequestParam("orderId") String orderId) {
    
    
        return orderQueryService.queryOrderInfo2(orderId);
    }

The test results are not posted here, and the results are similar.

2. Fuse downgrade

In addition to flow control, fusing and downgrading unstable resources in the calling link is also one of the important measures to ensure high availability.

Due to the complexity of the call relationship, if a certain resource in the call link is unstable, it will eventually lead to the accumulation of requests. Sentinel fuse downgrade will limit the invocation of this resource when a certain resource in the call link is unstable (for example, the call timeout or the abnormal ratio increases), so that the request will fail quickly and avoid affecting other resources and causing the level Link error. When the resource is downgraded, within the next downgrade time window, all calls to the resource are automatically fuse (the default behavior is to throw DegradeException).

For an introduction about fusing downgrade, see: Sentinel fusing downgrade.

The following is an annotation-based way to implement the demo of Sentinel's fusing and downgrading.

@Component
@Slf4j
public class GoodsQueryService {
    
    

    private static final String KEY = "queryGoodsInfo2";

    /**
     * 模拟商品查询接口
     *
     * @param spuId
     * @return
     */
    @SentinelResource(value = KEY, blockHandler = "blockHandlerMethod", fallback = "queryGoodsInfoFallback")
    public String queryGoodsInfo(String spuId) {
    
    

        // 模拟调用服务出现异常
        if ("0".equals(spuId)) {
    
    
            throw new RuntimeException();
        }

        return "query goodsinfo success, " + spuId;
    }

    public String blockHandlerMethod(String spuId, BlockException e) {
    
    
        log.warn("queryGoodsInfo222 blockHandler", e.toString());
        return "queryGoodsInfo error, blockHandlerMethod res: " + spuId;

    }

    public String queryGoodsInfoFallback(String spuId, Throwable e) {
    
    
        log.warn("queryGoodsInfo222 fallback", e.toString());
        return "queryGoodsInfo error, return fallback res: " + spuId;
    }

    @PostConstruct
    public void initDegradeRule() {
    
    
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();
        rule.setResource(KEY);
        // 80s内调用接口出现异常次数超过5的时候, 进行熔断
        rule.setCount(5);
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        rule.setTimeWindow(80);
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
    }
}


// 测试类
@Controller
@RequestMapping("goods")
public class GoodsController {
    
    

    @Autowired
    private GoodsQueryService goodsQueryService;

    @RequestMapping("/queryGoodsInfo")
    @ResponseBody
    public String queryGoodsInfo(@RequestParam("spuId") String spuId) {
    
    
        String res = goodsQueryService.queryGoodsInfo(spuId);
        return res;
    }
}

Three, the use of the console

Sentinel provides a lightweight open source console, which provides machine discovery, health management, monitoring (single machine and cluster), rule management and push functions.

The main functions are:

  • Check the machine list and health status;
  • monitor;
  • Rule management and push;
  • Authentication

1. Start the Sentinel console

How to start the console see: Start the console

Start method:

(1) Download the jar package, by command

Download the dashboard jar package of the corresponding version at https://github.com/alibaba/Sentinel/releases, enter the directory where the jar is located, and then run the jar package through the java command:

java -Dserver.port=8080 \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-jar target/sentinel-dashboard.jar

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-QHMUeLiz-1575117332203)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130195303037.png)]

(2) git clone the entire sentinel source code, enter the sentinel-dashboard module, and execute the packaging command:, mvn clean packagegenerate an executable fat jar package, then start the console, enter url:, and localhost:8080then enter the main page.

2. Client access (Spring Boot project access to the console)

After starting the console module, the console pages are all empty and need to be connected to the client.

(1) First import the jar package that communicates with the console:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>${sentinel.version}</version>
</dependency>

(2) Configure JVM startup parameters:

-Dproject.name=sentinel-demo -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dcsp.sentinel.api.port=8719

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-pxjzpbyT-1575117332204)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130192128302.png)]

Start the application.

Note: The application needs to have initialization code to trigger current limit and degradation.

The http://localhost:8083/order/getOrder1?orderId=123interface in this demo is executed multiple times, which will trigger the current limiting operation. At this time, go to the console:

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-sZvaNKw7-1575117332204)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130195613860.png)]

As you can see, the number of times the getOrderInfo interface has been current-limited.

4. Use of the console

If we want to use Sentinel's current limiting and fuse function, in addition to hard coding in the code, you can also roughly limit and fuse the interface directly through the console.

/**
     * 代码不加任何限流 熔断
     * @return
     */
    @RequestMapping("/test")
    @ResponseBody
    @SentinelResource("test")
    public String test() {
    
    
        return "test";
    }

After executing the http://localhost:8083/goods/testinterface action, you can see that the interface has been counted in the cluster point link on the page:

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-kc56Vgu1-1575117332207)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130201216117.png)]

Click Flow Control to add a flow control rule to the interface, and the configuration is as follows:

[External link image transfer failed. The source site may have an anti-leech link mechanism. It is recommended to save the image and upload it directly (img-zMK2mbJt-1575117332208)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130201312578.png)]

After clicking add,

[External link image transfer failed. The source site may have an anti-hotlinking mechanism. It is recommended to save the image and upload it directly (img-BxQdvVMd-1575117332209)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image- 20191130201331799.png)]

Go to execute the interface again http://localhost:8083/goods/test, and when the QPS exceeds 2, you can see that the interface returns abnormally, and the flow control effect is achieved.

Of course, there are still many uses of console flow control rules and downgrade rules. You can refer to the official documentation to see how to use them.


PS

In the process of accessing the console, it is found that the console will always report error:

2019-11-30 20:42:23.338 ERROR 5317 --- [pool-2-thread-1] c.a.c.s.dashboard.metric.MetricFetcher   : Failed to fetch metric from <http://10.200.183.30:8721/metric?startTime=1575117735000&endTime=1575117741000&refetch=false> (ConnectionException: Connection refused)

The cause of the error is that the console http://10.200.183.30:8721cannot connect from the IP address when collecting client data ;

Later, I found that the proxy was turned on, and it was normal after turning off the proxy.


reference:

Official document: https://github.com/alibaba/Sentinel/wiki

Reference blog: https://www.jianshu.com/p/c47dfd25eeee The
code of this article: https://github.com/nomico271/sentinel-demo/tree/master/Ch1_SentinelDemo

Guess you like

Origin blog.csdn.net/noaman_wgs/article/details/103328793