Я расскажу немного о том, чего я пытаюсь достичь. У меня есть весеннее загрузочное приложение, которое является клиентом 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](https://i.stack.imgur.com/OsoFd.png)
Вот мойкод регистрации пользовательской службы:
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();
}
}