外籍客户找不到自定义注册的尤里卡服务

问题描述 投票:0回答:1

我将简要介绍我要实现的目标。我有一个Spring Boot应用程序,它是一个Eureka客户端,并将其注册为数据服务服务。在此应用程序启动之后(ApplicationReadeEvent.class),我还在注册另一个自定义创建的Eureka客户端,看来注册成功了。访问http://localhost:8761时,我可以看到该新注册的服务(工作流服务)。之所以决定在数据服务应用程序中执行此操作,是因为不需要该上下文,而仅在DEV环境中才需要它。后来代替它的是其他团队开发的真正的工作流服务。这里的问题是,当我尝试通过伪装的客户端访问此服务时,我收到异常:

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();
    }
}
spring-boot spring-cloud netflix-eureka spring-cloud-feign openfeign
1个回答
0
投票

仅通过设置虚拟主机名已解决。

newInstanceConfig.setVirtualHostname(workflowEngineApplicationName);
© www.soinside.com 2019 - 2024. All rights reserved.