如何解决当第一个尤里卡服务器关闭时,Spring Boot 应用程序不会启动
我有多个服务器的 Eureka 集群:
#ENV
EUREKA_URL=http://host1:8761/eureka/,http://host2:8761/eureka/,http://host3:8761/eureka/
#boostrap.yml
eureka:
client:
registryFetchIntervalSeconds: 5
serviceUrl:
defaultZone: ${EUREKA_URL:http://127.0.0.1:8761/eureka/}
万一,当 host1 关闭时,我的应用程序不会以异常启动:
13410 2021-01-14 11:28:34,994 ERROR [ main ] o.s.b.SpringApplication | Application run Failed
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://host1:8761/eureka/apps/": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:748)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:583)
at org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient.getApplicationsInternal(RestTemplateEurekaHttpClient.java:154)
at org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient.getApplications(RestTemplateEurekaHttpClient.java:142)
at org.springframework.cloud.netflix.eureka.config.EurekaconfigserverBootstrapConfiguration.lambda$eurekaconfigserverInstanceProvider$0(EurekaconfigserverBootstrapConfiguration.java:112)
at org.springframework.cloud.config.client.configserverInstanceProvider.getconfigserverInstances(configserverInstanceProvider.java:50)
at org.springframework.cloud.config.client.configserverInstanceProvider$$FastClassBySpringcglib$$facbf882.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.invokeJoinpoint(cglibAopProxy.java:771)
at
这对我来说很奇怪,因为我预计 eureka 会尝试连接到其他服务器,但事实并非如此。我在 spring-cloud-netflix-eureka-client-2.2.3.RELEASE.jar
中找到了它:
// EurekaconfigserverBootstrapConfiguration.java
private String getEurekaUrl(EurekaClientConfigBean config) {
List<String> urls = EndpointUtils.getServiceUrlsFromConfig(config,EurekaClientConfigBean.DEFAULT_ZONE,true);
return urls.get(0);
}
和
// DefaultEurekaClientConfig.java
@Override
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = configInstance.getStringProperty(
namespace + CONfig_EUREKA_SERVER_SERVICE_URL_PREFIX + "." + myZone,null).get();
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = configInstance.getStringProperty(
namespace + CONfig_EUREKA_SERVER_SERVICE_URL_PREFIX + ".default",null).get();
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(URL_SEParaTOR));
}
return new ArrayList<String>();
}
最后:
// RestTemplateEurekaHttpClient.java
private EurekaHttpResponse<Applications> getApplicationsInternal(String urlPath,String[] regions) {
String url = serviceUrl + urlPath;
if (regions != null && regions.length > 0) {
url = url + (urlPath.contains("?") ? "&" : "?") + "regions="
+ StringUtil.join(regions);
}
// There is no exception handling here and above!
ResponseEntity<EurekaApplications> response = restTemplate.exchange(url,HttpMethod.GET,null,EurekaApplications.class);
return anEurekaHttpResponse(response.getStatusCodeValue(),response.getStatusCode().value() == HttpStatus.OK.value()
&& response.hasBody() ? (Applications) response.getBody() : null)
.headers(headersOf(response)).build();
}
我有 java11
、springBootVersion = '2.3.4.RELEASE'
、spring-cloud-netflix-eureka-client-2.2.3.RELEASE
、eureka-client-1.9.21
。
我怎样才能让尤里卡在第一台服务器注册失败的情况下继续在后面的服务器上尝试?有什么想法吗?
解决方法
我找到了解决方法。 我只是覆盖 bean:
@Slf4j
@Configuration
public class EurekaMultiClientBoostrapConfig {
@Bean
@Primary
public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(EurekaClientConfigBean config) {
List<String> urls = EndpointUtils.getServiceUrlsFromConfig(config,EurekaClientConfigBean.DEFAULT_ZONE,true);
for (String url : urls) {
try {
RestTemplateEurekaHttpClient client = (RestTemplateEurekaHttpClient) new RestTemplateTransportClientFactory()
.newClient(new DefaultEndpoint(url));
client.getApplications(config.getRegion());
log.info("Registered on Eureka host '{}' is successful.",url);
return client;
} catch (Exception e) {
log.warn("Eureka host '{}' is unavailable(reason: {})",url,e.getMessage());
}
}
throw new IllegalStateException("Failed to register on any eureka host.");
}
附言由于此配置属于 Bootstrap 配置,所以不要忘记在 resources/META-INF/spring.factories
org.springframework.cloud.bootstrap.BootstrapConfiguration=your.app.package.EurekaMultiClientBoostrapConfig
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。