# 客户端连接管理
package com.bfxy.rapid.rpc.client;
import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.bfxy.rapid.rpc.codec.RpcRequest;
import com.bfxy.rapid.rpc.codec.RpcResponse;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* $RpcClientHandler 实际的业务处理器(Handler)
* @author 17475
*
*/
public class RpcClientHandler extends SimpleChannelInboundHandler<RpcResponse> {
private Channel channel;
private SocketAddress remotePeer;
private Map<String /*requestId*/, RpcFuture> pendingRpcTable = new ConcurrentHashMap<String, RpcFuture>();
public Channel getChannel() {
return channel;
}
/**
* 通道激活的时候触发此方法
*/
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
super.channelRegistered(ctx);
this.channel = ctx.channel();
}
/**
* 通道激活的时候触发此方法
*/
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
this.remotePeer = this.channel.remoteAddress();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RpcResponse rpcResponse) throws Exception {
String requestId = rpcResponse.getRequestId();
RpcFuture rpcFuture = pendingRpcTable.get(requestId);
if(rpcFuture != null) {
pendingRpcTable.remove(requestId);
rpcFuture.done(rpcResponse);
}
}
public SocketAddress getRemotePeer() {
return this.remotePeer;
}
/**
* Netty提供了一种主动关闭连接的方式.发送一个Unpooled.EMPTY_BUFFER 这样我们的ChannelFutureListener的close事件就会监听到并关闭通道
*/
public void close() {
channel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
/**
* 异步发送请求方法
* @param request
* @return
*/
public RpcFuture sendRequest(RpcRequest request) {
RpcFuture rpcFuture = new RpcFuture(request);
pendingRpcTable.put(request.getRequestId(), rpcFuture);
channel.writeAndFlush(request);
return rpcFuture;
}
}
-----------------------------------------------------------------------
@Slf4j
public class RpcConnectManager {
// private static volatile RpcConnectManager RPC_CONNECT_MANAGER = new RpcConnectManager();
public RpcConnectManager() {
}
/* 一个连接的地址,对应一个实际的业务处理器(client) */
private Map<InetSocketAddress, RpcClientHandler> connectedHandlerMap = new ConcurrentHashMap<InetSocketAddress, RpcClientHandler>();
/* 所有连接成功的地址 所对应的 任务执行器列表 connectedHandlerList */
private CopyOnWriteArrayList<RpcClientHandler> connectedHandlerList = new CopyOnWriteArrayList<RpcClientHandler>();
/* 用于异步的提交连接请求的线程池 */
private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(16, 16, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(65536));
private EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);
private ReentrantLock connectedLock = new ReentrantLock();
private Condition connectedCondition = connectedLock.newCondition();
private long connectTimeoutMills = 6000;
private volatile boolean isRunning = true;
private volatile AtomicInteger handlerIdx = new AtomicInteger(0);
//1. 异步连接 线程池 真正的发起连接,连接失败监听,连接成功监听
//2. 对于连接进来的资源做一个缓存(做一个管理)updateConnectedServer
/**
* $connect 发起连接方法
* @param serverAddress
*/
public void connect(final String serverAddress) {
List<String> allServerAddress = Arrays.asList(serverAddress.split(","));
updateConnectedServer(allServerAddress);
}
/**
* add connect List<String> serverAddress
* @param serverAddress
*/
public void connect(List<String> serverAddress) {
updateConnectedServer(serverAddress);
}
/**
* $更新缓存信息 并 异步发起连接
* 192.168.11.111:8765,192.168.11.112:8765
* @param allServerAddress
*/
public void updateConnectedServer(List<String> allServerAddress) {
if(CollectionUtils.isNotEmpty(allServerAddress)) {
// 1.解析allServerAddress地址 并且临时存储到我们的newAllServerNodeSet HashSet集合中
HashSet<InetSocketAddress> newAllServerNodeSet = new HashSet<InetSocketAddress>();
for(int i =0; i < allServerAddress.size(); i++) {
String[] array = allServerAddress.get(i).split(":");
if(array.length == 2) {
String host = array[0];
int port = Integer.parseInt(array[1]);
final InetSocketAddress remotePeer = new InetSocketAddress(host, port);
newAllServerNodeSet.add(remotePeer);
}
}
// 2.调用建立连接方法 发起远程连接操作
for(InetSocketAddress serverNodeAddress : newAllServerNodeSet) {
if(!connectedHandlerMap.keySet().contains(serverNodeAddress)) {
connectAsync(serverNodeAddress);
}
}
// 3. 如果allServerAddress列表里不存在的连接地址,那么我需要从缓存中进行移除
for(int i = 0; i< connectedHandlerList.size(); i++) {
RpcClientHandler rpcClientHandler = connectedHandlerList.get(i);
SocketAddress remotePeer = rpcClientHandler.getRemotePeer();
if(!newAllServerNodeSet.contains(remotePeer)) {
log.info(" remove invalid server node " + remotePeer);
RpcClientHandler handler = connectedHandlerMap.get(remotePeer);
if(handler != null) {
handler.close();
connectedHandlerMap.remove(remotePeer);
}
connectedHandlerList.remove(rpcClientHandler);
}
}
} else {
// 添加告警
log.error(" no available server address! ");
// 清除所有的缓存信息
clearConnected();
}
}
/**
* $connectAsync 异步发起连接的方法
* @param serverNodeAddress
*/
private void connectAsync(InetSocketAddress remotePeer) {
threadPoolExecutor.submit(new Runnable() {
@Override
public void run() {
Bootstrap b = new Bootstrap();
b
.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new RpcClientInitializer());
connect(b, remotePeer);
}
});
}
private void connect(final Bootstrap b, InetSocketAddress remotePeer) {
// 1.真正的建立连接
final ChannelFuture channelFuture = b.connect(remotePeer);
// 2.连接失败的时候添加监听 清除资源后进行发起重连操作
channelFuture.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
log.info("channelFuture.channel close operationComplete, remote peer =" + remotePeer);
future.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
log.warn(" connect fail, to reconnect! ");
clearConnected();
connect(b, remotePeer);
}
}, 3, TimeUnit.SECONDS);
}
});
// 3.连接成功的时候添加监听 把我们的新连接放入缓存中
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
log.info("successfully connect to remote server, remote peer = " + remotePeer);
RpcClientHandler handler = future.channel().pipeline().get(RpcClientHandler.class);
addHandler(handler);
}
}
});
}
/**
* $clearConnected
* 连接失败时,及时的释放资源,清空缓存
* 先删除所有的connectedHandlerMap中的数据
* 然后再清空connectedHandlerList中的数据
*/
private void clearConnected() {
for(final RpcClientHandler rpcClientHandler : connectedHandlerList) {
// 通过RpcClientHandler 找到具体的remotePeer, 从connectedHandlerMap进行移除指定的 RpcClientHandler
SocketAddress remotePeer = rpcClientHandler.getRemotePeer();
RpcClientHandler handler = connectedHandlerMap.get(remotePeer);
if(handler != null) {
handler.close();
connectedHandlerMap.remove(remotePeer);
}
}
connectedHandlerList.clear();
}
/**
* $addHandler 添加RpcClientHandler到指定的缓存中
* connectedHandlerMap & connectedHandlerList
*
* @param handler
*/
private void addHandler(RpcClientHandler handler) {
connectedHandlerList.add(handler);
InetSocketAddress remoteAddress = //(InetSocketAddress) handler.getRemotePeer();
(InetSocketAddress) handler.getChannel().remoteAddress();
connectedHandlerMap.put(remoteAddress, handler);
//signalAvailableHandler 唤醒可用的业务执行器
signalAvailableHandler();
}
/**
* 唤醒另外一端的线程(阻塞的状态中) 告知有新连接接入
*/
private void signalAvailableHandler() {
connectedLock.lock();
try {
connectedCondition.signalAll();
} finally {
connectedLock.unlock();
}
}
/**
* $waitingForAvailableHandler 等待新连接接入通知方法
* @return
* @throws InterruptedException
*/
private boolean waitingForAvailableHandler() throws InterruptedException {
connectedLock.lock();
try {
return connectedCondition.await(this.connectTimeoutMills, TimeUnit.MICROSECONDS);
} finally {
connectedLock.unlock();
}
}
/**
* $chooseHandler 选择一个实际的业务处理器
* @return RpcClientHandler
*/
public RpcClientHandler chooseHandler() {
CopyOnWriteArrayList<RpcClientHandler> handlers = (CopyOnWriteArrayList<RpcClientHandler>)this.connectedHandlerList.clone();
int size = handlers.size();
while(isRunning && size <= 0) {
try {
boolean available = waitingForAvailableHandler();
if(available) {
handlers = (CopyOnWriteArrayList<RpcClientHandler>)this.connectedHandlerList.clone();
size = handlers.size();
}
} catch (InterruptedException e) {
log.error(" wating for available node is interrupted !");
throw new RuntimeException("no connect any servers!", e);
}
}
if(!isRunning) {
return null;
}
// 最终使用取模方式取得其中一个业务处理器进行实际的业务处理
return handlers.get(((handlerIdx.getAndAdd(1) + size) % size));
}
/**
* $stop 关闭的方法
*/
public void stop() {
isRunning = false;
for(int i = 0; i< connectedHandlerList.size(); i++) {
RpcClientHandler rpcClientHandler = connectedHandlerList.get(i);
rpcClientHandler.close();
}
// 在这里要调用一下唤醒操作
signalAvailableHandler();
threadPoolExecutor.shutdown();
eventLoopGroup.shutdownGracefully();
}
/**
* $reconnect 发起重连方法 需要把对应的资源进行释放
* @param handler
* @param remotePeer
*/
public void reconnect(final RpcClientHandler handler , final SocketAddress remotePeer) {
if(handler != null) {
handler.close();
connectedHandlerList.remove(handler);
connectedHandlerMap.remove(remotePeer);
}
connectAsync((InetSocketAddress) remotePeer);
}
}
-----------------------------------------------------------------------
public class RpcClientInitializer extends ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline cp = ch.pipeline();
// 编解码的handler
cp.addLast(new RpcEncoder(RpcRequest.class));
// * @param lengthFieldOffset
// * the offset of the length field
// * @param lengthFieldLength
// * the length of the length field
cp.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0));
cp.addLast(new RpcDecoder(RpcResponse.class));
// 实际的业务处理器RpcClientHandler
cp.addLast(new RpcClientHandler());
}
}
public class RpcClient {
private final Map<Class<?>, Object> syncProxyInstanceMap = new ConcurrentHashMap<Class<?>, Object>();
private final Map<Class<?>, Object> asyncProxyInstanceMap = new ConcurrentHashMap<Class<?>, Object>();
private String serverAddress;
private List<String> serverAddressList;
private long timeout;
private RpcConnectManager rpcConnectManager;
public void initClient(String serverAddress, long timeout) {
this.serverAddress = serverAddress;
this.timeout = timeout;
this.rpcConnectManager = new RpcConnectManager();
connect();
}
private void connect() {
this.rpcConnectManager.connect(this.serverAddress);
}
/**
* initClient: 直接返回对应的代理对象,把RpcConnectManager透传到代理对象中
* @param <T>
* @param serverAddress
* @param timeout
* @param interfaceClass
* @return RpcProxyImpl
*/
@SuppressWarnings("unchecked")
public <T> T initClient(List<String> serverAddress, long timeout, Class<T> interfaceClass) {
this.serverAddressList = serverAddress;
this.timeout = timeout;
this.rpcConnectManager = new RpcConnectManager();
this.rpcConnectManager.connect(this.serverAddressList);
return (T) Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class<?>[]{interfaceClass},
new RpcProxyImpl<>(rpcConnectManager, interfaceClass, timeout)
);
}
public void updateConnectedServer(List<String> serverAddress) {
this.serverAddressList = serverAddress;
this.rpcConnectManager.updateConnectedServer(serverAddress);
}
/**
* <B>方法名称:</B>invokeSync<BR>
* <B>概要说明:</B>同步调用<BR>
* @author hezhuo.bai-JiFeng
* @since 2019年10月17日 下午4:10:04
* @param <T>
* @param interfaceClass
* @return
*/
@SuppressWarnings("unchecked")
public <T> T invokeSync(Class<T> interfaceClass) {
if (syncProxyInstanceMap.containsKey(interfaceClass)) {
return (T) syncProxyInstanceMap.get(interfaceClass);
} else {
Object proxy = Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class<?>[]{interfaceClass},
new RpcProxyImpl<>(rpcConnectManager, interfaceClass, timeout)
);
syncProxyInstanceMap.put(interfaceClass, proxy);
return (T) proxy;
}
}
/**
* <B>方法名称:</B>InvokeAsync<BR>
* <B>概要说明:</B>异步调用<BR>
* @author hezhuo.bai-JiFeng
* @since 2019年10月17日 下午4:12:14
* @param <T>
* @param interfaceClass
* @return
*/
@SuppressWarnings("unchecked")
public <T> RpcAsyncProxy invokeAsync(Class<T> interfaceClass) {
if (asyncProxyInstanceMap.containsKey(interfaceClass)) {
return ((RpcProxyImpl<T>) asyncProxyInstanceMap.get(interfaceClass));
} else {
RpcProxyImpl<T> rpcProxyImpl = new RpcProxyImpl<T>(rpcConnectManager, interfaceClass, timeout);
asyncProxyInstanceMap.put(interfaceClass, rpcProxyImpl);
return rpcProxyImpl;
}
}
public void stop() {
this.rpcConnectManager.stop();
}
}
# RPC编解码
@Data
public class RpcRequest implements Serializable {
private static final long serialVersionUID = 3424024710707513070L;
private String requestId;
private String className;
private String methodName;
private Class<?>[] paramterTypes;
private Object[] paramters;
}
@Data
public class RpcResponse implements Serializable {
private static final long serialVersionUID = -7989400623370901861L;
private String requestId;
private Object result;
private Throwable throwable;
}
package com.bfxy.rapid.rpc.codec;
import java.util.List;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
/**
* $RpcDecoder
* @author 17475
*
*/
public class RpcDecoder extends ByteToMessageDecoder {
private Class<?> genericClass;
public RpcDecoder(Class<?> genericClass) {
this.genericClass = genericClass;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
// 如果请求数据包 不足4个字节 直接返回, 如果大于等于4个字节 那么程序继续执行
if(in.readableBytes() < 4) {
return;
}
// 首先记录一下当前的位置
in.markReaderIndex();
// 当前请求数据包的大小读取出来
int dataLength = in.readInt();
if(in.readableBytes() < dataLength) {
in.resetReaderIndex();
return;
}
// 真正读取需要长度的数据包内容
byte[] data = new byte[dataLength];
in.readBytes(data);
// 解码操作 返回指定的对象
Object obj = Serialization.deserialize(data, genericClass);
// 填充到buffer中,传播给下游handler做实际的处理
out.add(obj);
}
}
public class RpcEncoder extends MessageToByteEncoder<Object> {
private Class<?> genericClass;
public RpcEncoder(Class<?> genericClass) {
this.genericClass = genericClass;
}
/**
* 编码器要做的事情
* 1. 把对应的java对象进行编码
* 2. 之后把内容填充到buffer中去
* 3. 写出到Server端
*/
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
if(genericClass.isInstance(msg)) {
byte[] data = Serialization.serialize(msg);
// 消息分为:1.包头 (数据包长度) 2.包体(数据包内容)
out.writeInt(data.length);
out.writeBytes(data);
}
}
}
# 服务端处理器
package com.bfxy.rapid.rpc.server;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.bfxy.rapid.rpc.codec.RpcDecoder;
import com.bfxy.rapid.rpc.codec.RpcEncoder;
import com.bfxy.rapid.rpc.codec.RpcRequest;
import com.bfxy.rapid.rpc.codec.RpcResponse;
import com.bfxy.rapid.rpc.config.provider.ProviderConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;
/**
*
*/
@Slf4j
public class RpcServer {
private String serverAddress;
private EventLoopGroup bossGroup = new NioEventLoopGroup();
private EventLoopGroup workerGroup = new NioEventLoopGroup();
private volatile Map<String /* interface name */, Object> handlerMap = new HashMap<String, Object>();
public RpcServer(String serverAddress) throws InterruptedException {
this.serverAddress = serverAddress;
this.start();
}
/**
* $start
* @throws InterruptedException
*/
private void start() throws InterruptedException {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// tpc = sync + accept = backlog
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline cp = ch.pipeline();
cp.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0));
cp.addLast(new RpcDecoder(RpcRequest.class));
cp.addLast(new RpcEncoder(RpcResponse.class));
cp.addLast(new RpcSeverHandler(handlerMap));
}
});
String[] array = serverAddress.split(":");
String host = array[0];
int port = Integer.parseInt(array[1]);
ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
log.info("server success bing to " + serverAddress);
} else {
log.info("server fail bing to " + serverAddress);
throw new Exception("server start fail, cause: " + future.cause());
}
}
});
try {
channelFuture.await(5000, TimeUnit.MILLISECONDS);
if(channelFuture.isSuccess()) {
log.info("start rapid rpc success! ");
}
} catch (InterruptedException e) {
log.error("start rapid rpc occur Interrupted, ex: " + e);
}
}
/**
* $registerProcessor 程序注册器
*/
public void registerProcessor(ProviderConfig providerConfig) {
//key : providerConfig.insterface (userService接口权限命名)
//value : providerConfig.ref (userService接口下的具体实现类 userServiceImpl实例对象)
handlerMap.put(providerConfig.getInterface(), providerConfig.getRef());
}
/**
* $close
*/
public void close() {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
@Slf4j
public class RpcSeverHandler extends SimpleChannelInboundHandler<RpcRequest> {
private Map<String, Object> handlerMap;
private ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 16, 600L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(65536));
public RpcSeverHandler(Map<String, Object> handlerMap) {
this.handlerMap = handlerMap;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RpcRequest rpcRequest) throws Exception {
executor.submit(new Runnable() {
@Override
public void run() {
RpcResponse response = new RpcResponse();
response.setRequestId(rpcRequest.getRequestId());
try {
Object result = handle(rpcRequest);
response.setResult(result);
} catch (Throwable t) {
response.setThrowable(t);
log.error("rpc service handle request Throwable: " + t);
}
ctx.writeAndFlush(response).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
// afterRpcHook
}
}
});
}
});
}
/**
* $handle 解析request请求并且去通过反射获取具体的本地服务实例后执行具体的方法
* @param request
* @return
* @throws InvocationTargetException
*/
private Object handle(RpcRequest request) throws InvocationTargetException {
String className = request.getClassName();
Object serviceRef = handlerMap.get(className);
Class<?> serviceClass = serviceRef.getClass();
String methodName = request.getMethodName();
Class<?>[] paramterTypes = request.getParamterTypes();
Object[] paramters = request.getParamters();
// JDK relect
// Cglib
FastClass serviceFastClass = FastClass.create(serviceClass);
FastMethod servicFastMethod = serviceFastClass.getMethod(methodName, paramterTypes);
return servicFastMethod.invoke(serviceRef, paramters);
}
/**
* $exceptionCaught 异常处理关闭连接
*/
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("server caught Throwable: " + cause);
ctx.close();
}
}
# 异步代理
package com.bfxy.rapid.rpc.client.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import com.bfxy.rapid.rpc.client.RpcClientHandler;
import com.bfxy.rapid.rpc.client.RpcConnectManager;
import com.bfxy.rapid.rpc.client.RpcFuture;
import com.bfxy.rapid.rpc.codec.RpcRequest;
public class RpcProxyImpl<T> implements InvocationHandler, RpcAsyncProxy {
private Class<T> clazz;
private long timeout;
private RpcConnectManager rpcConnectManager;
public RpcProxyImpl(RpcConnectManager rpcConnectManager, Class<T> clazz, long timeout) {
this.clazz = clazz;
this.timeout = timeout;
this.rpcConnectManager = rpcConnectManager;
}
/**
* invoke代理接口调用方式
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//1.设置请求对象
RpcRequest request = new RpcRequest();
request.setRequestId(UUID.randomUUID().toString());
request.setClassName(method.getDeclaringClass().getName());
request.setMethodName(method.getName());
request.setParamterTypes(method.getParameterTypes());
request.setParamters(args);
//2.选择一个合适的Client任务处理器
// RpcClientHandler handler = RpcConnectManager.getInstance().chooseHandler();
RpcClientHandler handler = this.rpcConnectManager.chooseHandler();
//3. 发送真正的客户端请求 返回结果
RpcFuture future = handler.sendRequest(request);
return future.get(timeout, TimeUnit.SECONDS);
}
/**
* $call 异步的代理接口实现, 真正的抱出去RpcFuture 给业务方做实际的回调等待处理
*/
@Override
public RpcFuture call(String funcName, Object... args) {
//1.设置请求对象
RpcRequest request = new RpcRequest();
request.setRequestId(UUID.randomUUID().toString());
request.setClassName(this.clazz.getName());
request.setMethodName(funcName);
request.setParamters(args);
// TODO: 对应的方法参数类型应该通过 类类型 + 方法名称 通过反射得到parameterTypes
Class<?>[] parameterTypes = new Class[args.length];
for(int i = 0; i < args.length; i++) {
parameterTypes[i] = getClassType(args[i]);
}
request.setParamterTypes(parameterTypes);
//2.选择一个合适的Client任务处理器
// RpcClientHandler handler = RpcConnectManager.getInstance().chooseHandler();
RpcClientHandler handler = this.rpcConnectManager.chooseHandler();
RpcFuture future = handler.sendRequest(request);
return future;
}
private Class<?> getClassType(Object obj) {
Class<?> classType = obj.getClass();
String typeName = classType.getName();
if (typeName.equals("java.lang.Integer")) {
return Integer.TYPE;
} else if (typeName.equals("java.lang.Long")) {
return Long.TYPE;
} else if (typeName.equals("java.lang.Float")) {
return Float.TYPE;
} else if (typeName.equals("java.lang.Double")) {
return Double.TYPE;
} else if (typeName.equals("java.lang.Character")) {
return Character.TYPE;
} else if (typeName.equals("java.lang.Boolean")) {
return Boolean.TYPE;
} else if (typeName.equals("java.lang.Short")) {
return Short.TYPE;
} else if (typeName.equals("java.lang.Byte")) {
return Byte.TYPE;
}
return classType;
}
}
@Slf4j
public class RpcServer {
private String serverAddress;
private EventLoopGroup bossGroup = new NioEventLoopGroup();
private EventLoopGroup workerGroup = new NioEventLoopGroup();
private volatile Map<String /* interface name */, Object> handlerMap = new HashMap<String, Object>();
public RpcServer(String serverAddress) throws InterruptedException {
this.serverAddress = serverAddress;
this.start();
}
/**
* $start
* @throws InterruptedException
*/
private void start() throws InterruptedException {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// tpc = sync + accept = backlog
.option(ChannelOption.SO_BACKLOG, 1024)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline cp = ch.pipeline();
cp.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0));
cp.addLast(new RpcDecoder(RpcRequest.class));
cp.addLast(new RpcEncoder(RpcResponse.class));
cp.addLast(new RpcSeverHandler(handlerMap));
}
});
String[] array = serverAddress.split(":");
String host = array[0];
int port = Integer.parseInt(array[1]);
ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
log.info("server success bing to " + serverAddress);
} else {
log.info("server fail bing to " + serverAddress);
throw new Exception("server start fail, cause: " + future.cause());
}
}
});
try {
channelFuture.await(5000, TimeUnit.MILLISECONDS);
if(channelFuture.isSuccess()) {
log.info("start rapid rpc success! ");
}
} catch (InterruptedException e) {
log.error("start rapid rpc occur Interrupted, ex: " + e);
}
}
/**
* $registerProcessor 程序注册器
*/
public void registerProcessor(ProviderConfig providerConfig) {
//key : providerConfig.insterface (userService接口权限命名)
//value : providerConfig.ref (userService接口下的具体实现类 userServiceImpl实例对象)
handlerMap.put(providerConfig.getInterface(), providerConfig.getRef());
}
/**
* $close
*/
public void close() {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
@Slf4j
public class RpcSeverHandler extends SimpleChannelInboundHandler<RpcRequest> {
private Map<String, Object> handlerMap;
private ThreadPoolExecutor executor = new ThreadPoolExecutor(16, 16, 600L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(65536));
public RpcSeverHandler(Map<String, Object> handlerMap) {
this.handlerMap = handlerMap;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, RpcRequest rpcRequest) throws Exception {
executor.submit(new Runnable() {
@Override
public void run() {
RpcResponse response = new RpcResponse();
response.setRequestId(rpcRequest.getRequestId());
try {
Object result = handle(rpcRequest);
response.setResult(result);
} catch (Throwable t) {
response.setThrowable(t);
log.error("rpc service handle request Throwable: " + t);
}
ctx.writeAndFlush(response).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if(future.isSuccess()) {
// afterRpcHook
}
}
});
}
});
}
/**
* $handle 解析request请求并且去通过反射获取具体的本地服务实例后执行具体的方法
* @param request
* @return
* @throws InvocationTargetException
*/
private Object handle(RpcRequest request) throws InvocationTargetException {
String className = request.getClassName();
Object serviceRef = handlerMap.get(className);
Class<?> serviceClass = serviceRef.getClass();
String methodName = request.getMethodName();
Class<?>[] paramterTypes = request.getParamterTypes();
Object[] paramters = request.getParamters();
// JDK relect
// Cglib
FastClass serviceFastClass = FastClass.create(serviceClass);
FastMethod servicFastMethod = serviceFastClass.getMethod(methodName, paramterTypes);
return servicFastMethod.invoke(serviceRef, paramters);
}
/**
* $exceptionCaught 异常处理关闭连接
*/
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("server caught Throwable: " + cause);
ctx.close();
}
}