This is the 20th day of my participation in the Genwen Challenge

Sentinel

Vi. @ SentinelResource

Perform flow control by resource name

code

@RestController
public class RateLimitController {
    @GetMapping("/byResource")
    @SentinelResource(value = "byResource",blockHandler = "handlerException")
    public ResultDto byResource(a) {
        System.out.println("byResource");
        return new ResultDto(200."byResource".new Payment(2020L."PaymentOne"));
    }

    public ResultDto handlerException(BlockException e) {
        System.out.println("deal_byResource");
        return new ResultDto(500,e.getClass().getCanonicalName()); }}Copy the code

The resource name is byResource

configuration

If you go beyond QPS, you enter a custom handlerException method. If you stream by URL, the resource name should be /byResource

Custom traffic limiting

Separate business code from blockHandler code

Business code

@GetMapping("/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class,blockHandler = "customerBlockHandler")
public ResultDto customerBlockHandler(a) {
    System.out.println("customerBlockHandler");
    return new ResultDto(200."Customize customerBlockHandler");
}
Copy the code

CustomerBlockHandler

public class CustomerBlockHandler {
    public static ResultDto customerBlockHandler(BlockException e) {
        return new ResultDto(500."CustomerBlockHandler-- 1");
    }

    public static ResultDto customerBlockHandler2(BlockException e) {
        return new ResultDto(500."CustomerBlockHandler-- 2"); }}Copy the code

When the flow control rule is triggered, the method specified by blockHandler in the class specified by blockHandlerClass is invoked.

Annotation attribute Description

Note: The annotation method does not support the private method.

@SentinelResource is used to define resources and provides optional exception handling and Fallback configuration items. The @sentinelResource annotation contains the following properties:

  • Value: resource name, required (cannot be empty)

  • EntryType: Entry type, optional (default entrytype.out)

  • BlockHandler/blockHandlerClass: Specifies the name of the function that processes blockExceptions. This parameter is optional. The blockHandler function must have a public access scope, a return type that matches the original method, a parameter type that matches the original method and an extra parameter of type BlockException at the end. The blockHandler function needs to be in the same class as the original method by default. If you want to use a function of another Class, you can specify blockHandlerClass as the Class object of the corresponding Class. Note that the corresponding function must be static; otherwise, it cannot be parsed.

  • fallback
    Copy the code

    : The optional fallback function name that provides fallback handling logic when an exception is thrown. The fallback function is available for all types of exceptions (except

    exceptionsToIgnore
    Copy the code

    The type of exception that is excluded). Fallback function signature and position requirements:

    • The return value type must be the same as that of the original function;
    • The method argument list needs to be the same as the original function, or it can be an extra oneThrowableType to receive the corresponding exception.
    • The fallback function needs to be in the same class as the original method by default. You can specify if you want to use a function from another classfallbackClassOf the corresponding classClassObject, note that the corresponding function must be static, otherwise it cannot be parsed.
  • defaultFallback
    Copy the code

    (since 1.6.0) : Default fallback function name, optional, usually used for generic fallback logic (that is, can be used for many services or methods). The default fallback function can be used for all types of exceptions (except

    exceptionsToIgnore
    Copy the code

    The type of exception that is excluded). If both fallback and defaultFallback are configured, only fallback takes effect. DefaultFallback signature requirements:

    • The return value type must be the same as that of the original function;
    • The method parameter list needs to be empty, or you can have an extra parameterThrowableType to receive the corresponding exception.
    • DefaultFallback needs to be in the same class as the original method by default. You can specify if you want to use a function from another classfallbackClassOf the corresponding classClassObject, note that the corresponding function must be static, otherwise it cannot be parsed.
  • ExceptionsToIgnore (since 1.6.0) : Specifies which exceptions are excluded and are not counted in the exception statistics or fallback logic. Instead, it is thrown as is.

Note: The fallback function before 1.6.0 only handles DegradeException, not service exception.

In particular, if blockHandler and Fallback are configured, only blockHandler processing logic will be entered when a BlockException is thrown due to traffic limiting demotion. If blockHandler, FallBack, and defaultFallback are not configured, BlockException will be thrown when traffic limiting is degraded.

Vii. Service circuit breaker

Sentinel integrated Ribbon + openFeign + fallback

Environment set up

Service providercloudalibaba-provider-payment9003/9004

Rely on
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code
configuration
server:
  port: 9003
spring:
  application:
    name: nacos-provider-payment
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848   Nacos configuration center address
management:   Expose the monitoring address
  endpoints:
    web:
      exposure:
        include: The '*'
Copy the code
business
@RestController
public class PaymentController {
    @Value("${server.port}")
    private String port;

    public static HashMap<Long, Payment> hashMap = new HashMap<>();
    static {
        hashMap.put(1L.new Payment(1L."111111111111111"));
        hashMap.put(2L.new Payment(2L."222222222222222"));
        hashMap.put(3L.new Payment(3L."333333333333333"));
    }

    @GetMapping("/payment/{id}")
    public ResultDto<Payment> customerBlockHandler(@PathVariable("id") Long id) {
        Payment payment = hashMap.get(id);
        return new ResultDto<Payment>(200."---customerBlockHandler---" + port + "-",payment); }}Copy the code

Copy 9004 from 9003

Service consumercloudalibaba-consumer-nacos-order84

Rely on
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Copy the code
configuration
server:
  port: 84
spring:
  application:
    name: nacos-consumer-order
  cloud:
    nacos:
      discovery:
        server-addr: 127.0. 01.: 8848   Nacos configuration center address
    sentinel:
      transport:
        dashboard: localhost:8080
        The default port is 8719. If the port is occupied, a +1 scan is automatically performed starting from 8719 to find the port that is not occupied
        port: 8719
service-url:  # Optional, the name of the microservice accessed by the user
  nacos-user-service: http://nacos-provider-payment
Copy the code
config
@SpringBootConfiguration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(a) {
        return newRestTemplate(); }}Copy the code
business
@RestController
public class CircleBreakerController {
    public final static String SERVER_URL = "http://nacos-provider-payment";
    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource("fallback")		// No configuration
    public ResultDto<Payment> fallback(@PathVariable("id") Long id) {
        ResultDto<Payment> result = restTemplate.getForObject(SERVER_URL + "/payment/" + id, ResultDto.class, id);
        if (result.getData() == null) {
            throw new NullPointerException("null");
        }
        returnresult; }}Copy the code

Service fuse test

The exception message is returned without specifying any fallback methods.

Configure the Fallback method

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback",fallback = "fallbackMethod")
public ResultDto<Payment> fallback(@PathVariable("id") Long id) {... }public ResultDto<String> fallbackMethod(@PathVariable("id") Long id,Throwable e) {
    return new ResultDto<>(500."fallbackMethod---" + e + "-" +id);
}
Copy the code

FallbackMethod is called when an exception occurs in the code.

Configure the blockHandler method

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandlerMethod")
public ResultDto<Payment> fallback(@PathVariable("id") Long id) {... }public ResultDto<String> blockHandlerMethod(@PathVariable("id") Long id, BlockException e) {
    return new ResultDto<>(500."blockMethod---" + e + "-" +id);
}
Copy the code

BlockHandler only invokes the methods of blockHandler after the Sentinel console configuration limits are triggered.

Configure the Fallback method and blockHandler method

Both can take effect. If there are conflicting console controls and blockHandler, they take precedence.

Configure the exceptionsToIgnore method

@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback",blockHandler = "blockHandlerMethod",exceptionsToIgnore = {NullPointerException.class})
public ResultDto<Payment> fallback(@PathVariable("id") Long id) {... }public ResultDto<String> blockHandlerMethod(@PathVariable("id") Long id, BlockException e) {
    return new ResultDto<>(500."blockMethod---" + e + "-" +id);
}
Copy the code

If the exceptionsToIgnore exception occurs again, the blockHandler method is not used

The service fuses OpenFeign

Rely on

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Copy the code

configuration

# Activate Sentinel support for Feign
feign:
  sentinel:
    enabled: true
Copy the code

The main start

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderMain84 {
    public static void main(String[] args) { SpringApplication.run(OrderMain84.class, args); }}Copy the code

business

@FeignClient(value = "nacos-provider-payment", fallback = PaymentFallbackService.class)
public interface PaymentService {
    @GetMapping("/payment/{id}")
    ResultDto<Payment> paymentSQL(@PathVariable("id") Long id);
}
Copy the code

If an exception occurs, the specific method implementation in the fallback implementation class needs to be degraded

@Service
public class PaymentFallbackService implements PaymentService{
    @Override
    public ResultDto<Payment> paymentSQL(Long id) {
        return new ResultDto<>(444."PaymentFallbackService - paymentSQL - the drop"); }}Copy the code

8. Sentinel rule Persistence

In the previous configuration, sentinel’s configuration rules were disabled whenever the microservice was restarted. Rule persistence was used to save the configured rules.

The rule configuration is saved in NACOS, and the sentinel configuration takes effect as soon as a rest address of the microservice is refreshed.

Example Modify the 8401 microservice

Rely on

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
Copy the code

configuration

cloud:
  sentinel:
     Persisting flow control rules to NACOS
      datasource:
        dsl:
          nacos:
            server-addr: localhost:8848
            data-id: ${spring.application.name}
            group-id: DEFAULT_GROUP
            data-type: json
            rule-type: flow
Copy the code

Sentinel Console Setup