阿里巴巴中间件性能挑战赛(RPC篇 复杂版)

来源:互联网 发布:淘宝店铺没流量没访客 编辑:程序博客网 时间:2024/06/05 06:39

与简单版相比,整个的思路没有什么变化,不过网络io模型换成了netty,同时使用了fst序列化库

//调用方法的协议:方法名  参数类型  参数值  上下文    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable     {    if(isAsyn(method.getName())) return null; //本方法是同步方法,被异步调用则返回空    RpcRequest request = new RpcRequest(method.getName(),method.getParameterTypes(),args,RpcContext.localMap.get());    consumerHook.before(request);ConsumerHandler handler = consumerHandlerPool.getConsumerHandler();RpcResponse response = handler.sendRpcRequest(request);Object result = response.getAppResponse();if(result instanceof Throwable){InvocationTargetException targetEx =  (InvocationTargetException)result;Throwable t = targetEx .getTargetException();throw t;}consumerHandlerPool.recycleHandler(handler);return result;    }

最核心的代码是

ConsumerHandler handler = consumerHandlerPool.getConsumerHandler();RpcResponse response = handler.sendRpcRequest(request);
从consumerHandlerPool中拿到handler然后利用handler向服务器端发送请求,并且同步等待请求结果的返回


ConsumerHandlerPool代码如下:

package com.alibaba.middleware.race.rpc.api.impl;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.PooledByteBufAllocator;import io.netty.channel.AdaptiveRecvByteBufAllocator;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import org.apache.commons.pool.PoolableObjectFactory;import org.apache.commons.pool.impl.GenericObjectPool;public class ConsumerHandlerPool implements PoolableObjectFactory<ConsumerHandler>{private GenericObjectPool<ConsumerHandler> pool; private EventLoopGroup group;private Bootstrap b;private String host;private int port;public ConsumerHandlerPool(String host,int port) {try{int coreCount = Runtime.getRuntime().availableProcessors()*2;this.host = host;this.port = port;pool = new GenericObjectPool<ConsumerHandler>(this);group = new NioEventLoopGroup();b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true).option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT).option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new FstDecoder(4096));ch.pipeline().addLast(new FstEncoder());ch.pipeline().addLast(new ConsumerHandler());}});for(int i = 0;i < coreCount ; i++)pool.addObject();System.out.println("初始化完成");}catch(Exception e){e.printStackTrace();}}public ConsumerHandler getConsumerHandler() throws Exception{return pool.borrowObject();}public void recycleHandler(ConsumerHandler h) throws Exception{if(h != null){pool.returnObject(h);}}@Overridepublic ConsumerHandler makeObject() throws Exception {ChannelFuture f = b.connect(host, port).sync();ConsumerHandler h = f.channel().pipeline().get(ConsumerHandler.class);return h;}@Overridepublic void destroyObject(ConsumerHandler obj) throws Exception {obj.close();}@Overridepublic boolean validateObject(ConsumerHandler obj) {if(obj != null) return true;return false;}@Overridepublic void activateObject(ConsumerHandler obj) throws Exception {// TODO Auto-generated method stub}@Overridepublic void passivateObject(ConsumerHandler obj) throws Exception {// TODO Auto-generated method stub}}

建立了一个连接池,配置好netty参数并且在池子里面放置了一定数量的ConsumerHandler


ConsumerHandler代码如下

package com.alibaba.middleware.race.rpc.api.impl;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.TimeUnit;import com.alibaba.middleware.race.rpc.model.RpcRequest;import com.alibaba.middleware.race.rpc.model.RpcResponse;import io.netty.channel.Channel;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class ConsumerHandler extends ChannelInboundHandlerAdapter {private final BlockingQueue<RpcResponse> answer = new LinkedBlockingQueue<RpcResponse>(); private volatile Channel channel;@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {//System.out.println("通道建立");this.channel = ctx.channel();}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {RpcResponse response = (RpcResponse)msg;answer.offer(response, 3000, TimeUnit.MILLISECONDS);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.flush();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {cause.printStackTrace();ctx.close();}public RpcResponse sendRpcRequest(RpcRequest request){channel.writeAndFlush(request);RpcResponse response;boolean interrupted = false;for(;;){try{response = answer.take();break;}catch(InterruptedException e){interrupted = true;}}if (interrupted) {  Thread.currentThread().interrupt();  } return response;}public void close() throws Exception{this.channel.close().sync();}}

用了一个BlockingQueue来拿netty返回的结果(其实这里用synchronized也一样)。


由于netty没有预先实现好的fst编解码器,因此需要自己实现fst编解码器


FstEncoder

package com.alibaba.middleware.race.rpc.api.impl;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.MessageToByteEncoder;public class FstEncoder  extends MessageToByteEncoder<Object>{private static final byte[] LENGTH_PLACEHOLDER = new byte[4];@Overrideprotected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)throws Exception {int lengthPos = out.writerIndex();out.writeBytes(LENGTH_PLACEHOLDER);out.writeBytes(FstUtil.objectToByte(msg));out.setInt(lengthPos, out.writerIndex() - lengthPos - 4);}}

FstDecoder:

package com.alibaba.middleware.race.rpc.api.impl;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.LengthFieldBasedFrameDecoder;public class FstDecoder extends LengthFieldBasedFrameDecoder{public FstDecoder(int maxObjectSize){super(maxObjectSize, 0, 4, 0, 4);}@Override    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {        ByteBuf frame = (ByteBuf) super.decode(ctx, in);        if (frame == null) {            return null;        }        byte[] out = new byte[frame.readableBytes()];        frame.readBytes(out);        return FstUtil.byteToObject(out);    }    @Override    protected ByteBuf extractFrame(ChannelHandlerContext ctx, ByteBuf buffer, int index, int length) {        return buffer.slice(index, length);    }}



最后贴出完整代码的链接:

https://github.com/xiefan46/rpc




0 0
原创粉丝点击