инициализация ленточного клиента с балансировкой нагрузки и службой обнаружения (эврика)

У меня есть служба, которая запускает некоторые сценарии инициализации после запуска приложения (реализовано с помощью ApplicationListener<ApplicationReadyEvent>). В этих сценариях мне нужно вызвать другие службы с RestTemplate, который равен @LoadBalanced. Когда вызывается вызов службы, нет информации об экземплярах удаленной службы, потому что к серверу обнаружения в то время не обращались (я полагаю).

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

Итак, есть ли способ получить список доступных служб с сервера обнаружения при запуске приложения, прежде чем мой сценарий инициализации будет выполнен?

Спасибо

edit: Проблема больше связана с тем, что в текущей среде (dev) все службы связаны в одну службу (api-service). Итак, изнутри api-service я пытаюсь вызвать @LoadBalanced client api-service, который не знает о себе? Могу ли я зарегистрировать слушателя или что-то подобное, чтобы знать, когда будет доступен api-service (self)?

здесь являются примерами приложений. Меня в основном интересует, как работать этот метод

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 и снова запустил ее, событие не публикуется. Есть ли еще какое-нибудь событие, которое я могу поймать?


person bilak    schedule 26.09.2016    source источник


Ответы (1)


В настоящее время в Camden и ранее приложения должны быть зарегистрированы в Eureka, прежде чем они смогут запрашивать другие приложения. Ваш звонок, скорее всего, находится на слишком ранней стадии жизненного цикла регистрации. Есть InstanceRegisteredEvent, который может помочь. Есть планы поработать над этим в выпуске Dalston.

person spencergibb    schedule 26.09.2016
comment
даже когда я меняю событие на InstanceRegisteredEvent, я получаю то же исключение (экземпляров нет - я отправил это на github). Что еще может мне помочь? Я вижу, что объект конфигурации из события может быть преобразован в EurekaInstanceConfigBean, и оттуда я могу получить IP-адрес и порт целевой службы, но я думаю, что в этом случае я не могу использовать шаблон отдыха @LoadBalanced. Если я могу чем-то помочь вам разобраться в этой проблеме, дайте мне знать. Мне нужно, чтобы эта функция была в текущем проекте. Спасибо - person bilak; 27.09.2016
comment
Я создал слушателя (см. Отредактированный вопрос), но есть проблема, что он не выполняется каждый раз при перезапуске приложения. - person bilak; 27.09.2016
comment
Можно ли прослушивать какое-либо событие, которое вызывается каждый раз, когда приложение регистрируется на сервере реестра? - person bilak; 30.09.2016