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

与简单版相比,整个的思路没有什么变化,不过网络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>() {
				@Override
				protected 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);
		}
	}
	
	@Override
	public ConsumerHandler makeObject() throws Exception {
		ChannelFuture f = b.connect(host, port).sync();
		ConsumerHandler h = f.channel().pipeline().get(ConsumerHandler.class);
		return h;
	}

	@Override
	public void destroyObject(ConsumerHandler obj) throws Exception {
		obj.close();
		
	}

	@Override
	public boolean validateObject(ConsumerHandler obj) {
		if(obj != null) return true;
		return false;
	}

	@Override
	public void activateObject(ConsumerHandler obj) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public 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;
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		//System.out.println("通道建立");
		this.channel = ctx.channel();
	}


	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		RpcResponse response = (RpcResponse)msg;
		answer.offer(response, 3000, TimeUnit.MILLISECONDS);
	}
	
	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}
	
	@Override
	public 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];
	
	@Override
	protected 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值