【问题标题】:How to set up Spring Cloud Gateway application so it can use the Service Discovery of Spring Cloud Kubernetes?如何设置 Spring Cloud Gateway 应用程序以便它可以使用 Spring Cloud Kubernetes 的服务发现?
【发布时间】:2019-05-16 14:07:20
【问题描述】:

我创建了两个 Spring Boot 应用程序,它们都将部署在 Kubernetes 集群中。其中一个应用程序将充当网关,因此使用 Spring Cloud Gateway 作为依赖项。另外我想将服务发现与 Spring Cloud Kubernetes 集成,网关使用服务发现自动生成相应的路由。但是,当我公开在本地 Minikube 集群中运行的网关应用程序并调用第二个应用程序/服务时,我收到 503 错误并显示以下消息:Unable to find instance for ...-service

目前我已经安装了以下:

  • Minikube
  • 虚拟盒子
  • Docker 工具箱

我创建了一个带有两个子项目(网关和另一个服务)的 Gradle 项目。所有项目都将在本地构建/部署。默认服务帐户有权读取 Kubernetes API。部署这些服务后,我将网关服务公开在外部。在网关服务中,我实现了一些端点,

  1. 通过 DiscoveryClient 提供集群中所有服务的列表。
  2. 在应用层根据 DiscoveryClient 提供的 URI 调用其他服务。

似乎一切正常,但是当我使用 URI/serviceId 调用其他服务时,我收到 503 错误...

使用以下 Spring Cloud 版本: spring-cloud-starter-kubernetes 1.0.1.RELEASE spring-cloud-starter-gateway 2.1.1.RELEASE

我的演示应用程序位于https://github.com/nmaoez/spring-cloud-gateway-kubernetes,README.md 提供了将这两种服务部署到本地 Minikube 集群中的步骤。还显示了所有可用的端点。但有趣的是application.yaml和网关的应用类。

application.yaml:

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
management:
  endpoints:
    web:
      exposure:
        include: '*'

GatewayApplication.java

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class GatewayApplication {

  @Autowired
  RestTemplate restTemplate;

  @Autowired
  private DiscoveryClient discoveryClient;

  @GetMapping("/")
  @ResponseBody
  public String hello() {
    return "GatewayApplication says hello!";
  }

  @GetMapping("/test")
  @ResponseBody
  public String invokeTestService() {
    List<ServiceInstance> testServiceInstances = this.discoveryClient.getInstances("test-service");
    return restTemplate.getForObject(testServiceInstances.get(0).getUri(), String.class);
  }

  @GetMapping("/services")
  public List<String> services() {
    return this.discoveryClient.getServices();
  }

  @GetMapping("/services/{serviceId}")
  public List<ServiceInstance> servicesById(@PathVariable("serviceId") String serviceId) {
    return this.discoveryClient.getInstances(serviceId);
  }

  @Bean
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

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

在将 gateway-service/application.yaml 中的 url-expression 字段覆盖为之后,我知道它是如何运行的

url-expression: "uri+'/'"

之后我在调用gateway-uri/another-service/ 后得到了正确的响应。但我的愿望是不明确替换默认的lb://serviceid。我该怎么做?

我希望如果我通过网关调用集群中的另一个服务,我会收到 200 响应和基于应用程序其余控制器的正确答案。

【问题讨论】:

标签: spring-boot spring-cloud service-discovery spring-cloud-gateway spring-cloud-kubernetes


【解决方案1】:

您还必须将依赖项添加到spring-cloud-starter-kubernetes-ribbon

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
            <version>1.0.1.RELEASE</version>
        </dependency>

然后它无需任何重写就可以工作,只需spring.cloud.gateway.discovery.locator.enabled: true

【讨论】:

  • 我有类似的问题,这个答案没有帮助
【解决方案2】:

我刚刚使用 Spring Cloud Gateway 和 Kubernetes 实现了一个示例应用程序,它就像 Docker Desktop 中的魅力一样。并且不需要额外或有趣的配置。

如果有帮助,这是我的build.gradle

plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.1.0-SNAPSHOT'

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

ext {
    set('springCloudVersion', "2020.0.0")
    set('springCloudKubernetesVersion', '1.1.7.RELEASE')
    set('springCloudVersion', '2020.0.0')
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation "org.springframework.cloud:spring-cloud-starter-kubernetes:$springCloudKubernetesVersion"
    implementation "org.springframework.cloud:spring-cloud-starter-kubernetes-config:$springCloudKubernetesVersion"
    implementation "org.springframework.cloud:spring-cloud-starter-kubernetes-ribbon:$springCloudKubernetesVersion"
    implementation "org.springframework.cloud:spring-cloud-starter-kubernetes-loadbalancer:$springCloudKubernetesVersion"
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"
    }
}

test {
    useJUnitPlatform()
}

这是来自application.yaml的配置:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true

最后,DiscoveryClient 在应用中启用:

@SpringBootApplication
@EnableDiscoveryClient // So services can be discovered
public class GatewayApplication {

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

}

请注意,正如 Jakub Kubrynski 所说,您必须包含 Ribbon 依赖项。

还要注意路由仅在网关部署到 K8s 集群时才有效。在它之外,它可以看到 K8s 服务,但无法路由到它们,因为它们使用的是 K8s 网络中的 IP 地址。

【讨论】:

    【解决方案3】:

    我能够通过发现 spring-cloud-kubernetes 依赖版本 1.1.10.RELASE 和 Spring-boot: 2.5.7 Spring Cloud Gateway: 3.0.4 来设置 Spring Cloud Gateway:

    Pom 文件如下所示:

    <?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.5.7</version>
            <relativePath/>
        </parent>
    
        <groupId>com.csg.cro.rccs</groupId>
        <artifactId>api-gateway</artifactId>
        <version>${revision}</version>
        <name>RCC-APIGateway</name>
        <description>Enable Proxy and verify user token project for Risk 360</description>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>11</java.version>
            <spring-cloud.version>2020.0.3</spring-cloud.version>
            <revision>21.7.0-SNAPSHOT</revision>
        </properties>
    
    
        <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>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-kubernetes</artifactId>
                <version>1.1.10.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
                <version>1.1.10.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
                <version>1.1.10.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-kubernetes-loadbalancer</artifactId>
                <version>1.1.10.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-webflux</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                 <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>flatten-maven-plugin</artifactId>
                <version>1.1.0</version>
                <configuration>
                    <updatePomFile>true</updatePomFile>
                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
                </configuration>
                <executions>
                    <execution>
                        <id>flatten</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>flatten</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>flatten.clean</id>
                        <phase>clean</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            </plugins>
        </build>
        
    </project>
    
    

    我的发现配置如下:

    spring:
      application.name: gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true
              url-expression: "'http://'+serviceId+':'+getPort()"
              lower-case-service-id: true
    
    

    【讨论】:

      猜你喜欢
      • 2020-02-10
      • 2016-06-30
      • 2020-03-04
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 2019-11-18
      • 2019-03-02
      • 1970-01-01
      相关资源
      最近更新 更多