什么是RPC
RPC 全称 Remote Procedure Call——远程过程调用。在学校学编程,我们写一个函数都是在本地调用就行了。但是在互联网公司,服务都是部署在不同服务器上的分布式系统,服务之间如何调用呢? 答案就是RPC。RPC设计的技术很多,下图列出的是关于RPC涉及的相关技术。
添加图片注释,不超过 140 字(可选)
这里给大家一个非常好用的java面试题大全:
java面试大全:
RPC技术简单说就是为了解决远程调用服务的一种技术,使得调用者像调用本地服务一样方便透明。 下图是客户端调用远端服务的过程:
添加图片注释,不超过 140 字(可选)
1、客户端client发起服务调用请求。2、client stub 可以理解成一个代理ios小火箭节点购买10元一月,会将调用方法、参数按照一定格式进行封装,通过服务提供的地址,发起网络请求。3、消息通过网络传输到服务端。4、server stub接受来自socket的消息5、server stub将消息进行解包、告诉服务端调用的哪个服务,参数是什么6、结果返回给server stub。7、sever stub把结果进行打包交给socket8、socket通过网络传输消息9、client slub 从socket拿到消息。10、client stub解包消息将结果返回给client。一个RPC框架就是把步骤2到9都封装起来。
为什么需要RPC
1、首先要明确一点:RPC可以用HTTP协议实现,并且用HTTP是建立在 TCP 之上最广泛使用的 RPC,但是互联网公司往往用自己的私有协议shadowlink安卓版,比如鹅厂的JCE协议,私有协议不具备通用性为什么还要用呢?因为相比于HTTP协议,RPC采用二进制字节码传输,更加高效也更加安全。2、现在业界提倡“微服务“的概念,而服务之间通信目前有两种方式,RPC就是其中一种。RPC可以保证不同服务之间的互相调用。即使是跨语言跨平台也不是问题,让构建分布式系统更加容易。3、RPC框架都会有服务降级、流量控制的功能,保证服务的高可用。
一个简单例子
下面就举一个
1+1=2
的远程调用的例子。客户端发送两个参数,服务端返回两个数字的相加结果。
RpcConsumer
类调用
CalculateService
中的
Calculate
方法, 首先通过
RpcFramework
中的
call
方法,注册自己想要调用那个服务,返回代理,然后就像本地调用一样去调用
Calculate
方法,计算
People
,““People“`有两个属性都被赋值成1,返回这两个属性相加后的结果。public class RpcConsumer {public static void main(String args[]) { CalculateService service=RpcFramework.call(CalculateService.class,”127.0.0.1″,8888); People people=new People(1,1); String hello=service.Calculate(people); System.out.println(hello); }}生成动态代理的代码如下。客户端在调用方法前会先执行
invoke
方法,建立socket连接,把方法名和参数传递给服务端,然后获取返回结果。
//动态代理机制
public static T call(final Class interfaceClass,String host,int port){ if(interfaceClass==null){ throw new IllegalArgumentException(“调用服务为空”); } if(host==null||host。length()==0){ throw new IllegalArgumentException(“主机不能为null”); } if(port65535){ throw new IllegalArgumentException(“端口不合法”+port); } return (T)Proxy。newProxyInstance(interfaceClass。getClassLoader(),new Class[]{interfaceClass},new CallerHandler(host,port)); } static class CallerHandler implements InvocationHandler { private String host; private int port; public CallerHandler(String host, int port) { this。
host = host; this。port = port; SERVER = new InetSocketAddress(host, port); } 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(); } } }
RpcProvider
类实现具体的
Calculate
方法。通过
RpcFramework
中的
publish
方法,发布自己的服务。public class RpcProvider{ public static void main(String[] args) throws Exception { CalculateService service =new CalculateServiceImpl(); RpcFramework.publish(service,8888); }}interface CalculateService{ String Calculate(People p);}class CalculateServiceImpl implements CalculateService{ public String Calculate(People people){ int res=people.getA()+people.getB(); return “计算结果 “+res; }}发布服务的代码如下。服务端循环监听某个端口,采用java原生的序列化方法,读取客户端需要调用的方法和参数,执行该方法并将结果返回。public static void publish(final Object service,int port) throws IOException { if(service==null) throw new IllegalArgumentException(“发布服务不能是空”); if(port65535) throw new IllegalArgumentException(“端口不合法”+port); ServerSocket server=new ServerSocket(port); while (true) { 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(); } } }可以看到正确返回计算结果2。
添加图片注释,不超过 140 字(可选)






还没有评论,来说两句吧...