8

どちらも Kubernetes クラスターにデプロイされる 2 つの Spring Boot アプリケーションを作成しました。これらのアプリの 1 つがゲートウェイとして機能するため、Spring Cloud Gateway を依存関係として使用します。また、サービス ディスカバリを Spring Cloud Kubernetes と統合し、ゲートウェイがサービス ディスカバリを使用して対応するルートを自動的に生成するようにしたいと考えています。しかし、ローカルの Minikube クラスターで実行されているゲートウェイ アプリケーションを公開し、2 番目のアプリ/サービスを呼び出すと、次のメッセージで 503 エラーが発生します。Unable to find instance for ...-service

現在、私は以下をインストールしました:

  • ミニキューブ
  • VirtualBox
  • Docker ツールボックス

2 つのサブプロジェクト (ゲートウェイと別のサービス) を持つ Gradle プロジェクトを作成しました。すべてのプロジェクトはローカルでビルド/デプロイされます。デフォルトのサービス アカウントには、Kubernetes API を読み取る権限があります。これらのサービスをデプロイした後、ゲートウェイ サービスを外部に公開します。ゲートウェイ サービスには、いくつかのエンドポイントが実装されています。

  1. DiscoveryClient を介してクラスター内のすべてのサービスのリストを提供します。
  2. アプリケーション層では、DiscoveryClient によって提供された URI に基づいて他のサービスを呼び出します。

すべてが機能しているように見えますが、他のサービスを呼び出すとURI/serviceId503 エラーが発生します...

以下の 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 とゲートウェイのアプリケーション クラスです。

アプリケーション.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 応答が返され、アプリケーションの残りのコントローラーに基づいて正しい答えが得られると思います。

4

3 に答える 3