自己动手写rpc框架,手写rpc框架实战
如何解决写爬虫IP受阻的问题?立即使用。
RPC框架被称为远程调用框架,其实现的核心原理是消费者使用动态代理代理一个接口方法(基于JDK的动态代理,当然如果使用CGLib,可以直接使用没有接口类的方法)。通过添加网络传输编程,提供者可以得到调用接口的名称和方法参数,然后通过反射,执行接口的方法,反射执行的结果通过网络编程发回给消费者。
现在让我们依次实现这些概念。这里我们做最简单的实现。网络编程用的是BIO,你可以用Reactor模式的Netty来重写性能更好的方式。网络传输中使用的序列化和反序列化也是Java原生的。当然这样的传输字节比较大,可以用google的protoBuffer或者kryo来处理。这只是为了方便解释原理。
砰的一声
?xml版本=1.0 编码=UTF-8 ?
项目xmlns= http://maven . Apache . org/POM/4 . 0 . 0
xmlns:xsi= http://www . w3 . org/2001/XML schema-instance
xsi:schema location= http://maven . Apache . org/POM/4 . 0 . 0 http://maven.apache.org/xsd/maven-4.0.0.xsd
型号版本4 . 0 . 0/型号版本
groupIdcom.guanjian/groupId
artifact id RPC-框架/artifactId
1.0版-快照/版本
建设
插件
插件
groupIdorg.apache.maven.plugins/groupId
artifactId maven-编译器-插件/artifactId
版本3 . 7 . 0/版本
配置
源1.8/源
目标1.8/目标
encoding utf-8/编码
/配置
/插件
/插件
/构建
/project当然是我们要远程调用的接口,也是接口的方法。
公共接口HelloService {
String sayHello(字符串内容);}接口实现类
公共类HelloServiceImpl实现hello service { public String say hello(String content){ return hello, content;}
}消费者端的动态代理。如果在两个项目中写提供者和使用者,提供者端需要上面的接口和实现类,而使用者端只需要上面的接口。
公共类ConsumerProxy {
/**
*消费者方面的动态代理
* @param interfaceClass代理的接口类
* @param host远程主机IP
* @param port远程主机端口
* @param T
* @返回
*/
@SuppressWarnings(未选中)
public static T T consume(final class T interface class,final String host,final int port) {
return(T)proxy . newproxyinstance(interface class . get class loader(),
新类[]{interfaceClass},(代理,方法,参数)- {
//创建客户端套接字
Socket socket=新插座(主机,端口);
尝试{
//创建外部传输的对象流,并绑定套接字。
object output stream output=new object output stream(socket . get output stream());
尝试{
//将动态代理的方法名写入外部传输的对象流中。
output . write utf(method . getname());
//将动态代理的方法的参数写入外部传输的对象流。
output . writeobject(args);
//创建一个内部传输的对象流,并绑定套接字。
//这里是获取提供者返回的结果。
ObjectInputStream input=new ObjectInputStream(socket . getinputstream());
尝试{
//从内部传输的对象流中获取结果
object result=input . readobject();
Throwable的结果实例){
抛出(可抛出)结果;
}
返回结果;
}最后{
输入。close();
}
}最后{
输出。close();
}
}最后{
插座。close();
}
}
);
}
}有关爪哇岛开发工具包动态代理的内容可以参考面向切面编程原理与自实现,生物的部分可以参考传统超正析象管(图片Orthicon)与尼奥比较
提供者端的网络传输和远程方式调用服务
公共类提供反射{
私有静态最终执行者服务。newcachedthreadpool();
/**
* RPC监听和远程方法调用
* @param服务位置遥控(remote position control)远程方法调用的接口实例
* @param端口监听的端口
* @抛出异常
*/
公共静态空的提供程序(最终对象服务,int端口)引发异常{
//创建服务端的套接字,绑定端口港口
服务器套接字服务器套接字=新服务器套接字(端口);
while (true) {
//开始接收客户端的消息,并以此创建套接字
最终套接字套接字=服务器套接字。接受();
//多线程执行,这里的问题是连接数过大,线程池的线程数会耗尽
executorService.execute(() - {
尝试{
//创建呢一个对内传输的对象流,并绑定套接字
ObjectInputStream输入=新的ObjectInputStream(套接字。getinputstream());
尝试{
尝试{
//从对象流中读取接口方法的方法名
字符串方法名称=输入。读取utf();
//从对象流中读取接口方法的所有参数
Object[]args=(Object[])input。read Object();
Class[] argsTypes=新类[参数。长度];
for(int I=0;我参数。长度;i ) {
argsTypes[i]=args[i].getClass();
}
//创建一个对外传输的对象流,并绑定套接字
//这里是为了将反射执行结果传递回消费者端
对象输出流输出=新对象输出流(套接字。获取输出流());
尝试{
班级?[] interfaces=service.getClass().获取接口();
方法方法=null
for(int I=0;我接口。长度;i ) {
方法=接口[我].getDeclaredMethod(methodName,args类型);
如果(方法!=null) {
打破;
}
}
对象结果=方法。invoke(服务,参数);
//将反射执行结果写入对外传输的对象流中
output.writeObject(结果);
} catch (Throwable t) {
输出。writeobject(t);
}最后{
输出。close();
}
} catch(异常e) {
e。printstacktrace();
}最后{
输入。close();
}
}最后{
插座。close();
}
} catch(异常e) {
e。printstacktrace();
}
});
}
}
}启动提供者端的网络侦听和远程调用
公共类RPCProviderMain {
公共静态void main(String[] args)引发异常{
hello service service=new hello service impl();
ProviderReflect.provider(服务,8083);
}
}启动消费者的动态代理调用
公共类RPCConsumerMain {
公共静态void main(String[] args)引发中断的异常{
hello service服务=消费者代理。消费(hello服务。类, 127.0.0.1 ,8083);
for(int I=0;i 1000i ) {
String hello=service.sayHello(你好_ 我);
系统。出去。println(你好);
线程。睡眠(1000);
}
}
}运行结果
你好,你好_0
你好,你好_1
你好,你好_2
你好,你好_3
你好,你好_4
你好,你好_5
.
如果你要扩展成一个网状原缓冲区的高性能位置遥控(远程位置控制)框架可以参考妮蒂整合原缓冲液的相关写法。
推荐教程: 《PHP》 以上就是爪哇手写一个位置遥控(远程位置控制)框架的详细内容,更多请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。