|
@@ -9,6 +9,8 @@ import org.jboss.netty.channel.Channel;
|
|
|
import org.jboss.netty.channel.ChannelPipeline;
|
|
|
import org.jboss.netty.channel.ChannelPipelineFactory;
|
|
|
import org.jboss.netty.channel.Channels;
|
|
|
+import org.jboss.netty.channel.group.ChannelGroup;
|
|
|
+import org.jboss.netty.channel.group.DefaultChannelGroup;
|
|
|
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
|
|
|
|
|
import com.alibaba.otter.canal.common.AbstractCanalLifeCycle;
|
|
@@ -32,6 +34,7 @@ public class CanalServerWithNetty extends AbstractCanalLifeCycle implements Cana
|
|
|
private int port;
|
|
|
private Channel serverChannel = null;
|
|
|
private ServerBootstrap bootstrap = null;
|
|
|
+ private ChannelGroup childGroups = null; //socket channel container, used to close sockets explicitly.
|
|
|
|
|
|
private static class SingletonHolder {
|
|
|
|
|
@@ -40,6 +43,7 @@ public class CanalServerWithNetty extends AbstractCanalLifeCycle implements Cana
|
|
|
|
|
|
private CanalServerWithNetty(){
|
|
|
this.embeddedServer = CanalServerWithEmbedded.instance();
|
|
|
+ this.childGroups = new DefaultChannelGroup();
|
|
|
}
|
|
|
|
|
|
public static CanalServerWithNetty instance() {
|
|
@@ -55,6 +59,19 @@ public class CanalServerWithNetty extends AbstractCanalLifeCycle implements Cana
|
|
|
|
|
|
this.bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
|
|
|
Executors.newCachedThreadPool()));
|
|
|
+ /*
|
|
|
+ * enable keep-alive mechanism, handle abnormal network connection scenarios on OS level.
|
|
|
+ * the threshold parameters are depended on OS.
|
|
|
+ * e.g. On Linux:
|
|
|
+ * net.ipv4.tcp_keepalive_time = 300
|
|
|
+ * net.ipv4.tcp_keepalive_probes = 2
|
|
|
+ * net.ipv4.tcp_keepalive_intvl = 30
|
|
|
+ */
|
|
|
+ bootstrap.setOption("child.keepAlive", true);
|
|
|
+ /*
|
|
|
+ * optional parameter.
|
|
|
+ */
|
|
|
+ bootstrap.setOption("child.tcpNoDelay", true);
|
|
|
|
|
|
// 构造对应的pipeline
|
|
|
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
|
@@ -62,7 +79,8 @@ public class CanalServerWithNetty extends AbstractCanalLifeCycle implements Cana
|
|
|
public ChannelPipeline getPipeline() throws Exception {
|
|
|
ChannelPipeline pipelines = Channels.pipeline();
|
|
|
pipelines.addLast(FixedHeaderFrameDecoder.class.getName(), new FixedHeaderFrameDecoder());
|
|
|
- pipelines.addLast(HandshakeInitializationHandler.class.getName(), new HandshakeInitializationHandler());
|
|
|
+ //support to maintain child socket channel.
|
|
|
+ pipelines.addLast(HandshakeInitializationHandler.class.getName(), new HandshakeInitializationHandler(childGroups));
|
|
|
pipelines.addLast(ClientAuthenticationHandler.class.getName(),
|
|
|
new ClientAuthenticationHandler(embeddedServer));
|
|
|
|
|
@@ -87,6 +105,11 @@ public class CanalServerWithNetty extends AbstractCanalLifeCycle implements Cana
|
|
|
this.serverChannel.close().awaitUninterruptibly(1000);
|
|
|
}
|
|
|
|
|
|
+ //close sockets explicitly to reduce socket channel hung in complicated network environment.
|
|
|
+ if (this.childGroups != null) {
|
|
|
+ this.childGroups.close().awaitUninterruptibly(5000);
|
|
|
+ }
|
|
|
+
|
|
|
if (this.bootstrap != null) {
|
|
|
this.bootstrap.releaseExternalResources();
|
|
|
}
|