与简单版相比,整个的思路没有什么变化,不过网络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