«1. Обзор

В этой статье мы рассмотрим, как балансировка нагрузки работает с Zuul и Eureka.

Мы будем направлять запросы к службе REST, обнаруженной Spring Cloud Eureka, через Zuul Proxy.

2. Первоначальная настройка

Нам нужно настроить сервер/клиент Eureka, как показано в статье Spring Cloud Netflix-Eureka.

3. Настройка Zuul

Zuul, среди прочего, получает данные из служб Eureka и выполняет балансировку нагрузки на стороне сервера.

3.1. Конфигурация Maven

Во-первых, мы добавим Zuul Server и зависимость Eureka в наш pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

3.2. Связь с Eureka

Во-вторых, мы добавим необходимые свойства в файл application.properties Zuul:

server.port=8762
spring.application.name=zuul-server
eureka.instance.preferIpAddress=true
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone=${EUREKA_URI:http://localhost:8761/eureka}

Здесь мы говорим Zuul зарегистрироваться как служба в Eureka и работать на порту 8762. ~ ~~ Далее мы реализуем основной класс с @EnableZuulProxy и @EnableDiscoveryClient. @EnableZuulProxy указывает, что это сервер Zuul, а @EnableDiscoveryClient указывает, что это клиент Eureka:

Мы укажем в нашем браузере на http://localhost:8762/routes. Это должно показать все маршруты, доступные для Zuul, обнаруженные Eureka:

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class ZuulConfig {
    public static void main(String[] args) {
        SpringApplication.run(ZuulConfig.class, args);
    }
}

Теперь мы будем общаться с клиентом Eureka, используя полученный маршрут Zuul Proxy. Указав в браузере на http://localhost:8762/spring-cloud-eureka-client/greeting, вы получите примерно такой ответ:

{"/spring-cloud-eureka-client/**":"spring-cloud-eureka-client"}

4. Балансировка нагрузки с помощью Zuul

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!

Когда Zuul получает запрос, он выбирает одно из доступных физических местоположений и перенаправляет запросы фактическому экземпляру службы. Весь процесс кэширования местоположения экземпляров службы и перенаправления запроса в фактическое местоположение предоставляется из коробки без необходимости дополнительных настроек.

Здесь мы видим, как Zuul инкапсулирует три разных экземпляра одной и той же службы:

Внутри Zuul использует ленту Netflix для поиска всех экземпляров службы из службы обнаружения (Eureka Server).

Давайте понаблюдаем за этим поведением при вызове нескольких экземпляров.

4.1. Регистрация нескольких экземпляров

Мы начнем с запуска двух экземпляров (порты 8081 и 8082).

Когда все экземпляры запущены, в журналах мы можем наблюдать, что физическое расположение экземпляров регистрируется в DynamicServerListLoadBalancer, а маршрут сопоставляется с контроллером Zuul, который обеспечивает пересылку запросов к фактическому экземпляру:

Примечание: журналы были отформатированы для лучшей читабельности.

Mapped URL path [/spring-cloud-eureka-client/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]
Client:spring-cloud-eureka-client instantiated a LoadBalancer:
  DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloud-eureka-client,
  current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
Using serverListUpdater PollingServerListUpdater
DynamicServerListLoadBalancer for client spring-cloud-eureka-client initialized: 
  DynamicServerListLoadBalancer:{NFLoadBalancer:name=spring-cloud-eureka-client,
  current list of Servers=[0.0.0.0:8081, 0.0.0.0:8082],
  Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;	Instance count:2;	
  Active connections count: 0;	Circuit breaker tripped count: 0;	
  Active connections per server: 0.0;]},
  Server stats: 
    [[Server:0.0.0.0:8080;	Zone:defaultZone;......],
    [Server:0.0.0.0:8081;	Zone:defaultZone; ......],

4.2. Пример балансировки нагрузки

Давайте несколько раз перейдем в браузере по адресу http://localhost:8762/spring-cloud-eureka-client/greeting.

Каждый раз мы должны видеть несколько иной результат:

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!
Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8082'!
Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8081'!

Каждый запрос, полученный Zuul, пересылается в другой экземпляр в циклическом режиме.

Если мы запустим другой экземпляр и зарегистрируем его в Eureka, Zuul зарегистрирует его автоматически и начнет пересылать ему запросы:

Hello from 'SPRING-CLOUD-EUREKA-CLIENT with Port Number 8083'!

Мы также можем изменить стратегию балансировки нагрузки Zuul на любую другую стратегию ленты Netflix — больше об этом можно найти в нашей статье на ленте.

5. Заключение

Как мы видели, Zuul предоставляет один URL-адрес для всех экземпляров Rest Service и выполняет балансировку нагрузки для пересылки запросов одному из экземпляров в циклическом режиме.

Как всегда, полный код этой статьи можно найти на GitHub.