"Spring Cloud Alibaba Microservice Architecture" topic (15)-Spring Cloud AlibabaSentinel @SentinelResource annotation configuration details

1 Introduction

In the previous chapters, we have used @SentinelResourceannotations. In this article, how we will use @SentinelResource annotations to flexibly define control resources and how to configure control strategies. After defining the resource point, we can Dashboardprotect the resource point by setting current limiting and downgrading strategies. At the same time, you can also @SentinelResourcespecify the exception handling strategy when current limiting and degradation occur. Next, let's take a look at how current limiting and downgrading are achieved.

2.@SentinelResource case analysis

Below we introduce the use of @SentinelResource annotation in two situations:

按资源名称进行限流;
按URL请求路径进行限流;

2.1. Current limiting by resource name

So we need to transform the module [springcloudalibaba-sentinel-service8401]:

[A] Create a new RateLimitController.java

@SentinelResourceMainly used to define a resource. blockHandler is used to specify the downgrade method.

package com.bruce.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.bruce.pojo.JsonResult;
import com.bruce.pojo.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;


@RestController
public class RateLimitController {
    
    

    /**
     * 根据资源名称进行限流
     */
    @GetMapping("/limitByResource")
    @SentinelResource(value = "limitByResource", blockHandler = "blockHandlerLimitByResource")
    public JsonResult limitByResource() {
    
    
        return new JsonResult(200, "根据资源名称进行限流", new Payment(20200906L, UUID.randomUUID().toString()));
    }

    /**
     * 服务兜底降级方法
     */
    public JsonResult blockHandlerLimitByResource(BlockException exception) {
    
    
        return new JsonResult(500, exception.getClass().getCanonicalName() + "\t 服务不可用");
    }

    /**
     * 根据URL进行限流
     */
    @GetMapping("/limitByUrl")
    @SentinelResource(value = "limitByUrl")
    public JsonResult limitByUrl() {
    
    
        return new JsonResult(200, "根据URL进行限流", new Payment(20200906L, UUID.randomUUID().toString()));
    }

}

[B] Configure flow control rules, see the figure below for details
Insert picture description here
Insert picture description here

[C] Current limit by resource name-test

Normal browser access: http://localhost:8401/limitByResource The
Insert picture description here
above is a normal access, that is, only one request is sent in one second. Below we crazy request this interface in one second: http://localhost:8401/limitByResource
Insert picture description here
we It is found that when the number of requests in one second is greater than one, the interface is restricted and the microservice is unavailable. These have been introduced in the previous chapters. I believe that the friends are not unfamiliar. Next, let’s take a look at an additional problem. We stop the 8401 service and return to the Sentinel console:
Insert picture description here
We found that when we stop After the microservice, all the previously configured flow control rules have disappeared. Obviously, the flow control rules of Sentinel are temporary and are not persistent at present. Here we will first introduce the problem, and we will talk about how to solve it later.

2.2. Limit flow by URL

[A] Limit flow by URL-test
Insert picture description here
. Normal browser access: http://localhost:8401/limitByUrl, once a
Insert picture description here
second, once a second, is normal access, that is, only one request is sent within one second. Crazy request for this interface within seconds: http://localhost:8401/limitByUrl
Insert picture description here
We found that because the /limitByUrl method did not specify the blockHandler downgrade method, the prompt confidence of the current limit is also the default error report [Blocked by Sentinel ( flow limiting)], as shown in the figure above.

Summarize the current problems of the above-mentioned method of handling the bottom line:

1.系统默认的,没有体现我们自己的业务要求;
2.依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观;
3.每个业务方法都需要添加一个降级方法,代码膨胀加剧;
4.没有体现全局统一的处理方法;

3. Customer-defined current limiting processing logic

By default, Sentinel's current limiting processing of control resources directly throws exceptions. This can be done if there is no reasonable business undertaking or front-end docking, but under normal circumstances, for better user business, some special processing will be implemented after the flow is limited. We don't want to show a rigid error, which requires us to customize Current limit processing logic.

[A] Create a CustomBlockHandler class for custom current limiting processing logic

package com.bruce.controller;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.bruce.pojo.JsonResult;

/**
 * @Description 自定义BlockHandler限流处理类
 * 说明: 必须是static静态方法
 */
public class CustomBlockHandler {
    
    

    public static JsonResult customBlockHandlerMethodA(BlockException exception) {
    
    
        return new JsonResult(500, "[客户自定义限流处理逻辑]--->customBlockHandlerMethodA");
    }

    public static JsonResult customBlockHandlerMethodB(BlockException exception) {
    
    
        return new JsonResult(500, "[客户自定义限流处理逻辑]--->customBlockHandlerMethodB");
    }
}

【B】 RateLimitController.java

  blockHandlerClass: 指定限流逻辑处理类;
  blockHandler: 指定限流处理方法, 对应blockHandlerClass处理类中的方法名称;
 /**
   * 客户自定义限流处理逻辑
   * blockHandlerClass: 指定限流逻辑处理类
   * blockHandler: 指定限流处理方法, 对应blockHandlerClass处理类中的方法名称
   */
  @GetMapping("/customBlockHandler")
  @SentinelResource(value = "customBlockHandler",
          blockHandlerClass = CustomBlockHandler.class,
          blockHandler = "customBlockHandlerMethodA")
  public JsonResult customerBlockHandler() {
    
    
      return new JsonResult(200, "客户自定义限流处理逻辑", new Payment(20200906L, UUID.randomUUID().toString()));
  }

Mainly did two things:

通过@SentinelResource注解的blockHandler属性制定具体的处理函数
实现处理函数,该函数的传参必须与资源点的传参一样,并且最后加上BlockException异常参数;同时,返回类型也必须一样。

Readers who are familiar with Hystrix should find that this design is very similar to the fallback defined in HystrixCommand, and it is easy to understand.

[C] Sentinel configuration
Insert picture description here
[d] test

Normal browser access: http://localhost:8401/customBlockHandler once a
Insert picture description here
second, once a second, both are normal access, that is, only one request is sent in one second, and we will request this interface madly in one second: http: //localhost:8401/customBlockHandler
Insert picture description here
can see that because the downgrade method we specified is customBlockHandlerMethodA, when the traffic exceeds the threshold, the downgrade processing is also customBlockHandlerMethodAthe logic of the method. Through the above method, all the downgrade processing is extracted, which is conducive to decoupling from the business logic, and it is recommended to use it.

4. More annotation attribute description

View Sentinelsource code, you can see SentinelResourcethe definition of the value, entryType, resourceType, blockHandler, fallback, defaultFallbackand other property, source code as follows:

/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.csp.sentinel.annotation;

import com.alibaba.csp.sentinel.EntryType;

import java.lang.annotation.*;

/**
 * The annotation indicates a definition of Sentinel resource.
 *
 * @author Eric Zhao
 * @since 0.1.1
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
    
    

    /**
     * @return name of the Sentinel resource
     */
    String value() default "";

    /**
     * @return the entry type (inbound or outbound), outbound by default
     */
    EntryType entryType() default EntryType.OUT;

    /**
     * @return the classification (type) of the resource
     * @since 1.7.0
     */
    int resourceType() default 0;

    /**
     * @return name of the block exception function, empty by default
     */
    String blockHandler() default "";

    /**
     * The {@code blockHandler} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same block handler,
     * then users can set the class where the block handler exists. Note that the block handler method
     * must be static.
     *
     * @return the class where the block handler exists, should not provide more than one classes
     */
    Class<?>[] blockHandlerClass() default {
    
    };

    /**
     * @return name of the fallback function, empty by default
     */
    String fallback() default "";

    /**
     * The {@code defaultFallback} is used as the default universal fallback method.
     * It should not accept any parameters, and the return type should be compatible
     * with the original method.
     *
     * @return name of the default fallback method, empty by default
     * @since 1.6.0
     */
    String defaultFallback() default "";

    /**
     * The {@code fallback} is located in the same class with the original method by default.
     * However, if some methods share the same signature and intend to set the same fallback,
     * then users can set the class where the fallback function exists. Note that the shared fallback method
     * must be static.
     *
     * @return the class where the fallback method is located (only single class)
     * @since 1.6.0
     */
    Class<?>[] fallbackClass() default {
    
    };

    /**
     * @return the list of exception classes to trace, {@link Throwable} by default
     * @since 1.5.1
     */
    Class<? extends Throwable>[] exceptionsToTrace() default {
    
    Throwable.class};
    
    /**
     * Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should
     * not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore}
     * will be of higher precedence.
     *
     * @return the list of exception classes to ignore, empty by default
     * @since 1.6.0
     */
    Class<? extends Throwable>[] exceptionsToIgnore() default {
    
    };
}

The following explains the role of these attributes:

  • value: Resource name, a required item, because the corresponding rule needs to be found through the resource name, this must be configured.
  • entryType: Entry type, optional, there are two options, IN and OUT, the default is EntryType.OUT.
public enum EntryType {
    
    
    IN("IN"),
    OUT("OUT");
}
  • blockHandler: BlockHandler corresponds to the name of the function that handles BlockException, optional. The access scope of the blockHandler function needs to be public, the return type needs to match the original method, the parameter type needs to match the original method, and an additional parameter is added at the end, the type is BlockException.
  • blockHandlerClass: By default, the blockHandler function needs to be in the same class as the original method. If you want to use functions of other classes, you need to specify blockHandlerClass as the Class object of the corresponding class. Note that the corresponding function must be a static function, otherwise it cannot be parsed.
  • fallback: Fallback function name, optional, used to provide fallback processing logic when an exception is thrown. The fallback function can handle all types of exceptions (except the exception types excluded in exceptionsToIgnore).
  • fallbackClass: The application of fallbackClass is similar to blockHandlerClass. The fallback function needs to be in the same class as the original method by default. If you want to use functions of other classes, you can specify fallbackClass as the Class object of the corresponding class. Note that the corresponding function must be a static function, otherwise it cannot be parsed.
  • defaultFallback(Since 1.6.0): If the defaultFallback method is not configured, it will come here by default. The default fallback function name, optional, usually used for general fallback logic. The default fallback function can handle all types of exceptions (except the exception types excluded in exceptionsToIgnore). If both fallback and defaultFallback are configured, only fallback will take effect.
  • exceptionsToIgnore(Since 1.6.0): Used to specify which exceptions are excluded, not included in the exception statistics, and will not enter the fallback logic, but will be thrown as-is.

Note: The fallback function of versions prior to 1.6.0 only deals with DegradeException, and cannot deal with business exceptions.

5. Summary

This article mainly summarizes how to use @SentinelResourceannotations to flexibly define control resources and how to configure control strategies to achieve control of the call current limit of a method or the call current limit of an external resource.

Guess you like

Origin blog.csdn.net/BruceLiu_code/article/details/113934265