Перейти к основному содержимому

Запасной путь для Зуульского маршрута

· 4 мин. чтения

1. Обзор

Zuul — это пограничный сервис (или шлюз API) от Netflix, который обеспечивает динамическую маршрутизацию, мониторинг, отказоустойчивость и безопасность.

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

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

Для начала мы сначала настроим два приложения Spring Boot. В первом приложении мы создадим простую службу REST. Принимая во внимание, что во втором приложении мы будем использовать прокси-сервер Zuul для создания маршрута для службы REST первого приложения.

2.1. Простой REST-сервис

Допустим, нашему приложению необходимо отобразить пользователю сегодняшнюю информацию о погоде. Итак, мы создадим приложение службы погоды на основе Spring Boot, используя стартер spring-boot-starter-web :

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Теперь мы создадим контроллер для нашего погодного сервиса:

@RestController
@RequestMapping("/weather")
public class WeatherController {

@GetMapping("/today")
public String getMessage() {
return "It's a bright sunny day today!";
}

}

Теперь давайте запустим службу погоды и проверим API службы погоды:

$ curl -s localhost:8080/weather/today
It's a bright sunny day today!

2.2. Приложение шлюза API

Давайте теперь создадим наше второе приложение Spring Boot, шлюз API. В этом приложении мы создадим маршрут Zuul для нашей службы погоды.

И поскольку и наша служба погоды, и Zuul по умолчанию захотят использовать 8080, мы настроим его для работы на другом порту, 7070.

Итак, давайте сначала добавим spring-cloud-starter-netflix-zuul в pom.xml:

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

Далее мы добавим аннотацию @EnableZuulProxy в наш класс приложения API Gateway:

@SpringBootApplication
@EnableZuulProxy
public class ApiGatewayApplication {

public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}

}

Наконец, мы настроим маршрут Zuul, используя ленту, для нашего API службы погоды в application.yml :

spring:
application:
name: api-gateway
server:
port: 7070

zuul:
igoredServices: '*'
routes:
weather-service:
path: /weather/**
serviceId: weather-service
strip-prefix: false

ribbon:
eureka:
enabled: false

weather-service:
ribbon:
listOfServers: localhost:8080

2.3. Тестирование зуульского маршрута

На данный момент оба приложения Spring Boot настроены на предоставление API службы погоды с использованием прокси-сервера Zuul.

Итак, запустим оба приложения и проверим API погодного сервиса через Zuul:

$ curl -s localhost:7070/weather/today
It's a bright sunny day today!

2.4. Тестирование сбоя маршрута Zuul без отката

Теперь давайте остановим приложение службы погоды и снова проверим службу погоды через Zuul. В результате в ответе мы увидим сообщение об ошибке:

$ curl -s localhost:7070/weather/today
{"timestamp":"2019-10-08T12:42:09.479+0000","status":500,
"error":"Internal Server Error","message":"GENERAL"}

Очевидно, это не тот ответ, который хотел бы видеть пользователь. Итак, один из способов позаботиться об этом — создать запасной вариант для маршрута метеослужбы Zuul.

3. Zuul Fallback для маршрута

Прокси-сервер Zuul использует ленту для балансировки нагрузки, а запросы выполняются в команде Hystrix. В результате в матрице Hystrix появляются сбои на зуульском маршруте .

Поэтому, чтобы создать настраиваемый запасной вариант для маршрута Zuul, мы создадим bean-компонент типа FallbackProvider .

3.1. Класс WeatherServiceFallback _

В этом примере мы хотим вернуть сообщение из резервного ответа вместо сообщения об ошибке по умолчанию, которое мы видели ранее. Итак, давайте создадим простую реализацию FallbackProvider для маршрута службы погоды:

@Component
class WeatherServiceFallback implements FallbackProvider {

private static final String DEFAULT_MESSAGE = "Weather information is not available.";

@Override
public String getRoute() {
return "weather-service";
}

@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
if (cause instanceof HystrixTimeoutException) {
return new GatewayClientResponse(HttpStatus.GATEWAY_TIMEOUT, DEFAULT_MESSAGE);
} else {
return new GatewayClientResponse(HttpStatus.INTERNAL_SERVER_ERROR, DEFAULT_MESSAGE);
}
}

}

Как мы видим, мы переопределили методы getRoute и fallbackResponse . Метод getRoute возвращает идентификатор маршрута, для которого мы должны создать запасной вариант. Принимая во внимание, что метод fallbackResponse возвращает настраиваемый резервный ответ , объект типа GatewayClientResponse в нашем случае. GatewayClientResponse — это простая реализация ClientHttpResponse .

3.2. Тестирование Zuul Fallback

Теперь давайте проверим резервную копию, которую мы создали для службы погоды. Поэтому мы запустим приложение API Gateway и убедимся, что приложение службы погоды остановлено.

Теперь давайте получим доступ к API службы погоды через маршрут Zuul и посмотрим на резервный ответ в действии:

$ curl -s localhost:7070/weather/today
Weather information is not available.

4. Резервный вариант для всех маршрутов

До сих пор мы видели, как создать запасной вариант для маршрута Zuul, используя его идентификатор маршрута . Однако предположим, что мы также хотим создать общий запасной вариант для всех других маршрутов в нашем приложении. Мы можем сделать это, создав еще одну реализацию FallbackProvider и вернув * или null из метода getRoute вместо идентификатора маршрута :

@Override
public String getRoute() {
return "*"; // or return null;
}

5. Вывод

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

Как обычно, реализацию всех этих примеров и фрагментов кода можно найти на GitHub .