Странное поведение балансировки нагрузки на стороне сервера в Spring Cloud Gateway с Netflix Eureka

Я пытаюсь реализовать 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, кажется, что это работает, но этот обходной путь не может быть принят из-за ответственности за микросервисы.

Чего я хочу добиться, так это полной балансировки нагрузки на стороне сервера -> каждый клиент, делающий запрос через шлюз, не должен знать, какой и где вызов службы шлюза.

1
0
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для будущих искателей: Такое поведение было связано с перенаправлением 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/'

Другие вопросы по теме