【Java】java实现的远程调用例子 rpc原理

当今分布式应用盛行,rpc框架也就随之出现,今天用java写一个小的demo。

首先看一下什么事远程调用

远程调用涉及到了网络io,基本过程是客户端向服务端发送消息,表明自己要调用的方法的名字以及包含的参数,然后服务端调用函数,再向客户端返回结果。所以涉及了两次网络io。

这样的话,客户端的代码写起来比较费劲,每一个方法底层都是网络io,但是过程都是一样的,传递参数,得到结果,所以这里肯定可以优化,比如在java中可以使用动态代理机制。只需要使用一个服务端的接口类就,让Proxy动态生成一个代理类。服务端就是一个socket的常规服务器,可以使用线程池或者多路复用这样的技术,然后通过反射来调用实际类。还有注册服务的功能,所谓注册就是让接口和真正的实现类对接,最后就可以调用到实现类的方法。

所以远程调用其实就是网络io,在客户端和服务端下面都有消息的封装和解析,以及网络io。

下面是一个简单的例子:

接口

public interface HelloService{

	public String hello(String name);
	
}
实现类:

public class HelloServiceImpl implements HelloService{

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

}
sever:

public class RPCServer {

	private ExecutorService threadPool;
	private static final int DEFAULT_THREAD_NUM = 10;
	
	public RPCServer(){
		threadPool = Executors.newFixedThreadPool(DEFAULT_THREAD_NUM);
	}
	
	public void register(Object service, int port){
		try {
			System.out.println("server starts...");
			ServerSocket server = new ServerSocket(port);
			Socket socket = null;
			while((socket = server.accept()) != null){
				System.out.println("client connected...");
				threadPool.execute(new Processor(socket, service));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	class Processor implements Runnable{
		Socket socket;
		Object service;
		
		public Processor(Socket socket, Object service){
			this.socket = socket;
			this.service = service;
		}
		public void process(){
			
		}
		@Override
		public void run() {
			try {
				ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
				String methodName = in.readUTF();
				Class<?>[] parameterTypes = (Class<?>[]) in.readObject();
				Object[] parameters = (Object[]) in.readObject();
				Method method = service.getClass().getMethod(methodName, parameterTypes);
				try {
					Object result = method.invoke(service, parameters);
					ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
					out.writeObject(result);
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			}
		}
	}
}

启动:

public class Main {

	public static void main(String args[]){
		HelloService helloService = new HelloServiceImpl();
		
		RPCServer server = new RPCServer();
		server.register(helloService, 50001);
	}
}


客户端:

public class RPCClient {

	public static void main(String args[]){
		HelloService helloService = getClient(HelloService.class, "127.0.0.1", 50001);
		System.out.println(helloService.hello("liyao1"));
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getClient(Class<T> clazz, String ip, int port){
		return  (T) Proxy.newProxyInstance(RPCClient.class.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler() {
			
			@Override
			public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
				Socket socket = new Socket(ip, port);
				ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
				out.writeUTF(arg1.getName());
				out.writeObject(arg1.getParameterTypes());
				out.writeObject(arg2);
				ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
				return in.readObject();
			}
		});
	}
}

这就是远程调用的一个小例子。


可以看到,随便实现一个仅仅是返回字符串的逻辑都是如此的复杂,反射,动态代理,网络io,消息解析等等。。。头疼。。。。

那么什么是rpc呢?既然是框架,那么必然是帮我们做了一下上面的事情的。rpc帮助我们生成了客户端和服务端的消息和io等公共的代码,这样客户端可以直接调用代理类的方法,感知不到远程调用,服务端也只需要注册服务即可,也就是上面的io,反射,代理等等复杂的代码rpc框架都给我们生成了。

使用了rpc框架,我们只需要定义一个接口,然后让rpc框架为我们生成客户端的代理类,同时生成服务端的serversocket类,我们只需要在服务端编写真正的实现类,然后注册在服务器上就可以。其余的事情都是框架做的。

再说一遍,我们只需要:

(1)定义接口;

(2)用接口生成服务端和客户端代理的代码;

(3)编写接口实现;

(4)注册服务;

这下是不是简单了很多,这就是rpc框架的魅力。

下一节我会给出一个thrift的小例子,就可以感受使用框架的便捷。

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值