При перепечатке просьба указывать источник:www.fangzhipeng.comЭта статья взята изБлог Фан Чжипэна
В статье подробно описан Gateway Predict, Predict определяется после запроса, перед обработкой маршрута, необходимо пройти "pre" типы фильтров, которые обрабатывают обработку маршрутизации, процесс возвращает ответ, тип "post" фильтра обработка.
Роль и жизненный цикл фильтра
С точки рабочего процесса фильтра мы можем знать, что фильтр играет очень важную роль.В фильтре «предварительного» типа вы можете выполнять проверку параметров, проверку разрешений, мониторинг трафика, вывод журнала, преобразование протокола и т. д. в « post" тип фильтрации Содержание ответа, модификация заголовка ответа, вывод журнала, мониторинг трафика и т. д. могут быть выполнены на сервере. Прежде всего, нам нужно выяснить, зачем нужен уровень шлюза, что должно сказать о роли фильтра.
эффект
Когда у нас есть много сервисов, таких как сервис пользователя, сервис товаров, сервис продаж и другие сервисы на рисунке ниже, когда клиент запрашивает API каждого сервиса, каждый сервис должен делать одни и те же вещи, такие как аутентификация, Ограничение тока, вывод журнала и т. д.
Есть ли способ улучшить такую повторяющуюся работу? Ответ — да. Добавьте глобальный контроль разрешений, текущее ограничение, службу Api Gateway вывода журнала на верхний уровень микрослужбы, а затем перенаправьте запрос на конкретный уровень бизнес-службы. Эта служба Api Gateway действует как граница службы.Внешние запросы на доступ к системе должны сначала пройти через уровень шлюза.
жизненный цикл
Spring Cloud Gateway похож на zuul и имеет два типа фильтров: «pre» и «post». Запрос клиента сначала проходит через фильтр типа "pre", а затем перенаправляет запрос в конкретную бизнес-службу, такую как user-service на рисунке выше. После получения ответа от бизнес-службы он обрабатывается " post" и, наконец, вернуть ответ клиенту.
В отличии от zuul, помимо фильтров, которые делятся на "pre" и "post", в Spring Cloud Gateway фильтры можно разделить еще на два типа по сфере действия. Один - шлюз для одного маршрута. , который аналогичен предсказателю в файле конфигурации, а другой — глобальный фильтр шлюза для всех маршрутов. Теперь объясните эти два фильтра с точки зрения разделения сферы.
gateway filter
Фильтры позволяют каким-либо образом модифицировать входящие HTTP-запросы или исходящие HTTP-ответы. Фильтры могут быть ограничены определенными путями запросов. Spring Cloud Gateway включает ряд встроенных фабрик GatewayFilter.
Фабрика GatewayFilter аналогична фабрике Predicate, представленной в предыдущей статье. Она настраивается в файле конфигурации application.yml. Она соответствует идее соглашения о конфигурации. Вам нужно только настроить имя фабрики GatewayFilter в файл конфигурации без записи всех имен классов.Например, AddRequestHeaderGatewayFilterFactory нужно написать только AddRequestHeader в файле конфигурации, а не все имена классов. Фабрика GatewayFilter, настроенная в файле конфигурации, в конечном итоге будет обрабатываться соответствующим классом фабрики фильтров.
Список встроенных фабрик фильтров в Spring Cloud Gateway выглядит следующим образом:
Теперь выберите несколько распространенных фабрик фильтров для объяснения. Каждая фабрика фильтров содержит подробные примеры использования в официальной документации. Если вам непонятно, вы также можете увидеть каждую фабрику фильтров на org.springframework.cloud.gateway.filter.factory Исходный код завода фильтров.
AddRequestHeader GatewayFilter Factory
Создайте проект и введите соответствующие зависимости, в том числе Spring Boot версии 2.0.5, Spring Cloud версию Finchley и зависимости от шлюза:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
В файле конфигурации проекта добавьте следующую конфигурацию:
server:
port: 8081
spring:
profiles:
active: add_request_header_route
---
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://httpbin.org:80/get
filters:
- AddRequestHeader=X-Request-Foo, Bar
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
profiles: add_request_header_route
В приведенной выше конфигурации запуск порта проекта составляет 8081, а файл конфигурации является ADD_REQUEST_HEADER_ROUTE. В конфигурации ADD_REQUEST_HEADER_ROUTE идентификатор ротора настраивается как ADD_REQUEST_HEADER_ROUTE, а адрес маршрутизации является http://httpbin.org:80 / get. Маршрутизатор имеет последующую обработку, есть фильтр под названием AddrequestHeadergatewayFilterfactory (записан как AddrequestHeader по Конвенции), и фабрика фильтра AddrequestHeader добавит пару заголовков запросов на заголовок запроса, имя x-request-foo Значение бара. Чтобы проверить, как работает AddrequestheaderGatewayFilterFactory, посмотрите на свой исходный код. Исходный код AddrequestHeatergatewayFilterFactory является следующим:
public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest().mutate()
.header(config.getName(), config.getValue())
.build();
return chain.filter(exchange.mutate().request(request).build());
};
}
}
Из приведенного выше кода вы можете увидеть новый ServerHttpRequest на основе старого ServerHttpRequest, добавить заголовок запроса в новый ServerHttpRequest, затем создать новый ServerWeBexchange и отправить цепочку фильтров для продолжения фильтрации.
Запустите проект и смоделируйте запрос с помощью команды curl:
curl localhost:8081
наконец показывает изhttpbin.org:80/получить запрос, ответ...
{
"args": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Forwarded": "proto=http;host=\"localhost:8081\";for=\"0:0:0:0:0:0:0:1:56248\"",
"Host": "httpbin.org",
"User-Agent": "curl/7.58.0",
"X-Forwarded-Host": "localhost:8081",
"X-Request-Foo": "Bar"
},
"origin": "0:0:0:0:0:0:0:1, 210.22.21.66",
"url": "http://localhost:8081/get"
}
Из приведенного выше ответа видно, что заголовок запроса, такой как X-Request-Foo, действительно добавляется в заголовок запроса, и вступает в силу фабрика фильтров AddRequestHeader, настроенная в файле конфигурации.
Подобно фабрике фильтров AddRequestHeader, фабрика фильтров AddResponseHeader не будет здесь повторяться.
RewritePath GatewayFilter Factory
В службе Nginx очень мощная функция. Шлюз весеннего облака обеспечивает такую функцию по умолчанию. Эта функция ZUUL. Добавьте следующую конфигурацию в файле конфигурации:
spring:
profiles:
active: rewritepath_route
---
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://blog.csdn.net
predicates:
- Path=/foo/**
filters:
- RewritePath=/foo/(?<segment>.*), /$\{segment}
profiles: rewritepath_route
Вышеуказанная конфигурация, все The / foo / ** маршрутизатор ударит конфигурацию путей начала, а выполнение логического фильтра, фильтр сконфигурировал ReWritePath в этом случае завод, это завод будет /foo/(.*) переписан как {сегмент} , а затем отправлен в https://blog.csdn.net. Такие запросы на веб-странице Localhost: 8081 / FOO / FOREZP, пересылают запрос на случай HTTPS://blog.csdn.net/forezp, такие как запросы на странице на localhost: 8081 / foo / feedzp / 1, страница Дисплей 404, потому что нет https://blog.csdn.net/forezp/1 Эта страница.
пользовательский фильтр
Spring Cloud Gateway имеет встроенные 19 мощных фабрик фильтров, которые могут удовлетворить потребности многих сценариев, так что можете ли вы настраивать свои собственные фильтры?Конечно, можете. В Spring Cloud Gateway фильтры должны реализовать интерфейсы GatewayFilter и Ordered2. Напишите RequestTimeFilter со следующим кодом:
public class RequestTimeFilter implements GatewayFilter, Ordered {
private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
if (startTime != null) {
log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
}
})
);
}
@Override
public int getOrder() {
return 0;
}
}
В приведенном выше коде метод int getOrder() в Ordered используется для установки уровня приоритета фильтра. Чем больше значение, тем ниже приоритет. Также существует метод filterI(exchange,chain) В этом методе время начала запроса записывается и хранится в ServerWebExchange Здесь фильтр типа "pre", а затем внутренний chain.filter Метод run() в классе эквивалентен фильтру «post», где печатается время, затраченное на запрос. Затем зарегистрируйте фильтр на маршрутизаторе с помощью следующего кода:
@Bean
public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
// @formatter:off
return builder.routes()
.route(r -> r.path("/customer/**")
.filters(f -> f.filter(new RequestTimeFilter())
.addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
.uri("http://httpbin.org:80/get")
.order(0)
.id("customer_filter_router")
)
.build();
// @formatter:on
}
Перезапустите программу и смоделируйте запрос через команду curl:
curl localhost:8081/customer/123
В консоль программы выводится лог следующей информации запроса:
2018-11-16 15:02:20.177 INFO 20488 --- [ctor-http-nio-3] o.s.cloud.gateway.filter.GatewayFilter : /customer/123: 152ms
Пользовательский фильтр завод
Есть ли в приведенном выше пользовательском фильтре способ настроить класс фабрики фильтров? Таким образом, фильтр можно настроить в файле конфигурации. Теперь вам нужно реализовать фабрику фильтров.При печати времени вы можете установить параметры, чтобы решить, следует ли печатать параметры. Глядя на исходный код GatewayFilterFactory, вы можете обнаружить, что иерархия GatewayFilterfactory выглядит следующим образом:
Интерфейс верхнего уровня фабрики фильтров — GatewayFilterFactory. Мы можем напрямую наследовать два его абстрактных класса, чтобы упростить разработку AbstractGatewayFilterFactory и AbstractNameValueGatewayFilterFactory. Разница между этими двумя абстрактными классами заключается в том, что первый получает параметр (например, StripPrefix, а тот, который мы создан), а последний Получатель получает два параметра (например, AddResponseHeader).
Интерфейс верхнего уровня фабрики фильтров — GatewayFilterFactory, который имеет два абстрактных класса, более близких к конкретной реализации, а именно AbstractGatewayFilterFactory и AbstractNameValueGatewayFilterFactory. два параметра, например класс реализации AddRequestHeaderGatewayFilterFactory. Теперь вам нужно распечатать запрошенный журнал, вам нужно использовать параметр, вы можете обратиться к методу записи RedirectToGatewayFilterFactory.
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> {
private static final Log log = LogFactory.getLog(GatewayFilter.class);
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
private static final String KEY = "withParams";
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(KEY);
}
public RequestTimeGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
if (startTime != null) {
StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
.append(": ")
.append(System.currentTimeMillis() - startTime)
.append("ms");
if (config.isWithParams()) {
sb.append(" params:").append(exchange.getRequest().getQueryParams());
}
log.info(sb.toString());
}
})
);
};
}
public static class Config {
private boolean withParams;
public boolean isWithParams() {
return withParams;
}
public void setWithParams(boolean withParams) {
this.withParams = withParams;
}
}
}
В приведенном выше коде анонимный класс GatewayFilter создается в методе apply(Config config).Конкретная логика реализации такая же, как и раньше, за исключением того, что добавлена логика того, следует ли печатать параметры запроса, и переключатель этого логика config.isWithParams() . Статический внутренний класс Config должен получить сервис параметров логического типа, имя переменной в нем может быть написано произвольно, но метод List ShortcutFieldOrder() должен быть переписан. .
Следует отметить, что в конструкторе класса должен быть вызван конструктор родительского класса для передачи типа Config, иначе будет сообщено ClassCastException
Наконец, вам необходимо зарегистрировать класс RequesttiMegeWayFilterfaactory на контейнер IOC SRPING в классе приложений файла запуска.
@Bean
public RequestTimeGatewayFilterFactory elapsedGatewayFilterFactory() {
return new RequestTimeGatewayFilterFactory();
}
Затем может быть организовано в файле конфигурации следующим образом:
spring:
profiles:
active: elapse_route
---
spring:
cloud:
gateway:
routes:
- id: elapse_route
uri: http://httpbin.org:80/get
filters:
- RequestTime=false
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
profiles: elapse_route
Запустите проект и посетите localhost:8081?name=forezp в браузере.Вы можете увидеть в консоли, что журнал выводит время, затраченное на запрос, и параметры запроса.
global filter
Spring Cloud Gateway делится на GatewayFilter и GlobalFilter в соответствии со сферой действия. Различия между ними заключаются в следующем:
-
GatewayFilter: необходимо настроить конкретный маршрут через spring.cloud.routes.filters, действовать только на текущем маршруте или через глобальные фильтры spring.cloud.default, действующие на всех маршрутах.
-
GlobalFilter : глобальный фильтр, который не нужно настраивать в файле конфигурации, действует на всех маршрутах и, наконец, упаковывается в фильтр, идентифицируемый GatewayFilterChain через GatewayFilterAdapter, который преобразует службу запроса и URI маршрута в адрес запроса. службы реального сервиса Основной фильтр, который не нуждается в настройке, загружается при инициализации системы и действует на каждом маршруте.
GlobalFilter, встроенный в структуру Spring Cloud Gateway, выглядит следующим образом:
上图中每一个GlobalFilter都作用在每一个router上,能够满足大多数的需求。但是如果遇到业务上的定制,可能需要编写满足自己需求的GlobalFilter。在下面的案例中将讲述如何编写自己GlobalFilter,该GlobalFilter会校验请求中是否包含了请求参数“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑。 код показывает, как показано ниже:
public class TokenFilter implements GlobalFilter, Ordered {
Logger logger=LoggerFactory.getLogger( TokenFilter.class );
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (token == null || token.isEmpty()) {
logger.info( "token is empty..." );
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
Приведенный выше TokenFilter должен реализовать интерфейсы GlobalFilter и Ordered, что очень похоже на реализацию GatewayFilter. Затем получить ServerHttpRequest в соответствии с ServerWebExchange, а затем в соответствии с наличием токена параметра в ServerHttpRequest, если нет, выполнить запрос и завершить переадресацию, в противном случае выполнить обычную логику.
Затем вам нужно внедрить TokenFilter в контейнер Spring Ioc в классе запуска проекта, код выглядит следующим образом:
@Bean
public TokenFilter tokenFilter(){
return new TokenFilter();
}
Запустите проект и используйте команду curl для запроса:
curl localhost:8081/customer/123
Видно, что запрос не переадресовывается, запрос завершается, а в консоль выводится следующий лог:
2018-11-16 15:30:13.543 INFO 19372 --- [ctor-http-nio-2] gateway.TokenFilter : token is empty...
Приведенный выше журнал показывает, что запрос вошел в логику без передачи «токена».
Суммировать
В этой статье описываются фильтры в Spring Cloud Gateway, включая GatewayFilter и GlobalFilter. Начните со встроенных фильтров в официальной документации, а затем объясните пользовательский GatewayFilter, GatewayFilterFactory и пользовательский GlobalFilter. Есть много встроенных фильтров, которые не были описаны, например, фильтр ограничения тока, который я считаю более важным, и фильтр, на который все обращают внимание, будет описан в следующей статье.
использованная литература
cloud.spring.IO/spring - уродливый...
woo woo Краткое описание.com/fear/retribution 3 ah 67291…
Загрузка исходного кода
Github.com/fore photo / sp день ...
Сканировать и поддерживать автор
(Для перепечатываемых статей просьба указывать автора и источникБлог Фан Чжипэна)