/**
*
*/
package com.taobao.top.analysis.node.connect;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.Executors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelDownstreamHandler;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelUpstreamHandler;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
import org.jboss.netty.handler.logging.LoggingHandler;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.logging.Log4JLoggerFactory;
import com.taobao.top.analysis.exception.AnalysisException;
import com.taobao.top.analysis.node.event.GetTaskResponseEvent;
import com.taobao.top.analysis.node.event.SendMonitorInfoResponseEvent;
import com.taobao.top.analysis.node.event.SendResultsResponseEvent;
import com.taobao.top.analysis.node.job.JobTask;
/**
* Socket版本的服务端通信组件
* @author fangweng
* @email: fangweng@taobao.com
* 2011-12-2 下午5:15:22
*
*/
public class SocketMasterConnector extends AbstractMasterConnector{
private static final Log logger = LogFactory.getLog(SocketMasterConnector.class);
ServerBootstrap bootstrap;
Channel serverChannel;
ChannelDownstreamHandler downstreamHandler;
ChannelUpstreamHandler upstreamHandler;
private static final ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
@Override
public void init() throws AnalysisException
{
InternalLoggerFactory.setDefaultFactory(new Log4JLoggerFactory());
bootstrap =
new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
ChannelPipeline pipe =
Channels.pipeline(
new ObjectEncoder(),
new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.weakCachingConcurrentResolver(this
.getClass().getClassLoader())), new MasterConnectorHandler(masterNode));
pipe.addLast("log", new LoggingHandler());
return pipe;
}
});
bootstrap.setOption("reuseAddress", true);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.setOption("child.receiveBufferSize", 8192 * 4); // 9753
bootstrap.setOption("child.sendBufferSize", 4096); // 8642
bootstrap.setOption("child.connectTimeoutMillis", 10000);
serverChannel = bootstrap.bind(new InetSocketAddress(config.getMasterPort()));
logger.info("SocketMasterConnector init now.");
}
public void openServer()
{
if (serverChannel != null)
{
releaseResource();
}
try {
init();
}
catch (AnalysisException e) {
logger.error("reinit server error", e);
}
}
@Override
public void releaseResource() {
try
{
serverChannel.close().awaitUninterruptibly();
bootstrap.getFactory().releaseExternalResources();
bootstrap.releaseExternalResources();
}
catch(Exception ex)
{
logger.error(ex,ex);
}
logger.info("SocketMasterConnector releaseResource now.");
}
@Override
public void echoGetJobTasks(final GetTaskResponseEvent event) {
ChannelFuture channelFuture = ((Channel)event.getChannel()).write(event);
// 这里的线程等待只是为了阻塞线程?
// try {
// channelFuture.await(10, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// }
channelFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if(future.isSuccess()) {
//warn的日志,打点为了对每轮执行情况进行观察
if (logger.isWarnEnabled())
{
List<JobTask> jobTasks = event.getJobTasks();
if (jobTasks != null && jobTasks.size() > 0)
{
StringBuilder sb = new StringBuilder("Send " + jobTasks.size() + " tasks to slave(" + future.getChannel().getRemoteAddress() + "), tasks : { ");
for(JobTask t : jobTasks)
{
sb.append("taskId:").append(t.getTaskId()).append(",");
sb.append("taskInput:").append(t.getInput()).append(";");
}
sb.append(" }");
logger.warn(sb.toString());
}
}
}
if (!future.isSuccess())
{
logger.error("Mastersocket write error.",future.getCause());
future.getChannel().close();
}
}
});
}
@Override
public void echoSendJobTaskResults(SendResultsResponseEvent event) {
ChannelFuture channelFuture = ((Channel)event.getChannel()).write(event);
// try {
// channelFuture.await(10, TimeUnit.SECONDS);
// } catch (InterruptedException e) {
// }
channelFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess())
{
logger.error("Mastersocket write error.",future.getCause());
future.getChannel().close();
}
}
});
}
@Override
public void echoSendMonitorInfo(SendMonitorInfoResponseEvent event) {
ChannelFuture channelFuture = ((Channel)event.getChannel()).write(event);
channelFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (!future.isSuccess())
{
logger.error("Mastersocket write error.",future.getCause());
future.getChannel().close();
}
}
});
}
public ChannelDownstreamHandler getDownstreamHandler() {
return downstreamHandler;
}
public void setDownstreamHandler(ChannelDownstreamHandler downstreamHandler) {
this.downstreamHandler = downstreamHandler;
}
public ChannelUpstreamHandler getUpstreamHandler() {
return upstreamHandler;
}
public void setUpstreamHandler(ChannelUpstreamHandler upstreamHandler) {
this.upstreamHandler = upstreamHandler;
}
}