Netty+Kryo实现高性能网络通信

netty 是 开源的基于java的网络通信框架,其中java对象的传输,netty使用的是java原生的序列化/反序列化实现的,而Kryo是性能更好的java序列化框架,能否让netty和kryo结合,实现高性能的数据通信呢?下面就是如何实现。

首先,模仿Netty自带的ObjectEncoder,写一个kryo序列化的ObjectEncoder:

import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferOutputStream;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;

public class ObjectKryoEncoder extends OneToOneEncoder {
	private static final byte[] LENGTH_PLACEHOLDER = new byte[4];
	
	@Override
	protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
        ChannelBufferOutputStream bout =
            new ChannelBufferOutputStream(dynamicBuffer(
                    4096, ctx.getChannel().getConfig().getBufferFactory()));
        bout.write(LENGTH_PLACEHOLDER);
        
        Kryo kryo = new Kryo();
        Output output = new Output(bout);
        kryo.writeClassAndObject(output, msg);
		output.flush();
		output.close();
		
        ChannelBuffer encoded = bout.buffer();
        encoded.setInt(0, encoded.writerIndex() - 4);
        return encoded;
	}
}

接下来,模仿Netty自带的ObjectDecoder,写一个kryo序列化的ObjectDecoder:

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferInputStream;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;

public class ObjectKryoDecoder extends LengthFieldBasedFrameDecoder {
    public ObjectKryoDecoder() {
        this(10485760);
    }

    public ObjectKryoDecoder(int maxObjectSize) {
    	super(maxObjectSize, 0, 4, 0, 4);
    }
    
    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
        ChannelBuffer frame = (ChannelBuffer) super.decode(ctx, channel, buffer);
        if (frame == null) {
            return null;
        }
        Kryo kryo = new Kryo();
		Input input = null;
		try {
			input = new Input(new ChannelBufferInputStream(frame));
			return kryo.readClassAndObject(input);
		} finally {
			input.close();
		}
    }
}

 以上的Encoder和Decoder都是kryo序列化的版本,将其注入ChannelPipelineFactory 中即可:

	ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
	bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
		public ChannelPipeline getPipeline() {
			ChannelPipeline pipeline = Channels.pipeline();
			pipeline.addLast("decoder", new ObjectKryoDecoder());
			pipeline.addLast("encoder", new ObjectKryoEncoder());
			pipeline.addLast("handler", new TimeClientHandler3());
			return pipeline;
		}
	});
......

猜你喜欢

转载自dreamworker.iteye.com/blog/1946100