ITKeyword - 技术文章推荐分享

首页 > 自己实现一个RPC框架

自己实现一个RPC框架

标签: RPC,

相关推荐:(十五) Thunder分布式RPC框架

Thunder(QQ 群 471164539)发布在淘宝代码基地 http://code.taobao.org/p/Thunder/框架支持两种方式的序列化,Java对象和字节数组的序列化和反序列化,Java对象和Json字符串的转换1)binary - Java实体类和字节数组的序列化/反序列化2)compression -

RPC简介远程调用协议。 有多有用,多普遍就不摆了。大概过程:1. 调用客户端句柄,传输参数。2. 封装参数等消息为网络传输格式传给远程主机3. 服务器句柄得到消息并解析参数4. 在服务器段执行要调用的代码,并把结果返回给服务器句柄5. 服务器句柄封装返回结果并用网络传输给客户端6. 客户端解析并进行其他处理可见之问题主要有,通信方式、句柄实现、以及消息封装和解析(序列化及反序列化)RPC 之 通信直接用Socket走TCP/IP 或者是UDP协议, 例如RMI走HTTP协议,

Hessian。 好处不用防火墙再开端口了在下面的例子中,使用java socket。这样可以看到更基础的内容。RPC 之动态代理句柄部分我们可以使用动态代理,在调用客户端方法的时候使用动态代理来调用远程方法RPC 之序列化与反序列化这个也有很多种,比如Java自带的序列化机制,实现了Serializable接口的类,都能够进行序列化对于Java序列化的原理可以看下下面的博文:http://www.java3z.com/cwbwebhome/article/article8/862.html是Java处理二进制的一贯风格,定义了标志位表示后面有多长的内容表示了一个什么,然后是具体的内容。Java的反序列化。最好的办法当然是看ObjectInputStream的源代码了。大概的流程是:1. readObject0

入口2. 然后就是一段一段读取然后解析了。一般最开始读取Class readClass,读取这个类的Class接口3. readOrdinaryObject 使用newInstance来创建实例4. 然后用defaultReadFields 中的desc.setObjFieldValues内容来个这个实例的字段赋值。5. 这是一个循环的过程,知道把对象中所有的内容都还原。还可以有其他的方式,比如WebService技术是使用了Soap协议来进行传输的,使用的是类似于XML格式的方式描述消息内容的(因此消息内容会比较臃肿)Hessian是使用了二进制的方式进行了序列化,它使用了自己的规则,该规则可以用其他语言实现,是一个简单而且高效的协议。细节链接如下:http://hessian.caucho.com/doc/hessian-serialization.html在下面的例子中使用ObjectInputStream来进行序列化操作。自己的RPC框架服务器端启动Socket并且给每个请求创建一个处理线程:public class StartUp { public static final int port = 8080;

public static void main(String[] args) {

exportRpc(); }

/**

* 导出RPC接口

*/ private static void exportRpc() {

try {

ServerSocket ss = new ServerSocket(9001);

while(true){

Socket s = ss.accept();

new RpcThread(s).start();

}

} catch (IOException e) {

e.printStackTrace();

} }}然后定义传递的消息内容,要包含了客户端要告诉服务器端的内容,最少要包含,调用的接口名,调用的方法名,以及方法参数。该对象如下:public class RpcObject implements Serializable{ private static final long serialVersionUID = 1L; private Class c; private String methodName; private Object[] args;

public RpcObject() { }

public RpcObject(Class c, String methodName, Object[] args) {

this.c = c;

this.methodName = methodName;

this.args = args; } public Class getC() {

return c; } public void setC(Class c) {

this.c = c; } public String getMethodName() {

return methodName; } public void setMethodName(String methodName) {

this.methodName = methodName; } public Object[] getArgs() {

return args; } public void setArgs(Object[] args) {

this.args = args; }}服务器端处理线程,将会出去参数对象,然后通过反射来得到具体的实例对象以及调用需要调用的方法。public class RpcThread extends Thread { private Socket s; public RpcThread(Socket s) {

this.s = s; }

@Override public void run() {

ObjectInputStream is = null;

ObjectOutputStream os = null;

try {

is = new ObjectInputStream(s.getInputStream());

// 得到远程调用参数,包含了接口名,调用方法,方法参数

RpcObject rpcObject = (RpcObject) is.readObject();

// 构建接口的实现类,然后通过反射调用方法

Object o = getObject(rpcObject.getC());

Object reO = executeMethod(o, rpcObject.getMethodName(), rpcObject.getArgs());

// 输出返回值

os = new ObjectOutputStream(s.getOutputStream());

os.writeObject(reO);

os.flush();

} catch (IOException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} finally {

try {

is.close();

os.close();

} catch (IOException e) {

e.printStackTrace();

}

} }

/**

* 通过反射技术执行方法,并返回返回值

* @param o

* @param methodName

* @param args

* @return

*/ private Object executeMethod(Object o, String methodName, Object[] args) {

Object objR = null;

Class[] cs = new Class[args.length];

for (int i = 0; i < args.length; i++) {

Object arg = args[i];

cs[i] = arg.getCl

相关推荐:(一) Thunder分布式RPC框架

Thunder(QQ 群 471164539)发布在淘宝代码基地 http://code.taobao.org/p/Thunder/1. 概要1.1 Thunder是基于Netty + Hessian + Kafka + ActiveMQ + Tibco + Zookeeper(Curator Framework) + Redis + FST + Spring + Spring Web MVC分布式RPC调用框

ass();

}

try {

Method m = o.getClass().getMethod(methodName, cs);

objR = m.invoke(o, args);

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return objR; }

/**

* 根据接口名得到实例

* @param c

* @return

*/ private Object getObject(Class c) {

Object o = null;

try {<span style="white-space:pre">

</span>o = ConfMonitor.conf.get(c.getName()).newInstance();<span style="white-space:pre">

</span>} catch (InstantiationException e) {<span style="white-space:pre">

</span>e.printStackTrace();<span style="white-space:pre">

</span>} catch (IllegalAccessException e) {<span style="white-space:pre">

</span>e.printStackTrace();<span style="white-space:pre">

</span>}

return o; }}服务器端配置文件,主要是配置接口对应了哪个实现类:/** * 模拟配置,实际的框架中大部分都是使用xml进行配置的,比如Hessian是配置在web.xml的servlet属性里的 * @author cdwangzijian * */public class ConfMonitor { public static Map<String, Class> conf = new HashMap<String, Class>();

static {

conf.put("com.prince.rpc.service.IHello", HelloImpl.class); }}客户端使用动态代理,给每一个方法调用都变为远程调用。public class ProxyFactory { public static <T> T create(Class<T> c, String ip, int port) {

InvocationHandler handler = new RpcProxy(ip, port, c);

return (T) Proxy.newProxyInstance(c.getClassLoader(),

new Class[] {c },

handler); }}代理将会封装远程参数,把调用的接口,方法名,参数传给远程,并且获得返回值/** * 客户端接口代理 * 当客户端接口方法被调用的时候,把方法名,方法参数作为参数。 * 传送给远程服务执行,然后获取返回值 * @author cdwangzijian * */public class RpcProxy implements InvocationHandler, Serializable{ private String ip; private int port; private Class c;

private static final long serialVersionUID = 1L; public RpcProxy(String ip, int port, Class c) {

this.ip = ip;

this.port = port;

this.c = c; }

/**

* 动态代理类,当调用接口方法的时候转为调用此方法

*/ @Override public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object o = null;

// 用作返回值

// 通过socket调用远程服务

Socket s = new Socket(ip, port);

// 组装为一个保留了要调用的类,方法名及参数的对象,然后序列化之后传给远程

RpcObject rpcObject = new RpcObject(c, method.getName(), args);

ObjectOutputStream os = null;

ObjectInputStream is = null;

try{

os = new ObjectOutputStream(s.getOutputStream());

os.writeObject(rpcObject);

os.flush();

// 从远程得到返回结果

is = new ObjectInputStream(s.getInputStream());

o = is.readObject();

} catch (Exception e) {

e.printStackTrace();

} finally{

os.close();

is.close();

}

return o; } }最后是调用部分,获得代理类。public class RpcClient { public static void main(String[] args) {

String ip = "localhost";

int port = 9001;

IHello hello = ProxyFactory.create(IHello.class, ip, port);

System.out.println(hello.sayHello("wzj")); }}下面是用作测试的接口及实现类的代码:public interface IHello { String sayHello(String name);}public class HelloImpl implements IHello { @Override public String sayHello(String name) {

return "hello:" + name; }}最后就是源代码的下载路径了:

http://download.csdn.net/detail/three_man/8059871

相关推荐:RPC框架与Dubbo完整使用

这并不是原理性的解释文章。而是快速入门,还有一个完整的Java例子。 一篇我觉得不错的文章推荐:深入浅出 RPC - 浅出篇 一、RPC什么是RPC?RPC(Remote Procedure Call)远程过程调用。见名知意 - 从远程主机调用一个过程/函数。RPC的目标是:使得

RPC简介远程调用协议。 有多有用,多普遍就不摆了。大概过程:1. 调用客户端句柄,传输参数。2. 封装参数等消息为网络传输格式传给远程主机3. 服务器句柄得到消息并解析参数4. ...

------分隔线----------------------------