Feign Client не может найти зарегистрированный пользовательский сервис eureka - PullRequest
0 голосов
/ 27 октября 2019

Я расскажу немного о том, чего я пытаюсь достичь. У меня есть весеннее загрузочное приложение, которое является клиентом Eureka и регистрируется как служба данных. После запуска этого приложения (ApplicationReadeEvent.class) я регистрирую еще один клиент Eureka, созданный пользователем, и, кажется, регистрация прошла успешно. Я вижу эту недавно зарегистрированную службу (workflow-service) при доступе к http://localhost:8761.. Причина, по которой я решил сделать это внутри приложения службы данных, заключается в том, что мне не нужно это вне этого контекста, и оно мне нужнотолько в среде DEV. Позже вместо него был бы подключен настоящий workflow-сервис, разработанный другой командой. Проблема здесь в том, что когда я пытаюсь получить доступ к этой услуге через симулируемого клиента, я получаю исключение:

com.netflix.client.ClientException: Load balancer does not have available server for client: workflow-service

enter image description here

Вот мойкод регистрации пользовательской службы:

package XXX;

import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.HttpRequest;
import org.mockserver.model.HttpResponse;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtilsProperties;
import org.springframework.cloud.netflix.eureka.*;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;

import java.net.SocketException;

@Configuration
@ConditionalOnExpression("${workflow.engine.mock.enabled:false}")
public class MockWorkflowEngineConfiguration {

    @Value("${workflow.engine.mock.application.name}") private String workflowEngineApplicationName;
    @Value("${workflow.engine.mock.application.port}") private Integer workflowEnginePort;

    @Autowired private EurekaInstanceConfigBean originalInstanceConfig;
    @Autowired private EurekaClientConfigBean originalClientConfig;
    @Autowired private ApplicationInfoManager applicationInfoManager;
    @Autowired private ApplicationContext applicationContext;
    @Autowired private ApplicationEventPublisher applicationEventPublisher;
    @Autowired private ObjectProvider<HealthCheckHandler> healthCheckHandler;
    @Autowired private EurekaServiceRegistry eurekaServiceRegistry;

    private EurekaRegistration workflowEngineEurekaRegistration;
    private DiscoveryClient workflowEngineDiscoveryClient;
    private ClientAndServer workflowEngineMockClient;

    @EventListener(ApplicationReadyEvent.class)
    public void initializeMockWorkflowEngine() throws SocketException{
        workflowEngineDiscoveryClient = new CloudEurekaClient(
                        createWorkflowEngineAppInfoManager(),
                        duplicateEurekaClientConfig(),
                        applicationEventPublisher);

        workflowEngineEurekaRegistration = EurekaRegistration.builder((CloudEurekaInstanceConfig) workflowEngineDiscoveryClient.getApplicationInfoManager().getEurekaInstanceConfig())
                .with(workflowEngineDiscoveryClient)
                .with(workflowEngineDiscoveryClient.getApplicationInfoManager())
                .with(healthCheckHandler).build();

        eurekaServiceRegistry.register(workflowEngineEurekaRegistration);

        workflowEngineMockClient = new ClientAndServer(workflowEnginePort);

        workflowEngineMockClient.when(
                HttpRequest.request()
                    .withMethod("GET")
                    .withPath("/job")
        )
        .respond(
                HttpResponse.response()
                .withStatusCode(200)
                .withBody("{ id: '1', name: 'default'}")
        );
    }

    @EventListener(ContextClosedEvent.class)
    public void shutdownMockWorkflowEngine(){
        workflowEngineDiscoveryClient.shutdown();
        eurekaServiceRegistry.deregister(workflowEngineEurekaRegistration);
        workflowEngineMockClient.stop(true);
    }

    private ApplicationInfoManager createWorkflowEngineAppInfoManager() throws SocketException {
        EurekaInstanceConfigBean newInstanceConfig =
                new EurekaInstanceConfigBean(new InetUtils(new InetUtilsProperties()));

        newInstanceConfig.setEnvironment(applicationContext.getEnvironment());
        newInstanceConfig.setAppname(workflowEngineApplicationName);
        newInstanceConfig.setInstanceId(applicationInfoManager.getInfo().getHostName() + ":" + workflowEngineApplicationName + ":" + workflowEnginePort);
        newInstanceConfig.setInitialStatus(InstanceInfo.InstanceStatus.UP);
        newInstanceConfig.setNonSecurePortEnabled(originalInstanceConfig.isNonSecurePortEnabled());
        newInstanceConfig.setNonSecurePort(workflowEnginePort);
        newInstanceConfig.setHostname(applicationInfoManager.getInfo().getHostName());
        newInstanceConfig.setSecurePortEnabled(originalInstanceConfig.isSecurePortEnabled());
        newInstanceConfig.setSecurePort(originalInstanceConfig.getSecurePort());
        newInstanceConfig.setDataCenterInfo(originalInstanceConfig.getDataCenterInfo());
        newInstanceConfig.setHealthCheckUrl(originalInstanceConfig.getHealthCheckUrl());
        newInstanceConfig.setSecureHealthCheckUrl(originalInstanceConfig.getSecureHealthCheckUrl());
        newInstanceConfig.setHomePageUrl(originalInstanceConfig.getHomePageUrl());
        newInstanceConfig.setStatusPageUrl(originalInstanceConfig.getStatusPageUrl());
        newInstanceConfig.setStatusPageUrlPath(originalInstanceConfig.getStatusPageUrlPath());
        newInstanceConfig.setIpAddress(originalInstanceConfig.getIpAddress());
        newInstanceConfig.setPreferIpAddress(originalInstanceConfig.isPreferIpAddress());

        ApplicationInfoManager manager =
                new ApplicationInfoManager(newInstanceConfig, (ApplicationInfoManager.OptionalArgs) null);

        return manager;
    }

    private EurekaClientConfigBean duplicateEurekaClientConfig() {
        EurekaClientConfigBean newConfig = new EurekaClientConfigBean();
        newConfig.setFetchRegistry(false);
        newConfig.setEurekaServerPort(originalClientConfig.getEurekaServerPort());
        newConfig.setAllowRedirects(originalClientConfig.isAllowRedirects());
        newConfig.setAvailabilityZones(originalClientConfig.getAvailabilityZones());
        newConfig.setBackupRegistryImpl(originalClientConfig.getBackupRegistryImpl());
        newConfig.setServiceUrl(originalClientConfig.getServiceUrl());
        return newConfig;
    }
}

А вот мой код клиентского симуляции:

@FeignClient(name = "workflow-service", configuration = FeignClientConfiguration.class)
public interface WorkflowService {
    @RequestMapping(value = "/job", method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<List<WorkflowJobDTO>> listJobs();

Вот пример использования симулированного клиента, с помощью которого я пытаюсь получить доступ к другому сервису:

@GetMapping(path = "/workflow-jobs", produces = "application/json")
    public ResponseEntity<List<WorkflowJobDTO>> getAllJobs() {
        return workflowService.listJobs();
    }
}

1 Ответ

0 голосов
/ 28 октября 2019

Это было исправлено путем установки имени виртуального хоста.

newInstanceConfig.setVirtualHostname(workflowEngineApplicationName);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...