- Java 1.8
- Canal 1.1.7
- Server 和 Client在同一台机器上
Canal Server运行一段时间后,触发“Connection reset by peer”,且客户端重新连接也无法解决问题,直至Canal Server端宕机。重启Canal Server可立即解决问题。
看了很多issue说是处理空闲连接超时,作者和其他同学给的解决方案是:
- 做好重试。
- 加大空闲连接超时时间。
疑问:
- 重试并没起到作用(详见下面的代码)
- 为何加大空闲连接超时时间可以解决这个问题?连接如若实际不可用,不是应该缩短空闲连接超时时间,以尽早释放无效连接从而建立新的连接吗?如果加大超时时间可以消掉这个错,为何客户端SDK不直接设置成永不超时,内部消化掉?
Server 端的日志和实际表现上看,当Connection reset by peer触发一段时间后,Server端就自动停机了,Server是不是因为这个错停机,无任何可供排查的日志。
代码案例public class CanalConsumer {
private volatile boolean isRunning;
private volatile boolean isConnected;
private final CanalConnector connector;
//...初始化代码
public synchronized void start() {
if (isRunning) {
return;
}
this.isRunning = true;
new Thread(this::run, "canal-consumer").start();
}
private void run() {
while(isRunning) {
try {
connect()
Message message = connector.getWithoutAck(1024);
long batchId = message.getId();
List<CanalEntry.Entry> entries = message.getEntries();
if (batchId != -1 && entries != null && !entries.isEmpty()) {
// 消费数据
}
connector.ack(batchId);
} catch(Exception e) {
// 只要出现Canal客户端异常都会断开连接并在下一次触发重新连接
if (e instanceof CanalClientException) {
try {
disconnect()
} catch(CanalClientException ex) {
log.error("failed", ex);
}
}
}
}
}
private void connect() {
if (isConnected) {
return;
}
connector.connect();
connector.subscribe("xxx");
isConnected = true;
}
private void disconnect() {
if(!isConnected) {
return;
}
isConnected = false;
connector.disconnect();
}
}