背景
spring cloud Hoxton.SR1
微服务多实例发布时,通过Ribbon实现的重试机制,在停掉一个服务之后并没有触发重试机制;
我的主要配置(服务的消费者)
ribbon:
eager-load:
enabled: true
ReadTimeout: 10000 # 获取到响应内容的超时时间
ConnectTimeout: 2000 # 连接超时时间
MaxAutoRetries: 0 # 在当前服务重试的次数
MaxAutoRetriesNextServer: 1 # "默认轮询去重选列表中服务" 的次数
OkToRetryOnAllOperations: false #是否所有操作都重试 (默认false) 非GET方式请求,只有ConnectException 才会进行重试
测试发现一个服务的提供者突然停止后,通过feign远程调用,并没有进行重试,而是直接降级处理;
于是,我关闭了降级处理,让控制台把错误抛出来看看。
结果发现错误是 java.net.SocketTimeoutException: connect timed out
测试
**自己写段代码在windows上测试了一下:
public static void main(String[] args) throws InterruptedException {
ConcurrentHashMap<Integer, Object> c = new ConcurrentHashMap<>(1000);
//设置超时时间 (单位:ms)
final int timeout = 2000;
for(int i=0; i<1000; i++){
int ii =i;
new Thread(new Runnable() {
@Override
public void run() {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress("127.0.0.1", 8080), timeout);
} catch (IOException e) {
if (e instanceof ConnectException){
System.out.println(ii + e.getClass().getName() + ": " + e.getMessage());
}else{
System.err.println(ii + e.getClass().getName() + ": " + e.getMessage());
c.put(ii,e.getClass().getName() + ": " + e.getMessage());
}
}
}
}).start();
}
//等他执行一会
TimeUnit.SECONDS.sleep(10);
System.out.println("非ConnectException的数量: " + c.size());
// SpringApplication.run(NnhxOrderApplication.class, args);
}
当timeout设置为 2000ms 时:
几乎很少出现符合重试机制要求的ConnectException了
当timeout设置为 2050ms 时:
现在已经全部都是ConnectException了
打了个jar包,在阿里云服务器CentOS上测试(timeout=2050)
也全部都是ConnectException
于是又在centos上分别测试了 timout为2000、1000、500
结果全部也都是 ConnectException
这确实是个比较有意思的现象,大家觉得呢?
在windows上修改 ribbon.ConnectTimeout: 2050
测试发现,现在的确可以重试了;
针对此问题可以关注github:
issues: SocketTimeoutException(connect time out) is not judged as a ConnectionException:
https://github.com/Netflix/ribbon/issues/359