Введение: В предыдущих главах мы ограничили ток на уровне микросервиса и интегрировали Spring Cloud Gateway, Основное содержание этой главы — перенести текущую функцию ограничения с микросервиса на уровень шлюза.
Собственное ограничение тока SpringCloud Gateway
Собственное ограничение тока Springcloud Gateway в основном реализовано на основе фильтров, и мы можем напрямую использовать встроенные фильтры.RequestRateLimiterGatewayFilterFactory
,В настоящее времяRequestRateLimiterGatewayFilterFactory
реализация зависит отRedis
, так что мы также вводимspring-boot-starter-data-redis-reactive
.
POM-зависимости
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifatId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
Конфигурация ограничения тока
spring:
cloud:
gateway:
routes:
- id: account-service
uri: lb://account-service
order: 10000
predicates:
- Path=/account-service/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 3
key-resolver: "#{@ipKeyResolver}"
В основном настройте три основных параметра:
- redis-rate-limiter.replenishRate :
Сколько запросов пользователю разрешено обрабатывать в секунду - redis-rate-limiter.burstCapacity :
Емкость корзины токенов, максимальное количество запросов, разрешенных для выполнения за одну секунду. - key-resolver :
Имя объекта bean-компонента синтаксического анализатора для регулирования ключей. Он использует выражения SpEL для получения объектов bean-компонентов из контейнера Spring на основе #{@beanName}.
Настроить бины
/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
Sentinel регулирование
Мы говорили об использовании Sentinel в предыдущих главах.Если вам непонятно, вы можете прочитать предыдущие главы.Здесь мы в основном говорим об интеграции со шлюзом SpringCloud.
Начиная с версии 1.6.0, Sentinel предоставляет модуль адаптации для Spring Cloud Gateway, который может обеспечить текущее ограничение в двух измерениях ресурсов:
- измерение маршрута: то есть запись маршрута, настроенная в файле конфигурации Spring, имя ресурса является соответствующей настройкой routeId
- Параметр API: пользователи могут использовать API, предоставляемый Sentinel, для настройки некоторых групп API.
Ниже приведены наши шаги по интеграции
POM-зависимости
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
Поскольку nacos необходимо использовать в качестве центра конфигурации Sentinel, он также вводитсяsentinel-datasource-nacos
Начальная конфигурация
...
spring:
cloud:
sentinel:
transport:
dashboard: 10.0.10.48:8858
eager: true
datasource:
ds:
nacos:
server-addr: 10.0.10.48:8848
data-id: gateway-sentinel-flow
group-id: DEFAULT_GROUP
rule-type: gw-flow
...
Вот в основном соответствующая конфигурация часового, полученная из центра конфигурации nacos.gateway-sentinel-flow
В файле конфигурации текущим типом ограничения является тип шлюза gw-flow.
Конфигурация ограничения тока
Создано на общедоступной странице управления конфигурацией nacosdata-id
дляgateway-sentinel-flow
конфигурационный файл (формат json), дающийaccount-service
а такжеproduct-service
Добавьте правила регулирования.
[
{
"resource": "account-service",
"count": 5,
"grade": 1,
"paramItem": {
"parseStrategy": 0
}
},
{
"resource": "product-service",
"count": 2,
"grade": 1,
"paramItem": {
"parseStrategy": 0
}
}
]
После завершения настройки запустите проект шлюза, войдите в консоль Sentinel и просмотрите текущие правила ограничения:
Инструкции по настройке:
以客户端IP作为限流因子
public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
以客户端HOST作为限流因子
public static final int PARAM_PARSE_STRATEGY_HOST = 1;
以客户端HEADER参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
以客户端请求参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
以客户端请求Cookie作为限流因子
public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;
Тест ограничения тока
Множественный доступ через шлюзaccount-service
Сервисный тестhttp://localhost:8090/account/getByCode/javadaily
Проверьте эффект ограничения тока:
Исключение пользовательского ответа
Логика реализации по умолчанию исключения текущего ограничения шлюза SpringCloud:SentinelGatewayBlockExceptionHandler
, вы можете просмотреть исходный код, чтобы найти ключевой код ненормального ответа следующим образом.
Поскольку серверная часть службы возвращает формат ответа JSON, нам нужно изменить исходный ответ об исключении и изменить его наResultData
Формат ответа класса. Чтобы реализовать эту функцию, вам нужно только написать новый обработчик исключений и внедрить новый обработчик исключений в класс конфигурации SpringCloud GateWay.
- собственный обработчик исключений
CustomGatewayBlockExceptionHandler
public class CustomGatewayBlockExceptionHandler implements WebExceptionHandler {
...
/**
* 重写限流响应,改造成JSON格式的响应数据
* @author javadaily
* @date 2020/1/20 15:03
*/
private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
ServerHttpResponse serverHttpResponse = exchange.getResponse();
serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
ResultData<Object> resultData = ResultData.fail(ReturnCode.RC200.getCode(), ReturnCode.RC200.getMessage());
String resultString = JSON.toJSONString(resultData);
DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(resultString.getBytes());
return serverHttpResponse.writeWith(Mono.just(buffer));
}
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
if (exchange.getResponse().isCommitted()) {
return Mono.error(ex);
} else {
return !BlockException.isBlockException(ex) ? Mono.error(ex) : this.handleBlockedRequest(exchange, ex).flatMap((response) -> this.writeResponse(response, exchange));
}
}
...
}
Вы можете напрямую скопироватьSentinelGatewayBlockExceptionHandler
класс, а затем изменитьwriteResponse
интерфейс метода
- Измените класс конфигурации шлюза и внедрите
CustomGatewayBlockExceptionHandler
@Configuration
public class GatewayConfiguration {
...
/**
* 注入自定义网关异常
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CustomGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the custom block exception handler .
return new CustomGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
...
}
- Добавьте конфигурацию в файл bootstrap.yml
spring:
main:
allow-bean-definition-overriding: true
- Повторный тест, текущие результаты ограничения ответа следующие
{
"message": "服务开启限流保护,请稍后再试!",
"status": 200,
"success": false,
"timestamp": 1579509123946
}
Ограничение тока не вступает в силу
Если вы обнаружите, что текущее ограничение уровня шлюза не действует во время использования, вы можете запустить службу шлюза в режиме отладки, а затем отфильтровать шлюз.SentinelGatewayFilter
Чтобы отладить метод фильтрации в , я обнаружил, что идентификатор шлюза, полученный дозорным, не соответствует тому, что мы настроили.account-service
, но добавилCompositeDiscoveryClient_
префикс, как показано на следующем рисунке:
Итак, нам нужно изменитьgateway-sentinel-flow
Конфигурация нашего ресурса также префиксная, измененная конфигурация выглядит следующим образом:
[{
"resource": "CompositeDiscoveryClient_account-service",
"count": 5,
"grade": 1,
"paramItem": {
"parseStrategy": 0
}
}, {
"resource": "CompositeDiscoveryClient_product-service",
"count": 2,
"grade": 1,
"paramItem": {
"parseStrategy": 0
}
}]
При использовании jemter для тестирования интерфейса обнаружено, что шлюз может нормально ограничивать ток.
После вышеуказанных шагов мы можем удалить текущую ограничивающую конфигурацию внутреннего уровня микросервиса и позволить уровню шлюза взять на себя текущую ограничивающую функцию.
Ну что, друзья мои, содержание этого выпуска здесь полностью. Вы же видите, что здесь одноклассники все отличники. Следующее повышение и прибавка к зарплате будете у вас! Если вы считаете, что эта статья полезна для вас, отсканируйте приведенный ниже QR-код, чтобы добавить подписку.
«Ретвитнуть» плюс «просмотреть», чтобы выработать полезную привычку! Увидимся в следующий раз!
Серия статей SpringCloud Alibaba