предисловие
С ростом популярности микросервисов стабильность между сервисами и сервисами становится все более важной. Sentinel использует трафик в качестве точки входа для защиты стабильности сервисов от нескольких измерений, таких как управление трафиком, переход на более раннюю версию автоматического выключателя и защита системной нагрузки.
Sentinel обладает следующими характеристиками:
-
Разнообразные сценарии приложений: за последние 10 лет Sentinel реализовал основные сценарии Double Eleven от Alibaba, такие как всплески (т. кластерный контроль трафика, предохранители в реальном времени, нисходящие недоступные приложения и т. д.
-
Полный мониторинг в реальном времени: Sentinel также предоставляет функции мониторинга в реальном времени. В консоли можно увидеть данные второго уровня отдельной машины, подключенной к приложению, и даже агрегированную работу кластера с масштабом менее 500.
-
Обширная экосистема с открытым исходным кодом: Sentinel предоставляет готовые модули интеграции с другими платформами/библиотеками с открытым исходным кодом, такие как интеграция с Spring Cloud, Dubbo, gRPC. Вам нужно только ввести соответствующие зависимости и выполнить простую настройку, чтобы быстро получить доступ к Sentinel.
-
Полные точки расширения SPI: Sentinel предоставляет простые в использовании и полные интерфейсы расширения SPI. Вы можете быстро настроить логику, реализовав интерфейсы расширения. Например, управление пользовательскими правилами, адаптация источников динамических данных и т. д.
Приведенный выше контент взят из официального представления Sentinel. В этой статье автор изучит использование Sentinel с точки зрения практического применения.
1. Первое знакомство со Sentinel
Во-первых, нам нужно импортировать зависимости Sentinel.
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.2</version>
</dependency>
Sentinel поддерживает следующие правила: правила управления потоком, правила перехода на более раннюю версию автоматического выключателя, правила защиты системы, правила управления доступом к источнику и правила параметров точки доступа.
Здесь давайте покажем пример управления потоком и деградации автоматического выключателя.
1. Управление потоком
Принцип управления потоком заключается в отслеживании таких показателей, как количество запросов в секунду или количество одновременных потоков трафика приложений.При достижении указанного порога трафик контролируется, чтобы избежать переполнения мгновенным пиком трафика, тем самым обеспечивая высокую доступность применение.
Давайте возьмем QPS в качестве примера, чтобы сначала определить его правила См. комментарии для значения связанных атрибутов.
/**
* 加载限流规则
* @param resource
*/
public static void loadFlowRules(String resource){
FlowRule rule = new FlowRule();
//资源名称,可以是任意字符串
rule.setResource(resource);
//限流阈值
rule.setCount(5);
//限流阈值类型,设置为QPS。即每秒QPS大于5时,触发限流
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//针对的调用来源
rule.setLimitApp("default");
//调用关系限流策略,默认按照资源本身
rule.setStrategy(RuleConstant.STRATEGY_DIRECT);
//限流效果,默认直接拒绝
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
//是否集群限流
rule.setClusterMode(false);
FlowRuleManager.loadRules(Collections.singletonList(rule));
}
Как показано в приведенном выше коде, когда количество запросов в секунду достигает 5, последующие запросы в текущем временном окне будут напрямую отклонены.
Далее мы используем Sentinel API для кода, который должен управлять трафиком.SphU.entry("resource") 和 entry.exit()Просто окружите его.
public static void main(String[] args) throws InterruptedException {
loadFlowRules("orderService");
while (!stop){
count.incrementAndGet();
Entry entry = null;
try {
entry = SphU.entry(resource);
logger.info("业务操作...{}",count.get());
} catch (BlockException e) {
logger.error("请求被限流...{}",count.get());
Thread.sleep(1000);
} finally {
if (entry != null) {
entry.exit();
}
if (count.get()>=20){
stop = true;
}
}
}
}
Как и в приведенном выше коде, мы сначала передаемloadFlowRules()метод для загрузки текущих ограничивающих правил. Затем окружите бизнес-операции Sentinel API.
Текущий предельный порог, который мы определили, равен 5, и здесь всего 20 запросов. После запуска дросселирования наш поток приостанавливается на 1 секунду, чтобы пройти текущее временное окно, поэтому будет 3 запроса, которые будут дросселированы.
Запустив код, мы можем получить следующие результаты:
14:38:00.463 - 业务操作...1
14:38:00.465 - 业务操作...2
14:38:00.465 - 业务操作...3
14:38:00.465 - 业务操作...4
14:38:00.465 - 业务操作...5
14:38:00.494 - 请求被限流...6
14:38:01.494 - 业务操作...7
14:38:01.494 - 业务操作...8
14:38:01.495 - 业务操作...9
14:38:01.495 - 业务操作...10
14:38:01.495 - 业务操作...11
14:38:01.496 - 请求被限流...12
14:38:02.497 - 业务操作...13
14:38:02.497 - 业务操作...14
14:38:02.497 - 业务操作...15
14:38:02.497 - 业务操作...16
14:38:02.497 - 业务操作...17
14:38:02.497 - 请求被限流...18
14:38:03.498 - 业务操作...19
14:38:03.498 - 业务操作...20
2. Фьюзинг
Помимо управления потоком, слияние и понижение версии нестабильных ресурсов в вызывающем канале также является одной из важных мер по обеспечению высокой доступности.
Понижение предохранителя Sentinel ограничит вызов этого ресурса, когда ресурс в ссылке вызова находится в нестабильном состоянии (например, время ожидания вызова или ненормальное увеличение коэффициента), так что запрос быстро завершается ошибкой и не влияет на другие ресурсы.Ошибка подключения.
Так как же измерить стабильность ресурсов?
Sentinel предоставляет три метода: среднее время отклика, коэффициент аномалий и количество аномалий.
Давайте возьмем в качестве примера среднее время отклика и сначала определим его правила.
/**
* 1秒内的5个请求,平均响应时间大于10ms,接下来的3秒内都会自动熔断。
* @param resourceName
*/
public static void loadDegradeRule(String resourceName){
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
//资源名称
rule.setResource(resourceName);
//阈值 - 10ms
rule.setCount(10);
//熔断策略 - RT模式
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
//时间窗口 - 3s
rule.setTimeWindow(3);
//RT模式下,1秒内连续多少个请求的平均RT超出阈值,才可以触发熔断
rule.setRtSlowRequestAmount(5);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
Как показано в приведенном выше коде, мы определяем правила слияния, смотрим комментарии для значения атрибутов, а затем смотрим на тестовые примеры.
public static void main(String[] args)throws InterruptedException {
loadDegradeRule(resource);
while (!stop){
count.incrementAndGet();
Entry entry = null;
try {
entry = SphU.entry(resource);
logger.info("业务操作...{}",count.get());
Thread.sleep(15);
} catch (BlockException e) {
if (e instanceof DegradeException){
logger.error("触发熔断机制...{}",count.get());
Thread.sleep(500);
}
} finally {
if (entry != null) {
entry.exit();
}
if (count.get()>=20){
stop = true;
}
}
}
logger.info("----------------------------");
}
В приведенном выше коде у нас всего 20 запросов. Мы остановили поток на 15 мс, чтобы среднее значение RT превысило пороговое значение, превышающее 10 мс.
Правила, которые мы определяем,1秒内连续5个请求的平均RT超出阈值,就可以触发熔断, поэтому при поступлении 6-го запроса сработает автоматический выключатель.
Как долго работает предохранитель? Как раз в 3-секундном временном окне.
В приведенном выше тестовом коде после срабатывания автоматического выключателя мы вручную приостанавливаем поток на 1000 мс, поэтому для каждого автоматического выключателя будет 3 запроса.
Так ли это, давайте запустим код и посмотрим результат:
10:56:20.022 [main] INFO orderService - 业务操作...1
10:56:20.040 [main] INFO orderService - 业务操作...2
10:56:20.056 [main] INFO orderService - 业务操作...3
10:56:20.072 [main] INFO orderService - 业务操作...4
10:56:20.088 [main] INFO orderService - 业务操作...5
10:56:20.127 [main] ERROR orderService - 触发熔断机制...6
10:56:21.128 [main] ERROR orderService - 触发熔断机制...7
10:56:22.128 [main] ERROR orderService - 触发熔断机制...8
10:56:23.129 [main] INFO orderService - 业务操作...9
10:56:23.145 [main] INFO orderService - 业务操作...10
10:56:23.160 [main] INFO orderService - 业务操作...11
10:56:23.176 [main] INFO orderService - 业务操作...12
10:56:23.192 [main] INFO orderService - 业务操作...13
10:56:23.207 [main] ERROR orderService - 触发熔断机制...14
10:56:24.208 [main] ERROR orderService - 触发熔断机制...15
10:56:25.208 [main] ERROR orderService - 触发熔断机制...16
10:56:26.209 [main] INFO orderService - 业务操作...17
10:56:26.224 [main] INFO orderService - 业务操作...18
10:56:26.240 [main] INFO orderService - 业务操作...19
10:56:26.255 [main] INFO orderService - 业务操作...20
10:56:26.271 [main] INFO orderService - ----------------------------
На данный момент мы можем сказать, что Sentinel работает нормально.
2. Системная интеграция
Вышеприведенный пример — очень простой демонстрационный пример. Если мы хотим использовать Sentinel в нашем проекте SpringBoot, потребуется некоторая работа.
1. Консоль Sentinel
Sentinel предоставляет облегченную консоль с открытым исходным кодом, разработанную с использованием SpringBoot.
Он обеспечивает обнаружение компьютеров и управление их работоспособностью, мониторинг (отдельных компьютеров и кластеров), управление правилами и функции push-уведомлений.
Итак, давайте сначала запустим эту консоль.
Первый шаг требуетhttps://github.com/alibaba/Sentinel/releasesС этого адреса загрузите последнюю версию пакета jar консоли.
Второй шаг, используйте команду для запуска консольной программы, где-Dserver.port=9080Используется для указания порта консоли Sentinel.
java -Dserver.port=9080 -Dcsp.sentinel.dashboard.server=localhost:9080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
На третьем этапе наша бизнес-система представляет модуль Transport для связи с консолью Sentinel.
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.2</version>
</dependency>
Четвертый шаг, в нашей бизнес-системе, установите параметры запуска JVM, чтобы указать адрес консоли Sentinel.
-Dcsp.sentinel.dashboard.server=127.0.0.1:9080
Наконец, запустите нашу бизнес-систему, затем откройте консоль Sentinel, если вы видите список машин, все.
2. Определите правила
Перед определением правил нам необходимо спланировать объем ресурсов.
Что это обозначает? Например, если мы возьмем в качестве примера бизнес-заказ, все ли операции с заказами считаются ресурсом? Или разделите его, создание заказа считается одним ресурсом, а запрос заказа считается другим ресурсом.
Поэтому мы можем сначала определить имя ресурса, потоком которого мы хотим управлять.
public final class ResourceConstants {
public static final String ORDER_SERVICE = OrderService.class.getName();
public static final String ORDER_SERVICE_ORDERS = ORDER_SERVICE+".orders";
public static final String ORDER_SERVICE_CREATE = ORDER_SERVICE+".create";
}
Поскольку это проект SpringBoot, мы можем загружать правила управления потоком при запуске системы.
@Component
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
initFlowRule(ResourceConstants.ORDER_SERVICE,5);
initFlowRule(ResourceConstants.ORDER_SERVICE_ORDERS,5);
}
public void initFlowRule(String resourceName,int count) {
FlowRule flowRule = new FlowRule(resourceName)
.setCount(count)
.setGrade(RuleConstant.FLOW_GRADE_QPS);
List<FlowRule> list = new ArrayList<>();
list.add(flowRule);
FlowRuleManager.loadRules(list);
}
}
Затем мы добавляем код Sentinel в контроллер, чтобы добиться эффекта управления потоком.
@RequestMapping("/getOrders")
public ResponseEntity getOrders(){
Entry entry = null;
try {
entry = SphU.entry(ResourceConstants.ORDER_SERVICE_ORDERS);
return ResponseEntity.ok(orderService.orders());
} catch (BlockException e) {
logger.error("请求被限流...{}",e.getRule().getResource());
return ResponseEntity.badRequest().body(e.getRule());
} finally {
if (entry != null) {
entry.exit();
}
}
}
Теперь давайте проверим его с помощью JMeter и запустим 10 потоков для запроса этого интерфейса. Только 5 запросов будут переданы и 5 запросов будут отклонены.
Пока что мы можем просто использовать Sentinel в проекте SpringBoot, но на данный момент есть две очевидные проблемы.
- Везде, где требуется управление потоком, слишком навязчиво и неудобно, чтобы его жестко запрограммировали через API;
- Правила управления потоком хранятся только в памяти и исчезают после перезапуска системы, а постоянные данные правил отсутствуют.
Далее решаем две вышеуказанные задачи.
3. Адаптация кадра
Благодаря обширной экосистеме с открытым исходным кодом Sentinel предоставляет готовые модули интеграции с другими платформами/библиотеками с открытым исходным кодом. Нам нужно только ввести соответствующие зависимости и выполнить простую настройку для быстрого доступа к Sentinel.
Мы надеемся, что сможем контролировать поток веб-запросов, поэтому нам нужно ввести Sentinel, чтобы обеспечить интеграцию с Servlet.
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
<version>1.7.2</version>
</dependency>
1. Конфигурация фильтра
Поскольку это приложение SpringBoot, мы настраиваем его через Configuration.
@Configuration
public class SentinelFilterConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
registration.setName("sentinelFilter");
registration.setOrder(1);
return registration;
}
}
В нашем собственном бизнес-коде часть Sentinel API может быть опущена.
@RequestMapping("/getOrders")
public ResponseEntity getOrders(){
return ResponseEntity.ok(orderService.orders());
}
При условии, что правила управления потоком остаются неизменными, мы используем JMeter для запуска 10 потоков для запроса этого интерфейса. То же самое будет передавать только 5 запросов и отклонять 5 запросов.
2. Обработчик блоков URL
По умолчанию страница приглашения по умолчанию будет возвращена при регулировании запроса.
Мы можем вызвать код WebServletConfig.setBlockPage(blockPage)Метод устанавливает настраиваемый URL-адрес перехода, и когда запрос ограничен, он автоматически переходит на заданный URL-адрес.
Если мы не планируем позволять ему переходить на страницу, мы также можем реализовать интерфейс UrlBlockHandler и написать собственную логику обработки ограничения тока.
Например, как показано ниже, после текущего ограничения или предохранителя клиенту будет возвращен неправильный код состояния HTTP и информация о подсказке.
public class SentinelUrlBlockHandler implements UrlBlockHandler {
public static final String flowMsg = "触发流控机制~";
public static final String degradeMsg = "触发熔断机制~";
Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex){
logger.error("熔断限流...{}",ex.getRule());
response.setCharacterEncoding("UTF-8");
response.setStatus(HttpStatus.BAD_REQUEST.value());
PrintWriter out = response.getWriter();
if (ex instanceof FlowException){
out.print(flowMsg);
}else if (ex instanceof DegradeException){
out.print(degradeMsg);
}
out.flush();
out.close();
}
}
Затем зарегистрируйте его в WebCallbackManager.
WebCallbackManager.setUrlBlockHandler(new SentinelUrlBlockHandler());
3. Уборщик URL
Sentinel Web Filter будет рассматривать каждый входящий URL-адрес как отдельный ресурс.
Например, в бизнесе заказов создание заказа, запрос заказа, удаление заказа и т. д. из-за разных URL-адресов будут рассматриваться как разные ресурсы.
Если мы хотим отнести эти операции к ресурсу заказа/order/*, вам нужно реализовать интерфейс UrlCleaner для очистки ресурсов.
Например, классифицируйте ресурсы следующим образом. Например/order/getOrders和/order/createOrder, станет/order/*.
public class SentinelUrlClean implements UrlCleaner {
@Override
public String clean(String originUrl) {
if (originUrl == null || originUrl.isEmpty()) {
return originUrl;
}
int lastSlashIndex = originUrl.lastIndexOf("/");
if (lastSlashIndex >= 0) {
originUrl = originUrl.substring(0, lastSlashIndex) + "/*";
}
return originUrl;
}
}
Затем зарегистрируйте его в WebCallbackManager.
WebCallbackManager.setUrlCleaner(new SentinelUrlClean());
В то время он был более абсолютным, если вся система использует ресурс, то здесь можно вернуть только фиксированный url.
4. Лучшие практики
Как мы упоминали выше, текущие данные правил Sentinel хранятся только в памяти, нет возможности централизованно управлять и продвигать правила, и они не доступны в производственной среде.
Как правило, существует три способа управления и продвижения правил.
- необработанный режим
Передайте правила клиенту и обновите их непосредственно в памяти. Он исчезает после перезапуска и не рекомендуется для использования в производственной среде.
- Режим вытягивания
Клиент активно опрашивает и извлекает правила из центра управления правилами, который может быть СУБД, файлами и т. д. Работа в режиме реального времени не гарантируется, а слишком частое извлечение может вызвать проблемы с производительностью.
- Push-режим
Центр правил передается унифицированным образом, и клиент постоянно отслеживает изменения, регистрируя слушателей, например, используя центры конфигурации, такие как Nacos и Zookeeper, которые лучше работают в режиме реального времени и обеспечивают согласованность. Источник данных в режиме push обычно используется в производственной среде.
В производственной среде обычно чаще используется источник данных в режиме принудительной отправки. Для источников данных в режиме отправки, таких как удаленные центры конфигурации (ZooKeeper, Nacos, Apollo и т. д.), операция отправки не должна выполняться клиентом Sentinel, а должна управляться консолью и передаваться напрямую. отвечает только за получение. Конфигурация, переданная центром конфигурации, обновляется до локальной. Таким образом, правильный способ передачи правил должен быть ** Консоль Configuration Center / Консоль Sentinel → Центр конфигурации → Источники данных Sentinel → Sentinel **, а не отправка в Центр конфигурации через источники данных Sentinel.
Далее реализуем унифицированное управление данными центром конфигурации Nacos.
1. Запустите Нако
В этой статье больше нечего сказать о Nacos, просто скачайте стартап.
2. Введите зависимости
NacosDataSource, предоставленный официальным лицом, мы можем ввести соответствующие зависимости.
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-extension</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.2</version>
</dependency>
3. Считайте данные правила из источника данных
При инициализации NacosDataSource нам нужно указать адрес сервиса, groupId и dataId Nacos.
Затем подключите Nacos на основе этой информации, чтобы прочитать данные внутри. И зарегистрируйте прослушиватель, чтобы уведомлять клиента, когда данные правила в центре конфигурации Nacos изменяются.
Это может показаться сложным, но при использовании в качестве клиента на самом деле это относительно просто. Делаем класс и подключаем его.
@Component
public class DataSourceRuleManager {
private static final String remoteAddress = "localhost:8848";
private static final String groupId = "sentinel.group";
private static final String flowDataId = "flow.rule";
@PostConstruct
public void loadFlowRules() {
FlowConverter converter = new FlowConverter();
//连接Nacos,读取配置信息并通过converter将内容转换为对象
ReadableDataSource<String, List<FlowRule>> flowRuleDataSource =
new NacosDataSource<>(remoteAddress,groupId,flowDataId,converter);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
}
//转换器 从Nacos配置中心读取到的数据转换为对象
public class FlowConverter implements Converter {
@Override
public Object convert(Object source) {
return JSON.parseArray(source.toString(),FlowRule.class);
}
}
}
После завершения настройки мы можем запустить бизнес-систему.
4. Добавьте данные правил из центра конфигурации Nacos.
Теперь вы можете добавлять данные правил в центр конфигурации через консоль Nacos.
Следует отметить, что поскольку наш преобразователь анализирует объект массива типа FlowRule через JSON, формат и имя атрибута в содержимом конфигурации должны совпадать, иначе парсинг не будет выполнен.
Расширяя способ чтения источника данных, когда мы публикуем новый контент в центре конфигурации Nacos, соответствующие правила в нашей бизнес-системе также будут обновляться, и правила в консоли Sentinel также будут обновляться синхронно, реализуя унификацию центр правил. Нажимайте и упорствуйте.
Другой способ - напрямую пройтиКонсоль Sentinel → Центр конфигурации, в этом случае нужно дорабатывать реализацию дашборда.Хотя процесс не сложный, он сложнее.Из-за ограниченного места в этой статье повторять их не буду. Заинтересованные друзья могут оставить сообщение для общения~
Суммировать
В этой статье кратко рассказывается об использовании Sentinel, предохранителя и компонента ограничения тока в распределенных системах. Для достижения базовой доступности производственной среды включены интеграция Sentinel и Servlet, а также унифицированная отправка и постоянство центра правил.
Эта статья является лишь небольшой частью экологии Sentinel.Дополнительный контент, такой как управление потоком и механизм прерывателя цепи различных стратегий, управление черным и белым списками, адаптация фреймворка, принцип реализации и т. д., будет опубликован позже, когда будет время~
Нелегко быть оригинальным, это понравится приглашенным официальным лицам перед отъездом.Это будет движущей силой для автора продолжать писать~