loadbalanced功能区客户端初始化针对发现服务(尤里卡)

时间:2016-09-26 12:26:16

标签: spring-cloud netflix netflix-eureka spring-cloud-netflix netflix-ribbon

我有一个服务,它在应用程序启动后运行一些init脚本(用ApplicationListener<ApplicationReadyEvent>实现)。在这个脚本中,我需要使用RestTemplate调用另一个服务@LoadBalanced。当调用服务调用时,没有关于远程服务实例的信息,因为当时没有联系发现服务器(我猜)。

java.lang.IllegalStateException: No instances available for api-service
    at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:79)

在初始化脚本执行之前,如何在应用程序启动时从发现服务器获取可用服务列表?

由于

修改 问题与事实有关,在当前环境(dev)中,所有服务都在一个服务(api-service)中捆绑在一起。所以从api-service内部我试图调用@LoadBalanced客户端API服务而不了解自己?我可以注册一些听众或类似的东西,知道api-service(self)何时可用?

here是示例应用程序。我主要对如何工作this method

感兴趣

EDIT2:

现在可以有解决方案来创建EurekaListener

public static class InitializerListener implements EurekaEventListener {

    private EurekaClient eurekaClient;
    private RestOperations restTemplate;

    public InitializerListener(EurekaClient eurekaClient, RestOperations restTemplate) {
        this.eurekaClient = eurekaClient;
        this.restTemplate = restTemplate;
    }

    @Override
    public void onEvent(EurekaEvent event) {
        if (event instanceof StatusChangeEvent) {
            if (((StatusChangeEvent) event).getStatus().equals(InstanceInfo.InstanceStatus.UP)) {
                ResponseEntity<String> helloResponse = restTemplate.getForEntity("http://api-service/hello-controller/{name}", String.class, "my friend");
                logger.debug("Response from controller is {}", helloResponse.getBody());
                eurekaClient.unregisterEventListener(this);
            }
        }
    }
}

然后像这样注册:

EurekaEventListener initializerListener = new InitializerListener(discoveryClient, restTemplate);
discoveryClient.registerEventListener(initializerListener);

但是,这仅在应用程序第一次注册到发现服务时执行。下次当我停止api-service并再次运行它时,事件不会发布。还有其他事件我能抓到吗?

1 个答案:

答案 0 :(得分:4)

目前,在Camden及更早版本中,应用程序必须先在Eureka中注册,然后才能查询其他应用程序。您的通话可能在注册生命周期中过早。有一个InstanceRegisteredEvent可能会有所帮助。有计划在Dalston发布列车上进行此项工作。