rpc简介
RPC是远程过程调用(Remote Procedure Call),比如Dubbo框架就是使用rpc原理。
详情请自行《百度百科》
api模块–接口声明和协议定义
1.定义netty服务端和客户端的通信协议(即消息内容)
public class RpcProtocol implements Serializable {
/**类名**/
private String className;
/**方法名**/
private String methodName;
/**参数类型**/
private Class>[] parames;
/**参数值**/
private Object[] values;
}
12345678910
2. 接口声明
public interface IRpcService {
String test(String test);
}
123
远程服务提供者server端–编写
1.实现接口
public class RpcServiceimpl implements IRpcService {
@Override
public String test(String test) {
return "hello " + test + "!";
}
}
123456
2.编写服务提供
public class RpcProvider {
private int port;
public RpcProvider(int port) {
this.port = port;
}
public void start(){
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//协议解码器
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
//协议编码器
pipeline.addLast(new LengthFieldPrepender(4));
//对象参数类型编码器
pipeline.addLast(new ObjectEncoder());
//对象参数类型解码器
pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
pipeline.addLast(new RpcHandler());
}
})
//主线程 线程最大数量128
.option(ChannelOption.SO_BACKLOG,128)
//子线程配置 保存长连接
.childOption(ChannelOption.SO_KEEPALIVE,true);
ChannelFuture future = bootstrap.bind(port).sync();
System.out.println("Rpc start listen at " + port);
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142
3.netty handler 编写
public class RpcHandler extends ChannelInboundHandlerAdapter {
//保存服务实现的类实例
public static ConcurrentHashMap
//保存服务实现的类名
public List
public RpcHandler() {
//递归扫描
scannerClass("com.aiden.serviceimpl");
doRegister();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Object result = new Object();
RpcProtocol request = (RpcProtocol) msg;
if (serviceImplMap.containsKey(request.getClassName())) {
Object clazz = serviceImplMap.get(request.getClassName());
Method method = clazz.getClass().getMethod(request.getMethodName(), request.getParames());
result = method.invoke(clazz, request.getValues());
}
ctx.write(result);
ctx.flush();
ctx.close();
}
//扫描实现的class
private void scannerClass(String packageName) {
URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
File dir = new File(url.getFile());
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
scannerChildFile(packageName + "." + file.getName(), classNames, file);
} else {
classNames.add(packageName + "." + file.getName().replace(".class", "").trim());
}
}
}
private void scannerChildFile(String packageName, List
for (File file : child.listFiles()) {
if (file.isDirectory()) {
scannerChildFile(packageName + "." + file.getName(), classNames, file);
} else {
classNames.add(packageName + "." + file.getName().replace(".class", "").trim());
}
}
}
private void doRegister() {
if (classNames.size() == 0) {
return;
}
for (String className : classNames) {
try {
Class> clazz = Class.forName(className);
Class> serviceInterface = clazz.getInterfaces()[0];
serviceImplMap.put(serviceInterface.getName(), clazz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
4.启动类
public class RpcRemoteStart {
public static void main(String[] args) {
new RpcProvider(8080).start();
}
}
12345
本地rpc调用编写
1.编写代理类
public class RpcProxy {
public static
MethodProxy proxy = new MethodProxy(clazz);
Class> [] interfaces = clazz.isInterface()?new Class[]{clazz}:clazz.getInterfaces();
T result = (T) Proxy.newProxyInstance(clazz.getClassLoader(),interfaces,proxy);
return result;
}
private static class MethodProxy implements InvocationHandler{
private Class> clazz;
public MethodProxy(Class> clazz) {
this.clazz = clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this,args);
} else {
return rpcInvoke(proxy,method,args);
}
}
private Object rpcInvoke(Object proxy, Method method, Object[] args) {
RpcProtocol msg = new RpcProtocol();
msg.setClassName(this.clazz.getName());
msg.setMethodName(method.getName());
msg.setValues(args);
msg.setParames(method.getParameterTypes());
final RpcProxyHandler rpcProxyHandler = new RpcProxyHandler();
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap client = new Bootstrap();
client.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//协议解码器
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
//协议编码器
pipeline.addLast(new LengthFieldPrepender(4));
//对象参数类型编码器
pipeline.addLast(new ObjectEncoder());
//对象参数类型解码器
pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
pipeline.addLast(rpcProxyHandler);
}
});
ChannelFuture future = client.connect("localhost",8080).sync();
future.channel().writeAndFlush(msg).sync();
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
return rpcProxyHandler.getResponse();
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
2.netty handler 处理类编写
public class RpcProxyHandler extends ChannelInboundHandlerAdapter {
private Object response;
public Object getResponse() {
return response;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
response = msg;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("client exception is generate");
}
}
1234567891011121314151617
3.客户端启动类
public class ClientStart {
public static void main(String[] args) {
IRpcService rpcService = RpcProxy.create(IRpcService.class);
System.out.println(rpcService.test("Aiden"));
}
}
123456
结果