阿里巴巴中间件性能挑战赛(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
- 阿里巴巴中间件性能挑战赛(RPC篇 复杂版)
- 阿里巴巴中间件性能挑战赛(RPC篇 同步阻塞模型)
- 阿里巴巴中间件性能挑战赛(MOM篇)
- 2015年阿里巴巴中间件比赛rpc框架
- [笔记]2016阿里中间件性能挑战赛(一)
- [笔记]2016阿里中间件性能挑战赛(二)
- [笔记]2016阿里中间件性能挑战赛(三)
- 第三届阿里中间件性能挑战赛 初赛记录及源码分享
- RPC中间件之Hessian
- 远程调用中间件(RPC)
- 中间件(RPC,CORBA,DCOM,web service等)
- 一起写RPC框架(二十七)RPC测试篇四---性能测试
- 高性能JSON库---FastJson(阿里巴巴)
- 高性能JSON库---FastJson(阿里巴巴)
- 大数据挑战赛(大佬篇)
- 阿里巴巴分布式数据库解决方案——Cobar中间件配置详解 (转)
- 消息中间件与RPC若干问题简析
- RPC、ORB、MOM三类中间件比较
- Listview中一些小的注意问题
- c#读取指定路径的配置文件
- OCiOS开发:地图与定位
- replaced element ,input,select
- test8.5
- 阿里巴巴中间件性能挑战赛(RPC篇 复杂版)
- 游戏中实现快速点击功能(即双击)
- 链表中倒数第k个节点
- strcpy和memcpy
- 延迟脚本
- 如何在action中访问servlet API
- jaxb注解
- 重载问题
- JavaScript高级程序设计之引用类型之Object 类型第5.1讲敏敏笔记