Spring Boot 2.5.6 API 网关 + Eureka Server = 404

Posted

技术标签:

【中文标题】Spring Boot 2.5.6 API 网关 + Eureka Server = 404【英文标题】:Spring Boot 2.5.6 API Gateway + Eureka Server = 404 【发布时间】:2021-12-24 10:14:09 【问题描述】:

我正在使用 Spring API 网关、Eureka Server 和 WebFlux 创建一个项目。

借助 spring 文档,我启动了 3 项服务:

localhost:3761 - 尤里卡 localhost:4001 - 服务 localhost:8080 - Api 网关

Eureka 列出了 2 个服务(网关和我的服务) 我的服务在浏览器上运行良好 我的网关只有在我的路由 uri 是 localhost 并且我真的不知道如何解决它时才会响应。

网关 application.yml - 不工作

server:
  port: 8080

eureka:
  instance:
    hostname: localhost
    non-secure-port: 8761
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/eureka/

spring:
  application:
    name: GATEWAY-SERVER
  cloud:
    gateway:
      
      discovery:
        locator:
          enabled: true
      routes:
        - id: my-service-route
          uri: lb://MY-SERVICE
          predicates:
            - Path=/api/my/service/**

网关 application.yml - 工作

server:
  port: 8080

eureka:
  instance:
    hostname: localhost
    non-secure-port: 8761
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/eureka/

spring:
  application:
    name: GATEWAY-SERVER
  cloud:
    gateway:
      
      discovery:
        locator:
          enabled: true
      routes:
        - id: my-service-route
          uri: http://localhost:4001
          predicates:
            - Path=/api/my/service/**

请注意,唯一的区别是 URI 不是在寻找服务名称。

【问题讨论】:

请显示您的依赖关系。顺便说一句,你的尤里卡实例设置是错误的。这些是要注册的实例,而不是 eureka 服务器。 【参考方案1】:

@spencergibb

这里是依赖项:

父级(物料清单)

<?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 http://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.5.6</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.site</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <packaging>pom</packaging>
    <name>Parent POM</name>

    <properties>
        <java.version>11</java.version>
        <encoding>UTF-8</encoding>
        <spring-cloud.version>2020.0.4</spring-cloud.version>
        <spring-native.version>0.10.3</spring-native.version>
        <feign.reactor.version>3.1.1</feign.reactor.version>

        <maven.release.version>3.0.0-M4</maven.release.version>
        <lombok.mapstruct.binding.version>0.2.0</lombok.mapstruct.binding.version>
        <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
        <org.springdoc.version>1.5.11</org.springdoc.version>

        <project.build.sourceEncoding>$encoding</project.build.sourceEncoding>
        <project.reporting.outputEncoding>$encoding</project.reporting.outputEncoding>
        <project.resources.sourceEncoding>$encoding</project.resources.sourceEncoding>
        <archetype.encoding>$encoding</archetype.encoding>
        <maven.compiler.source>$java.version</maven.compiler.source>
        <maven.compiler.target>$java.version</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Develop -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok-mapstruct-binding</artifactId>
                <version>$lombok.mapstruct.binding.version</version>
            </dependency>

            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct</artifactId>
                <version>$org.mapstruct.version</version>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>$spring-cloud.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.playtika.reactivefeign</groupId>
                <artifactId>feign-reactor-spring-cloud-starter</artifactId>
                <version>3.1.1</version>
                <type>pom</type>
            </dependency>

            <!-- Documentation -->
            <dependency>
                <groupId>org.springdoc</groupId>
                <artifactId>springdoc-openapi-webflux-ui</artifactId>
                <version>$org.springdoc.version</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- DevOps -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>$basedir/src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>**/application*.yml</include>
                </includes>
            </resource>
        </resources>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <layers>
                        <enabled>true</enabled>
                        <includeLayerTools>true</includeLayerTools>
                    </layers>
                    <image>
                        <name>$project.artifactId:$project.version</name>
                    </image>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>$java.version</source> <!-- depending on your project -->
                    <target>$java.version</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>$org.mapstruct.version</version>
                        </path>

                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>$lombok.version</version>
                        </path>

                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>$lombok.mapstruct.binding.version</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg>
                    </compilerArgs>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>$maven.release.version</version>
                <configuration>
                    <allowTimestampedSnapshots>true</allowTimestampedSnapshots>
                    <tagNameFormat>@project.version</tagNameFormat>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

尤里卡

<?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>com.site</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <artifactId>eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>eureka-server</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

网关

<?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>com.site</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <artifactId>gateway-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway-server</name>
    <description>gateway-server</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

我的服务

<?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>com.site</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <artifactId>service</artifactId>
    <version>0.1.1-SNAPSHOT</version>

    <name>my-service</name>
    <description>my-service</description>


    <dependencies>
        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>com.playtika.reactivefeign</groupId>
            <artifactId>feign-reactor-spring-cloud-starter</artifactId>
            <type>pom</type>
        </dependency>

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

        <!-- Database -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>

        <!-- Developer -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
        </dependency>

        <!-- Documentation -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-webflux-ui</artifactId>
        </dependency>

        <!-- Validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <!-- Tests -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

这里还有服务的 yaml。我想我在网关或尤里卡做错了什么。

尤里卡

server:
  port: 8761

spring:
  application:
    name: EUREKA-SERVER

eureka:
  instance:
    hostname: localhost
    prefer-ip-address: true
  client:
    register-with-eureka: false
    fetch-registry: false
    use-dns-for-fetching-service-urls: false
    service-url:
      defaultZone: http://$eureka.instance.hostname:$server.port/eureka/

logging:
  level:
    com:
      netflix:
        eureka: off
        discovery: off

网关

server:
  port: 8080

eureka:
  instance:
    hostname: localhost
    non-secure-port: 8761
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/eureka/

spring:
  application:
    name: GATEWAY-SERVER
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: my-service-route
          uri: lb://MY-SERVICE
          predicates:
            - Path=/api/v1/**

我的服务

server:
  port: 4001

spring:
  application:
    name: MY-SERVICE
  data:
    mongodb:
      uri: mongodb://localhost:27017/service

eureka:
  instance:
    hostname: localhost
    non-secure-port: 8761
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://$eureka.instance.hostname:$eureka.instance.non-secure-port/eureka/

springdoc:
  api-docs:
    enabled: true
    path: /api-docs
  swagger-ui:
    path: /index.html

【讨论】:

【参考方案2】:

在 GATEWAY-SERVICE 上做一些测试。我注意到一些奇怪的事情:

我已经列出了网关上的服务:

网关服务器应用程序

@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayServerApplication implements CommandLineRunner 
    @Autowired
    private DiscoveryClient discoveryClient;

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

    @Override
    public void run(String... args) throws Exception 
        System.out.println("LIST INSTANCES");
        List<String> list = discoveryClient.getServices();

        list.forEach(item -> 
            System.out.println("Service: " + item);
            List<ServiceInstance> instances = this.discoveryClient.getInstances(item);
            instances.forEach(instance -> 
                System.out.println("URI: " + instance.getUri());
                System.out.println("HOST: " + instance.getHost());
                System.out.println("PORT: " + instance.getPort());
                System.out.println("INSTANCE ID: " + instance.getInstanceId());
                System.out.println("SERVICE ID: " + instance.getServiceId());
            );
        );
    



2021-11-13 09:24:35.633  INFO 1547 --- [           main] b.c.f.gateway.GatewayServerApplication   : Started GatewayServerApplication in 3.576 seconds (JVM running for 4.419)
LIST INSTANCES
Service: my-service
URI: http://192.168.0.103:8761
HOST: 192.168.0.103
PORT: 8761
INSTANCE ID: mbp-of-rafael:MY-SERVICE:4001
SERVICE ID: MY-SERVICE

URI 和 Port 定义为 8761(eureka 服务器端口)。但我认为应该是 4001(我的服务端口)。我错了吗?!

【讨论】:

以上是关于Spring Boot 2.5.6 API 网关 + Eureka Server = 404的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 应用程序中使用 API 网关时,HATEOAS 路径无效

如何在 Spring Boot 应用程序中从 Api 网关(Zuul)调用外部服务(非 MSA)

Spring Boot + Spring Cloud 构建微服务系统:API服务网关(Zuul)

Spring Boot API Gateway 无法解析名称

Spring Boot - 模拟对外部 API 的 POST REST 请求

使用 Spring Boot 的 gRPC 和 REST 微服务