RPC的小demo
理论
RPC其实就是远程程序调用,即Remote Procedure Call,相对于远程程序调用,其实最常见的调用就是本地函数调用,比如main函数中调用两数相加的函数,实现两数相加,这种形式在单体应用中,当然是很常见的,但是对于在分布式的场景下,就无法满足了,比如主机A总是想要主机B上的某些服务,就可以利用远程调用的方式。
但是很容易想到的是,我们可以直接HTTP请求啊,但是利用httpclient需要对于参数这些的设定,无法将模块抽象出来,而RPC则就是要解决远程调用像在本地调用一样简单。
所以,RPC要解决的问题就是:
1、解决分布式环境下,服务之间调用的问题
2、远程调用用,像本地调用一样方便。
RPC其实就相当于一个远程代理
实践
以上就是一个RPC远程调用的示意图,client中的Application通过Client Stub实现远程调用,client Run-Time Library是实现远程调用的工具包,可以是java的socket,也可以是httpclient,因为传输的数据是二进制的,因此需要进行序列化以及反序列化。
服务层
提供两数相加的服务(相当于上图Server中的Application):
AddService:
public interface AddService {
String add(double a,double b);
}
AddServiceImpl:
public class AddServiceImpl implements AddService {
@Override
public String add(double a, double b) {
return String.valueOf(a+b);
}
}
service的RPC封装(Server Stub)
Server:
public interface Server {
public void stop();
public void start() throws IOException;
public void register(Class serviceInterface,Class impl);
public boolean isRunning();
public int getPort();
}
ServiceCenter:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServiceCenter implements Server {
//声明线程池,一个可重用固定个数的线程池
private static ExecutorService executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static final HashMap<String,Class> serviceRegistry=new HashMap<String,Class>();
private static boolean isRunning=false;
private static int port;
public ServiceCenter(int port){
this.port=port;
}
//客户端的请求服务通过socket发送过来远程调用服务端接口并执行得结果
private static class ServiceTask implements Runnable{
Socket client=null;
public ServiceTask(Socket client){
this.client=client;
}
public void