В архитектуре микросервисов может быть несколько служб API и несколько компонентов пользовательского интерфейса, которые взаимодействуют с API. На сегодняшний день многие приложения на основе микросервисов по-прежнему используют монолитные интерфейсы, в которых весь пользовательский интерфейс построен как единый модуль. Вы можете выбрать микро-интерфейсы, в которых пользовательский интерфейс также разбит на несколько микросервисов, взаимодействующих с API для получения соответствующих данных. Вместо того чтобы сообщать UI обо всех деталях наших микросервисов, мы можем предоставить унифицированный прокси-интерфейс, который будет делегировать вызовы различным микросервисам на основе шаблона URL. В этом посте мы узнаем, как создать API-шлюз с помощью Spring Cloud Zuul Proxy .
Микроуслуги с использованием Spring Boot и Spring Cloud
- Часть 1. MicroServices: Spring Boot и Spring Cloud Обзор
- Часть 2. MicroServices: управление конфигурацией с помощью Spring Cloud Config и Vault
- Часть 3. MicroServices: реестр и обнаружение Spring Cloud Service
- Часть 4: MicroServices: автоматический выключатель Spring Cloud с использованием Netflix Hystrix
- Часть 5. MicroServices: Spring Cloud Zuul Proxy в качестве шлюза API
В этом посте мы собираемся узнать:
- Зачем нам нужен API Gateway?
- Реализация API-шлюза с использованием Spring Cloud Zuul Proxy
- Использование фильтров Zuul для сквозных задач
Зачем нам нужен API Gateway?
API Gateway , также известный как Edge Service , предоставляет унифицированный интерфейс для набора микросервисов, так что клиентам не нужно знать обо всех деталях внутренних компонентов микросервисов. Однако есть некоторые плюсы и минусы использования шаблона API Gateway в архитектуре микросервисов.
Плюсы:
- Обеспечивает более простой интерфейс для клиентов
- Может использоваться для предотвращения раскрытия внутренней структуры микросервисов клиентам
- Позволяет проводить рефакторинг микросервисов, не принуждая клиентов к рефакторизации логики потребления
- Может централизовать сквозные проблемы, такие как безопасность, мониторинг, ограничение скорости и т. Д.
Минусы:
- Это может стать единственной точкой отказа, если не будут приняты надлежащие меры для обеспечения высокой доступности
- Знание различных микросервисных API может проникнуть в API Gateway
Реализация API-шлюза с использованием Spring Cloud Zuul Proxy
Spring Cloud предоставляет прокси Zuul, похожий на Nginx , который можно использовать для создания API Gateway.
Давайте создадим интерфейсный модуль пользовательского интерфейса «shoppingcart-ui» как приложение SpringBoot, которое также действует как прокси Zuul. Создайте проект SpringBoot с помощью Web , клиента конфигурации , Eureka Discovery , Zuul для запуска и аннотируйте основной класс точки входа с помощью @EnableZuulProxy .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId></dependency><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency> |
ShoppingcartUiApplication.java
|
01
02
03
04
05
06
07
08
09
10
11
|
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@EnableZuulProxy@SpringBootApplicationpublic class ShoppingcartUiApplication { public static void main(String[] args) { SpringApplication.run(ShoppingcartUiApplication.class, args); }} |
Поскольку мы также используем Eureka Discovery, запросы от прокси-сервера с шаблонами URL / service-id / ** будут перенаправляться на службу, зарегистрированную на Eureka Server с идентификатором службы «service-id» .
Например, из приложения пользовательского интерфейса, если мы сделаем запрос к http: // localhost: 8080 / catalog-service / products, тогда оно будет искать в Service Registry для ServiceID «catalog-service» и отправлять запрос с URL / products на один доступных экземпляров службы каталогов.
Чтобы это произошло, нам нужно зарегистрировать «shoppingcart-ui» в сервисном реестре Eureka.
bootstrap.properties
|
1
2
3
|
spring.application.name=shoppingcart-uiserver.port=8080eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ |
С этой конфигурацией теперь мы можем получать информацию о продукте из каталога-сервиса, используя jQuery следующим образом:
|
1
2
3
4
5
6
|
$.ajax({ url: '/catalog-service/products'}).done(function(data) { this.products = data;}.bind(this)); |
Здесь из нашего пользовательского интерфейса мы звоним по адресу http: // localhost: 8080 / catalog-service / products. Предполагая, что служба каталогов зарегистрирована с ServiceID «catalog-service» и работает через порт 8181, этот запрос будет перенаправлен на http: // host: 8181 / products. Но пользовательский интерфейс совершенно не знает, где работает фактическая служба каталогов, номер порта его имени хоста и т. Д.
Мы также можем использовать общий префикс для URL-адресов, например «/ api» , для которого мы хотим, чтобы Zuul использовал прокси, установив свойство zuul.prefix .
|
1
|
zuul.prefix=/api |
Теперь из пользовательского интерфейса мы можем сделать запрос на выборку продуктов по адресу http: // localhost: 8080 / api / catalog-service / products. По умолчанию Zuul удалит префикс и отправит запрос.
Вы также можете настроить отображение пути службы следующим образом:
|
1
2
|
zuul.routes.catalogservice.path=/catalog/**zuul.routes.catalogservice.serviceId=catalog-service |
В этой конфигурации вы можете использовать URL http: // localhost: 8080 / api / catalog / products, который будет перенаправлен в сервис с помощью serviceId catalog-service.
По умолчанию все сервисы, зарегистрированные на Eureka Server, будут доступны. Вы можете использовать свойство zuul.ignored-services, чтобы отключить это поведение и предоставлять только явно настроенные службы.
|
1
2
3
4
5
6
7
|
zuul.ignored-services=*zuul.routes.catalogservice.path=/catalog/**zuul.routes.catalogservice.serviceId=catalog-servicezuul.routes.orderservice.path=/orders/**zuul.routes.orderservice.serviceId=order-service |
При такой конфигурации только служба каталогов, служба заказов предоставляется через прокси Zuul, но не сервис инвентаризации .
Использование фильтров Zuul для сквозных задач
Поскольку Zuul выступает в качестве прокси-сервера для всех наших микросервисов, мы можем использовать сервис Zuul для реализации некоторых сквозных задач, таких как безопасность, ограничение скорости и т. Д. Одним из распространенных вариантов использования является пересылка заголовков аутентификации всем нисходящим службам.
Обычно в микросервисах мы будем использовать сервис OAuth для аутентификации и авторизации. После проверки подлинности клиента служба OAuth сгенерирует токен, который должен быть включен в запросы, отправляемые другим микросервисам, чтобы клиенту не нужно было проходить проверку подлинности для каждой службы отдельно. Мы можем использовать фильтр Zuul для реализации подобных функций.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;import javax.servlet.http.HttpServletRequest;import java.util.UUID;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;public class AuthHeaderFilter extends ZuulFilter { @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); if (request.getAttribute("AUTH_HEADER") == null) { //generate or get AUTH_TOKEN, ex from Spring Session repository String sessionId = UUID.randomUUID().toString(); ctx.addZuulRequestHeader("AUTH_HEADER", sessionId); } return null; }} |
Мы добавляем AUTH_HEADER в качестве заголовка запроса, используя RequestContext.addZuulRequestHeader (), который будет перенаправлен в нисходящие сервисы. Нам нужно зарегистрировать его как бин Spring.
|
1
2
3
4
|
@BeanAuthHeaderFilter authHeaderFilter() { return new AuthHeaderFilter();} |
Вы можете найти исходный код этой статьи по адресу https://github.com/sivaprasadreddy/spring-boot-microservices-series
| Опубликовано на Java Code Geeks с разрешения Сивы Редди, партнера нашей программы JCG . См. Оригинальную статью здесь: MicroServices. Часть 5. Spring Cloud Zuul Proxy в качестве шлюза API.
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |