Я создал два приложения Spring Boot, которые будут развернуты в кластере Kubernetes.Одно из этих приложений будет действовать как шлюз и, следовательно, использует Spring Cloud Gateway в качестве зависимости.Также я хочу интегрировать обнаружение служб с Spring Cloud Kubernetes и чтобы шлюз использовал обнаружение служб для автоматической генерации соответствующих маршрутов.Но когда я открываю приложение шлюза, работающее в локальном кластере Minikube, и вызываю второе приложение / службу, я получаю сообщение об ошибке 503 со следующим сообщением: Unable to find instance for ...-service
В настоящее время я установил следующее:
- Minikube
- VirtualBox
- Docker Toolbox
Я создал проект Gradle с двумя подпроектами (шлюзом и другим сервисом).Все проекты будут построены / развернуты локально.Учетная запись службы по умолчанию имеет разрешение на чтение API Kubernetes.После развертывания этих сервисов я выставляю службу шлюза извне.В службе шлюза у меня реализованы некоторые конечные точки, которые
- предоставляют список всех служб в кластере с помощью DiscoveryClient.
- на прикладном уровне вызывают другую службу на основе URIпредоставляется DiscoveryClient.
Кажется, все работает, но когда я вызываю другую службу с 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);
}
}
Я получилЭто как-то работает после того, как я переписал поле выражения url в gateway-service / application.yaml в
url-expression: "uri+'/'"
После этого я получил правильный ответ после того, как вызвал gateway-uri/another-service/
.Но я не хочу явно заменять значение по умолчанию lb://serviceid
.Как я могу это сделать?
Я ожидаю, что если я вызову другую службу в кластере через шлюз, я получу ответ 200 и правильный ответ, основанный на контроллере остальных приложений.