自行实现一个简易RPC框架

10分钟写一个RPC框架

1、RpcFramework

package com.alibaba.study.rpc.framework;  

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket; 

/**
 * 自行实现一个简易RPC框架
 * @author wangwei03
 */
public class RpcFramework {  

    /**
     * 暴露服务
     *
     * @param service 服务实现
     * @param port 服务端口
     * @throws Exception
     */
    public static void export(final Object service, int port) throws Exception {
        if (service == null)
            throw new IllegalArgumentException("service instance == null");
        if (port <= 0 || port > 65535)
            throw new IllegalArgumentException("Invalid port " + port);
        System.out.println("Export service " + service.getClass().getName() + " on port " + port);
        ServerSocket server = new ServerSocket(port);
        for(;;) {
            try {
                final Socket socket = server.accept();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            try {
                                ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                                try {
                                    String methodName = input.readUTF();
                                    Class<?>[] parameterTypes = (Class<?>[])input.readObject();
                                    Object[] arguments = (Object[])input.readObject();
                                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                                    try {
                                        Method method = service.getClass().getMethod(methodName, parameterTypes);
                                        Object result = method.invoke(service, arguments);
                                        output.writeObject(result);
                                    } catch (Throwable t) {
                                        output.writeObject(t);
                                    } finally {
                                        output.close();
                                    }
                                } finally {
                                    input.close();
                                }
                            } finally {
                                socket.close();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }  

    /**
     * 引用服务
     *
     * @param <T> 接口泛型
     * @param interfaceClass 接口类型
     * @param host 服务器主机名
     * @param port 服务器端口
     * @return 远程服务
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {
        if (interfaceClass == null)
            throw new IllegalArgumentException("Interface class == null");
        if (! interfaceClass.isInterface())
            throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");
        if (host == null || host.length() == 0)
            throw new IllegalArgumentException("Host == null!");
        if (port <= 0 || port > 65535)
            throw new IllegalArgumentException("Invalid port " + port);
        System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
                Socket socket = new Socket(host, port);
                try {
                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                    try {
                        output.writeUTF(method.getName());
                        output.writeObject(method.getParameterTypes());
                        output.writeObject(arguments);
                        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                        try {
                            Object result = input.readObject();
                            if (result instanceof Throwable) {
                                throw (Throwable) result;
                            }
                            return result;
                        } finally {
                            input.close();
                        }
                    } finally {
                        output.close();
                    }
                } finally {
                    socket.close();
                }
            }
        });
    }  

}  

2、Provider

package com.alibaba.study.rpc.test;

/**
 * HelloService
 * 定义服务接口
 * @author william.liangf
 */
public interface HelloService {
    String hello(String name);
}
package com.alibaba.study.rpc.test;  

/**
 * HelloServiceImpl
 * 实现服务
 * @author william.liangf
 */
public class HelloServiceImpl implements HelloService {  

    public String hello(String name) {
        return "Hello " + name;
    }  

}  
package com.alibaba.study.rpc.test;  

import com.alibaba.study.rpc.framework.RpcFramework;  

/**
 * RpcProvider
 * 暴露服务
 * @author william.liangf
 */
public class RpcProvider {  

    public static void main(String[] args) throws Exception {
        HelloService service = new HelloServiceImpl();
        RpcFramework.export(service, 1234);
    }  

}  

3、Consumer

package com.alibaba.study.rpc.test;  

import com.alibaba.study.rpc.framework.RpcFramework;  

/**
 * RpcConsumer
 * 引用服务
 * @author william.liangf
 */
public class RpcConsumer {  

    public static void main(String[] args) throws Exception {
        HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);
        for (int i = 0; i < Integer.MAX_VALUE; i ++) {
            String hello = service.hello("World" + i);
            System.out.println(hello);
            Thread.sleep(1000);
        }
    }  

}  

转自梁飞:http://javatar.iteye.com/blog/1123915

时间: 2024-08-27 04:54:32

自行实现一个简易RPC框架的相关文章

简易RPC框架-心跳与重连机制

*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } a { color: #4183C4; } a.absent { color: #cc0000; } a.anchor { display: block; padding-left: 30px; margin-left: -30px; cursor: pointer; position: absolute

一个入门rpc框架的学习

一个入门rpc框架的学习 参考 huangyong-rpc 轻量级分布式RPC框架 该程序是一个短连接的rpc实现 简介 RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协议的 RPC, 它具有良好的跨平台性,但其性能却不如基于 TCP 协议的 RPC.会两方面会直接影响 RPC 的性能,一是传输方式,二是序列化. 众所

基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇

前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> 前一篇文章相对简略地介绍了RPC服务端的编写,而这篇博文最要介绍服务端(Client)的实现.RPC调用一般是面向契约编程的,而Client的核心功能就是:把契约接口方法的调用抽象为使用Netty向RPC服务端通过私有协议发送一个请求.这里最底层的实现依赖于动态代理,因此动态代理是动态实现接口的最简单方式(如果

一个简单RPC框架是如何炼成的(V)——引入传输层

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理    接下来处理数据传输.实际应用场景一般都是基于socket.socket代码比较多,使用起来也比较麻烦.而且具体的传输通道使用socket或者其他的方式,如更上层的http,或者android里的binder,都是可替换的,只是具体的一种实现而已.所以,这里我就偷个懒,只是引入一个很简单的Connection类,用来描述一下如何将数据传输 这一层给独立出来. 首先简单列出Conne

一个简单RPC框架是如何炼成的(VI)——引入服务注册机制

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理 接下来处理RPC服务的注册机制.所谓注册机制,就是Server需要声明支持哪些rpc方法,然后当客户端发送调用某个声明的rpc方法之后,服务端能自动找到执行该请求的具体方法.以实际的例子为例,这是现在server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的客户端请求 while True: req = self.conn.recv()

一个简单RPC框架是如何炼成的(I)——开局篇

开场白,这是一个关于RPC的相关概念的普及篇系列,主要是通过一步步的调整,提炼出一个相对完整的RPC框架. RPC(Remote Procedure Call Protocol)--远程过程调用协议,基于C/S模型.网络上有一篇文章写得不错,可以去了解一下相关概念深入浅出RPC 这里,直接使用一下上面作者的一个示意图 总结下来就是有4块核心内容 RPC数据的传输.如上面的RPCConnector,RPCChannel.它们主要负责数据传输这一块, 具体客户端与服务器之间的连接是不是socket连

一个简单RPC框架是如何炼成的(II)——制定RPC消息

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注册 RPC消息处理 下面,我们先看一个普通的过程调用 class Client(object): def __init__(self): self.remote = None ## # 内部是委托给远程remote对象来获取结果. def sayHello(self): if self.remote: return self.remote.sayHello() else : return None cla

一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制

开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法.然后当client发送调用某个声明的rpc方法之后,服务端能自己主动找到运行该请求的详细方法.以实际的样例为例.这是如今server端处理RPC请求的代码 def procRequest(self): # 循环读取并处理收到的client请求 while True: req = self.conn

一个简单RPC框架是怎样炼成的(II)——制定RPC消息

开局篇我们说了,RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 以下,我们先看一个普通的过程调用 class Client(object): def __init__(self): self.remote = None ## # 内部是托付给远程remote对象来获取结果. def sayHello(self): if self.remote: return self.remote.sayHello() else : return None cla