1. Обзор
В этом уроке мы рассмотрим фильтр сообщений Netflix Zuul.
Netflix Zuul – это пограничный поставщик услуг, который находится между клиентом API и множеством микросервисов.
Постфильтр запускается перед отправкой окончательных ответов клиенту API. Это дает нам возможность действовать на необработанном теле ответа и делать такие вещи, как ведение журнала и другие преобразования данных, которые мы хотим.
2. Зависимости
Мы будем работать с Zuul в весенней облачной среде. Итак, давайте добавим следующее в раздел управления зависимостями вашего pom.xml:
org.springframework.cloud spring-cloud-dependencies 2020.0.0 pom import org.springframework.cloud spring-cloud-starter-netflix-zuul 2.2.2.RELEASE
Последнюю версию зависимостей Spring Cloud и spring-cloud-starter-netflix-zuul можно найти на Maven Central.
3. Создание фильтра записей
Фильтр post – это обычный класс, который расширяет абстрактный класс ZuulFilter и имеет тип фильтра post :
public class ResponseLogFilter extends ZuulFilter { @Override public String filterType() { return POST_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { return null; } }
Обратите внимание, что мы вернули POST_TYPE в методе filter Type () . Это то, что на самом деле отличает этот фильтр от других типов.
Еще одним важным методом, на который следует обратить внимание, является метод should Filter () . Мы возвращаем true здесь, так как мы хотим, чтобы фильтр был запущен в цепочке фильтров.
В готовом к производству приложении мы можем экстернализировать эту конфигурацию для большей гибкости.
Давайте подробнее рассмотрим run () , который вызывается всякий раз, когда работает наш фильтр.
4. Изменение тела ответа
Как уже говорилось ранее, Zuul находится между микросервисами и их клиентами. Следовательно, он может получить доступ к телу ответа и при необходимости изменить его перед передачей.
Например, мы можем прочитать тело ответа и зарегистрировать его содержимое:
@Override public Object run() throws ZuulException { RequestContext context = RequestContext.getCurrentContext(); try (final InputStream responseDataStream = context.getResponseDataStream()) { if(responseDataStream == null) { logger.info("BODY: {}", ""); return null; } String responseData = CharStreams.toString(new InputStreamReader(responseDataStream, "UTF-8")); logger.info("BODY: {}", responseData); context.setResponseBody(responseData); } catch (Exception e) { throw new ZuulException(e, INTERNAL_SERVER_ERROR.value(), e.getMessage()); } return null; }
Приведенный выше фрагмент показывает полную реализацию метода run() в фильтре журнала ответов , который мы создали ранее. Во-первых, мы получили экземпляр RequestContext . И из этого контекста мы смогли получить данные ответа InputStream в попытке построить resources.
Обратите внимание, что входной поток ответа может быть null, поэтому мы проверяем его. Это может быть связано с таймаутом обслуживания или другими неожиданными исключениями в микросервисе. В нашем случае мы просто регистрируем пустое тело ответа, когда это происходит.
В дальнейшем мы считываем входной поток в строку |, которую затем можем зарегистрировать.
Очень важно, что мы добавляем тело ответа обратно в контекст для обработки с помощью context.setResponseBody(responseData). Если мы пропустим этот шаг, мы получим IOException в следующих строках: java.io.IOException: Попытка чтения в закрытом потоке .
5. Заключение
В заключение, фильтры сообщений в Zuul предоставляют разработчикам возможность что-то сделать с ответом службы, прежде чем отправлять его клиенту.
Однако мы должны быть осторожны, чтобы случайно не раскрыть конфиденциальную информацию, которая может привести к нарушению.
Кроме того, мы должны с осторожностью относиться к выполнению длительных задач в рамках нашего фильтра сообщений, так как это может значительно увеличить время отклика.
Как обычно, исходный код доступен на GitHub .