优化老项目服务启停导致的调用已停止服务的问题。启用EurekaNotificationServerListUpdater会出现一些问题,以下为跟踪过程以及目前可用的解决办法。
前置环境
springclound+springboot
<version.springboot>1.5.11.RELEASE</version.springboot>
<version.springcloud>Edgware.SR5</version.springcloud>
问题场景
使用EurekaNotificationServerListUpdater,但是在使用过程中,发现一旦启动该类,就会出现服务列表已更新,但是请求还会打到已关闭服务,进而出现问题。
服务A -》eureka-》 服务B (多节点101,102,103)
问题描述:
1.服务A-controller请求多次服务b的服务(正常)
2.关闭某个服务b节点(103),并使用以下代码打出eureka服务清单
public String getServices() {
List<String> services = discoveryClient.getServices();
StringBuilder stringBuilder = new StringBuilder();
for (String service : services) {
List<ServiceInstance> instances = discoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
stringBuilder.append("Service: ").append(service)
.append(", host: ").append(instance.getHost())
.append(", port: ").append(instance.getPort())
.append(", serviceId: ").append(instance.getServiceId())
.append(", uri: ").append(instance.getUri())
.append(", isSecure: ").append(instance.isSecure())
.append("\n");
}
}
return stringBuilder.toString();
}
服务清单:
Service: trade-service, host: 172.27.2.101, port: 8021, serviceId: TRADE-SERVICE, uri: http://172.27.2.101:8021, isSecure: false
Service: trade-service, host: 172.27.2.102, port: 8021, serviceId: TRADE-SERVICE, uri: http://172.27.2.102:8021, isSecure: false
3.如果此时继续访问,则基本3次访问会出现以下异常,推测虽然刷新列表,但是某个地方还存在缓存,并没有成功刷新。
而且在EurekaNotificationServerListUpdater中的监听器打断点,发现断点并未执行。
异常信息:
feign.RetryableException: Connection refused (Connection refused) executing GET http://trade-service/xxx/xxxxx
at feign.FeignException.errorExecuting(FeignException.java:67)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:104)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at .......
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:607)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
at sun.net.www.http.HttpClient.New(HttpClient.java:339)
at sun.net.www.http.HttpClient.New(HttpClient.java:357)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1229)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1165)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1059)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:993)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1343)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1318)
at feign.Client$Default.convertAndSend(Client.java:133)
at feign.Client$Default.execute(Client.java:73)
问题排查:
1.由于该问题相对而言比较严重,由此推测,可能原作者已进行相关代码修正。
由于项目中使用的是springcloud 决定先升级到最新的小版本试试。
<version.springboot>1.5.11.RELEASE</version.springboot>
<version.springcloud>Edgware.SR3</version.springcloud>
2.后查找到Edgware 版本最多存在Edgware6
Spring-Cloud-Edgware-Release-Notes
3.调整为Edgware.SR6 依次进行下降,重复上述实验。在SR5-SR6 该问题不会复现。
4.通过对比SR3-SR6引入的jar进行版本对比,看看那些jar进行了升级
由于EurekaNotificationServerListUpdater中的listener注册到eurekaclients上,所以推测可能client的包存在问题
5.接着下载client的源码,查到当时的git提交日志,发现了这个
这个就是导致无法正确的更新的代码
问题解决
如果你也与我使用的为springclound 尽可能升级到Edgware.SR5-Edgware.SR6;
如果单独引用,则需要确保spring-cloud-netflix-eureka-client:1.4.6版本及以上