どちらも 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 を読み取る権限があります。これらのサービスをデプロイした後、ゲートウェイ サービスを外部に公開します。ゲートウェイ サービスには、いくつかのエンドポイントが実装されています。
- DiscoveryClient を介してクラスター内のすべてのサービスのリストを提供します。
- アプリケーション層では、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 とゲートウェイのアプリケーション クラスです。
アプリケーション.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 応答が返され、アプリケーションの残りのコントローラーに基づいて正しい答えが得られると思います。