Я пытаюсь реализовать LB на стороне сервера с помощью SpringCloudGateway и Eureka. У меня есть микросервисы ABC (abc.test.com) и шлюз (gateway.test.com), зарегистрированные в eureka (eureka.test.com) по имени хоста.
Если я отправлю запрос от почтальона на локальном компьютере на gateway.test.com/test/owned, то я увижу в консоли почтальона 2 запроса вместо 1. Хотя у меня нет зависимости: spring-cloud-starter-loadbalancer Это похоже на то, что Spring выполняет балансировку нагрузки на стороне клиента, а не на стороне сервера. Кроме того, не все заголовки, вероятно, проходят через это перенаправление (например, авторизация, которая вызвала окончательную ошибку 401).
Маршрутизация шлюза:
- id: ABC
uri: lb://ABC
predicates:
- Path=/test/**
Первый:
GET / HTTP/1.1
Authorization: Bearer ****
User-Agent: PostmanRuntime/7.28.2
Accept: */*
Host: gateway.test.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP/1.1 301
location: https://abc.test.com/test/owned
date: Mon, 26 Dec 2022 13:00:54 GMT
server: ******
content-length: 0
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1 ; mode=block
referrer-policy: no-referrer
x-envoy-upstream-service-time: 12
Второй:
GET /test/owned HTTP/1.1
User-Agent: PostmanRuntime/7.28.2
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: https://gateway.test.com/test/owned
Host: abc.test.com
Cookie: JSESSIONID=720********
HTTP/1.1 401 Unauthorized
vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers
www-authenticate: Bearer
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-frame-options: DENY
content-length: 0
date: Mon, 26 Dec 2022 13:00:59 GMT
x-envoy-upstream-service-time: 5
server: *******
ПОМ:
<?xml version = "1.0" encoding = "UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.test</groupId>
<artifactId>testGateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>18</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Когда я запускаю службы на локальном хосте - скажем, шлюз 8080, abc 8081, eureka 8082, а затем отправляю запрос через шлюз, он работает (только 1 запрос находится в консоли почтальона, без видимого перенаправления клиента).
Когда я меняю маршрутизацию шлюза с lb://ABC direct на https://abc.test.com, кажется, что это работает, но этот обходной путь не может быть принят из-за ответственности за микросервисы.
Чего я хочу добиться, так это полной балансировки нагрузки на стороне сервера -> каждый клиент, делающий запрос через шлюз, не должен знать, какой и где вызов службы шлюза.
Для будущих искателей: Такое поведение было связано с перенаправлением http -> https. Мои сервисы были зарегистрированы в eureka как http -> балансировщик нагрузки Spring Cloud Gateway, получающий от http-адреса eureka и выполняющий запрос -> затем перенаправление было выполнено PAAS (я использую rail.app) на домен https (что приводит к потере заголовков и принудительному выполнению это на стороне клиента).
Исправить: Правильно зарегистрировать микросервис в eureka для https (наиболее важны первые четыре):
eureka.instance.nonSecurePort=80
eureka.instance.nonSecurePortEnabled=false
eureka.instance.securePortEnabled=true
eureka.instance.securePort=443
eureka.instance.preferIpAddress=false
eureka.instance.hostname=abc.test.com
eureka.instance.statusPageUrl='https://abc.test.com/info'
eureka.instance.healthCheckUrl='https://abc.test.com/health'
eureka.instance.homePageUrl='https://abc.test.com/'