Эта аннотация может одновременно исправить ограничение тока и понижение версии предохранителя: @SentinelResource

Java Spring Cloud

в предыдущем«Использование Sentinel для реализации ограничения тока интерфейса»В этой статье мы полагаемся только на интеграцию и инкапсуляцию Sentinel, представляя Spring Cloud Alibaba.spring-cloud-starter-alibaba-sentinel, который завершает текущий контроль ограничения всех интерфейсов Spring MVC. Однако в практических приложениях нам может понадобиться ограничить уровень тока не ограниченным интерфейсом. Может быть желательно контролировать вызов метода и вызов внешнего ресурса. Ну, в настоящее время мы должны вручную определить точки ресурсов, которые необходимо ограничить, и настроить соответствующие текущие политики ограничения и другое содержимое.

Сегодня мы вместе научимся пользоваться@SentinelResourceАннотации гибко определяют ресурсы управления и способы настройки стратегий управления.

пользовательская ресурсная точка

Следующие примеры основаны на том факте, что вы уже представили Spring Cloud Alibaba Sentinel.Если вы еще этого не знаете, рекомендуется сначала прочитать их.«Использование Sentinel для реализации ограничения тока интерфейса».

Шаг 1: Добавьте конфигурацию поддержки аннотаций в основной класс приложения:

@SpringBootApplication
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    // 注解支持的配置Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

}

Шаг 2: Используйте там, где вам нужно контролировать трафик через Sentinel@SentinelResourceАннотация, такая как следующая, для управления методом уровня логики службы в качестве примера:

@Slf4j
@Service
public class TestService {

    @SentinelResource(value = "doSomeThing")
    public void doSomeThing(String str) {
        log.info(str);
    }

}

На этом этапе определяется метод, который необходимо защитить. Поговорим о том, как реализовать различные стратегии защиты после определения ресурсных точек, в том числе: текущий лимит, даунгрейд и т. д.

Как реализовать ограничение тока и деградацию предохранителей

После определения точек ресурсов мы можем использовать панель инструментов, чтобы установить текущие ограничения и политики перехода на более ранние версии для защиты точек ресурсов. В то же время также возможно@SentinelResourceчтобы указать стратегию обработки исключений при возникновении текущего ограничения и перехода на более раннюю версию. Далее давайте посмотрим, как реализовано ограничение тока и переход на более раннюю версию.

Реализовать контроль ограничения тока

Шаг 1. Вызовите этот защищенный метод на веб-уровне:


@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/hello")
    public String hello() {
        estService.doSomeThing("hello " + new Date());
        return "didispace.com";
    }

}

Шаг 2: Запустите тестовое приложение и запустите Sentinel-Dashboard. отправить запрос на/helloВ интерфейсе вы можете увидеть несколько контрольных точек, показанных ниже на Sentinel-Dashboard:

Как видите, в дополнение к предыдущему примеру записи есть/helloПомимо ресурсной точки, есть еще однаdoSomeThingресурсная точка. Вы можете установить текущее правило ограничения для этой ресурсной точки через интерфейс, например, установить ее QPS на 2. так как/helloРесурс не имеет текущих ограничивающих правил, поэтому до тех пор, пока запрос/helloинтерфейс, вы можете напрямую имитировать вызовdoSomeThingресурсы, чтобы наблюдать, вступают ли в силу текущие правила ограничения.

Следующее может быть вызвано любым инструментом, который вам нравится/helloДля интерфейса, если количество запросов в секунду превышает 2, появится следующая ошибка, указывающая, что текущая политика ограничения вступает в силу.

В это время консоль сервера также будет иметь соответствующий журнал ошибок ограничения тока:

2019-06-27 11:30:43.514  INFO 36898 --- [nio-8001-exec-3] c.d.a.sentinel.service.TestService       : aaa
2019-06-27 11:30:43.905 ERROR 36898 --- [nio-8001-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause

com.alibaba.csp.sentinel.slots.block.flow.FlowException: null

Реализовать обработку исключений с ограничением тока

По умолчанию ограничивающая ток обработка управляющих ресурсов Sentinel напрямую выдает исключение, которое является содержимым журнала, опубликованным в предыдущем разделе. Это можно сделать, когда нет разумных деловых обязательств или интерфейсной стыковки.Однако в нормальных условиях для улучшения обслуживания пользователей после ограничения тока будет реализована некоторая специальная обработка.Мы не хотим показывать тупой отчет об ошибке . Затем просто выполните некоторую обработку на основе приведенного выше примера, например:

@Slf4j
@Service
public class TestService {

    @SentinelResource(value = "doSomeThing", blockHandler = "exceptionHandler")
    public void doSomeThing(String str) {
        log.info(str);
    }

    // 限流与阻塞处理
    public void exceptionHandler(String str, BlockException ex) {
        log.error( "blockHandler:" + str, ex);
    }
    
}

Делайте в основном две вещи:

  • пройти через@SentinelResourceаннотированныйblockHandlerАтрибуты формулируют конкретные функции обработки
  • Реализовать функцию обработки, параметры функции должны быть такими же, как параметры ресурсной точки, и добавить в концеBlockExceptionПараметры исключения, при этом тип возвращаемого значения должен быть одинаковым.

Читатели, знакомые с Hystrix, обнаружат, что этот дизайн очень похож на определение отката в HystrixCommand, и его легко понять.

После выполнения вышеуказанных изменений попробуйте снова получить доступ к интерфейсу (обратите внимание, что текущие правила ограничения должны быть настроены), тогда внешний интерфейс не будет возвращать информацию об исключении, а задний конец будет печататьexceptionHandlerВывод журнала, определенный в . В практических приложениях, пока текущий запрос на ограничение кэшируется или запросы внешнего интерфейса выполняются в соответствии с потребностями бизнеса, его можно реализовать на основе этого метода.

Понижение предохранителя

@SentinelResourceОбратите внимание, что помимо того, что он используется для управления ограничением тока, он также может реализовывать стратегию понижения рейтинга автоматических выключателей, аналогичную Hystrix. Давайте посмотрим, как его использовать.

Шаг 1: Как и в случае управления ограничением тока, используйте@SentinelResourceАннотации отмечают ресурсные точки, такие как:

@Slf4j
@Service
public class TestService {

    @SentinelResource(value = "doSomeThing2")
    public void doSomeThing2(String str) {
        log.info(str);
        throw new RuntimeException("发生异常");
    }

}

здесь, вTestServiceСоздайте новый метод в классе и используйте@SentinelResourceНазовите ресурс какdoSomeThing2. Этот метод выдает исключение для совместной работы с последующей формулировкой стратегии перехода на более раннюю версию на основе доли исключений (аналогично Hystrix). Sentinel богаче, чем Hystrix, и имеет стратегию деградации, основанную на времени отклика и количестве исключений.

Шаг второй: В веб-слое вызывается этот защищенный метод:

@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @GetMapping("/hello2")
    public String hello2() {
        testService.doSomeThing2("hello2 " + new Date());
        return "didispace.com";
    }

}

Шаг 3: Запустите тестовое приложение и запустите Sentinel-Dashboard. отправить запрос на/hello2интерфейс, так что Sentinel-Dashboard может видеть имяdoSomeThing2ресурсная точка. Затем нажмите кнопку перехода на более раннюю версию, чтобы установить правила перехода на более раннюю версию для ресурса. Здесь используется стратегия соотношения аномалий, соотношение установлено на 0,5 (т.е.: 50% аномалий), а временное окно установлено на 2 (секунды).

Шаг 4: Проверьте переход на более раннюю версию предохранителя в соответствии с приведенной выше конфигурацией политики понижения версии, когдаdoSomeThing2QPS вызова метода составляет >= 5. Если частота исключений превышает 50%, последующий вызов в течение 2 секунд напрямую вызовет предохранитель и переход на более раннюю версию, а значение по умолчанию будет выбрано напрямую.DegradeExceptionисключения, такие как:

2019-06-27 17:49:58.913 ERROR 99863 --- [nio-8001-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.reflect.UndeclaredThrowableException] with root cause

com.alibaba.csp.sentinel.slots.block.degrade.DegradeException: null

Объединенная обработка понижения

Определение обработки автоматических выключателей на более ранней версии в Sentinel очень просто, очень похоже на Hystrix. просто используйте@SentinelResourceаннотированныйfallbackатрибут для указания конкретного имени метода. Также необходимо отметить, что участие и отдача должны быть последовательными. Например:

@Slf4j
@Service
public class TestService {

    // 熔断与降级处理
    @SentinelResource(value = "doSomeThing2", fallback = "fallbackHandler")
    public void doSomeThing2(String str) {
        log.info(str);
        throw new RuntimeException("发生异常");
    }

    public void fallbackHandler(String str) {
        log.error("fallbackHandler:" + str);
    }
}

После завершения вышеуказанного преобразования перезапустите приложение и установитеdoSomeThing2Стратегия понижения уровня автоматического выключателя для ресурсов (с использованием процента исключений), затем частые запросы/hello2интерфейс. После QPS>=5, поскольку этот интерфейс выдавал исключения, должно быть выполнено условие перехода на более раннюю версию предохранителя, и оно будет выполнено в это время.fallbackHandlerМетод, постоянно печатающий следующим образом:

2019-06-27 23:44:19.432 ERROR 58471 --- [nio-8001-exec-1] c.d.a.sentinel.service.TestService       : fallbackHandler:hello2 Thu Jun 27 23:44:19 CST 2019
2019-06-27 23:44:19.599 ERROR 58471 --- [nio-8001-exec-2] c.d.a.sentinel.service.TestService       : fallbackHandler:hello2 Thu Jun 27 23:44:19 CST 2019
2019-06-27 23:44:19.791 ERROR 58471 --- [nio-8001-exec-3] c.d.a.sentinel.service.TestService       : fallbackHandler:hello2 Thu Jun 27 23:44:19 CST 2019
2019-06-27 23:44:19.975 ERROR 58471 --- [nio-8001-exec-4] c.d.a.sentinel.service.TestService       : fallbackHandler:hello2 Thu Jun 27 23:44:19 CST 2019
2019-06-27 23:44:20.168 ERROR 58471 --- [nio-8001-exec-5] c.d.a.sentinel.service.TestService       : fallbackHandler:hello2 Thu Jun 27 23:44:20 CST 2019

Дополнительные описания атрибутов аннотаций

о@SentinelResourceБыли введены два основных использования аннотаций: конкретные случаи использования контроля ограничения тока и деградации предохранителей. Кроме того, эта аннотация имеет некоторые другие более точные настройки, такие как игнорирование некоторых конфигураций исключений, функции понижения версии по умолчанию и т. д., которые можно увидеть в следующих инструкциях:

  • value: имя ресурса, обязательное (не может быть пустым)
  • entryType: тип записи, необязательный (по умолчаниюEntryType.OUT)
  • blockHandler / blockHandlerClass: blockHandlerОбработка корреспонденцииBlockExceptionИмя функции, необязательно. Область доступа к функции blockHandler должна бытьpublic, тип возвращаемого значения должен соответствовать исходному методу, тип параметра должен соответствовать исходному методу, а в конце добавляется дополнительный параметр, типBlockException. Функция blockHandler должна быть в том же классе, что и исходный метод по умолчанию. Если вы хотите использовать функции других классов, вы можете указатьblockHandlerClassдля соответствующего классаClassОбъект, обратите внимание, что соответствующая функция должна быть статической функцией, иначе она не может быть разрешена.
  • fallback: Имя резервной функции, необязательная, используемая для обеспечения логики резервной обработки при возникновении исключения. Резервную функцию можно использовать для всех типов исключений (кромеexceptionsToIgnoreНаизнанку вынуть необычный вид) для обработки. Требования к сигнатуре и расположению резервной функции:
    • Тип возвращаемого значения должен совпадать с типом возвращаемого значения исходной функции;
    • Список параметров метода должен быть таким же, как и исходная функция, или вы можете добавить еще одинThrowableПараметр типа используется для получения соответствующего исключения.
    • Резервная функция должна быть в том же классе, что и исходный метод по умолчанию. Если вы хотите использовать функции других классов, вы можете указатьfallbackClassдля соответствующего классаClassОбъект, обратите внимание, что соответствующая функция должна быть статической функцией, иначе она не может быть разрешена.
  • defaultFallback(начиная с версии 1.6.0): Имя резервной функции по умолчанию, необязательное, обычно используется для общей логики резервного копирования (т. е. может использоваться для многих служб или методов). Резервную функцию по умолчанию можно использовать для всех типов исключений (кромеexceptionsToIgnoreИсключенные в нем типы исключений) обрабатываются. Если настроены и резервный вариант, и defaultFallback, вступит в силу только резервный вариант. Сигнатура функции defaultFallback требует:
    • Тип возвращаемого значения должен совпадать с типом возвращаемого значения исходной функции;
    • Список параметров метода должен быть пустым, либо может быть дополнительныйThrowableПараметр типа используется для получения соответствующего исключения.
    • Функция defaultFallback по умолчанию должна находиться в том же классе, что и исходный метод. Если вы хотите использовать функции других классов, вы можете указатьfallbackClassдля соответствующего классаClassОбъект, обратите внимание, что соответствующая функция должна быть статической функцией, иначе она не может быть разрешена.
  • exceptionsToIgnore(начиная с версии 1.6.0): используется для указания исключений, которые не будут учитываться в статистике исключений и не попадут в резервную логику, а будут выброшены как есть.

Примечание. Резервная функция в версиях до 1.6.0 предназначена только для исключений перехода на более раннюю версию (DegradeException) обрабатывать,Не удается обработать бизнес-исключения.

В частности, если сконфигурированы и blockHandler, и резервный вариант, они будут деградированы из-за ограничения тока и выброшены.BlockExceptionвойдет толькоblockHandlerлогика обработки. Если не настроенblockHandler,fallbackиdefaultFallback, когда текущий предел понижен,BlockException бросить прямо.

использованная литература:Официальная документация Sentinel

Выходные данные: эта статья основана на версии 0.2.2 spring-cloud-alibaba-dependencies.Если у вас возникнут особые проблемы, проверьте, согласуются ли версии, или непосредственно обратитесь к примерам кода, чтобы проверить конкретные случаи.

пример кода

Клиентский код контента, представленный в этой статье, читатели примера могут проверить код на следующем складе.alibaba-sentinel-annotationпроект:

Если вы заинтересованы в них, добро пожаловать, пометьте, подпишитесь, добавьте в избранное и вперед, чтобы поддержать!