温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

rpc通信是如何进行的

发布时间:2022-01-18 10:10:15 阅读:188 作者:iii 栏目:大数据
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍了rpc通信是如何进行的的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇rpc通信是如何进行的文章都会有所收获,下面我们一起来看看吧。

RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

基本概念

  • RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务

  • 本地过程调用:如果需要将本地student对象的age+1,可以实现一个addAge()方法,将student对象传入,对年龄进行更新之后返回即可,本地方法调用的函数体通过函数指针来指定。

  • 远程过程调用:上述操作的过程中,如果addAge()这个方法在服务端,执行函数的函数体在远程机器上,如何告诉机器需要调用这个方法呢?

今天,我们就通过一个实例代码进行演示,一步步的查看,rpc的通信是如何进行的,有兴趣的朋友可以把代码进行实现,自己debug一下,查看每一步的传参

package com.mashibing.rpc.common;import java.io.Serializable;public class User implements Serializable {    private static final long serialVersionUID = 1L;    private Integer id;    private String name;    public User(Integer id, String name) {        this.id = id;        this.name = name;    }    public Integer getId() {        return id;    }    public String getName() {        return name;    }    public void setId(Integer id) {        this.id = id;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "User{" +                "id=" + id +                ", name='" + name + '\'' +                '}';    }}
package com.mashibing.rpc.common;public interface IUserService {    public User findUserById(Integer id);}
package com.mashibing.rpc01;import com.mashibing.rpc.common.IUserService;import com.mashibing.rpc.common.User;public class UserServiceImpl implements IUserService {    @Override    public User findUserById(Integer id) {        return new User(id, "Alice");    }}
package com.mashibing.rpc01;import com.mashibing.rpc.common.User;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.net.Socket;public class Client {    public static void main(String[] args) throws Exception {        Socket s = new Socket("127.0.0.1", 8888);        ByteArrayOutputStream baos = new ByteArrayOutputStream();        DataOutputStream dos = new DataOutputStream(baos);        dos.writeInt(123);        s.getOutputStream().write(baos.toByteArray());        s.getOutputStream().flush();        DataInputStream dis = new DataInputStream(s.getInputStream());        int id = dis.readInt();        String name = dis.readUTF();        User user = new User(id, name);        System.out.println(user);        dos.close();        s.close();    }}
package com.mashibing.rpc02;import com.mashibing.rpc.common.User;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.net.Socket;public class Stub {    public User findUserById(Integer id) throws Exception {        Socket s = new Socket("127.0.0.1", 8888);        ByteArrayOutputStream baos = new ByteArrayOutputStream();        DataOutputStream dos = new DataOutputStream(baos);        dos.writeInt(123);        s.getOutputStream().write(baos.toByteArray());        s.getOutputStream().flush();        DataInputStream dis = new DataInputStream(s.getInputStream());        int receivedId = dis.readInt();        String name = dis.readUTF();        User user = new User(id, name);        dos.close();        s.close();        return user;    }}
package com.mashibing.rpc03;import com.mashibing.rpc.common.IUserService;import com.mashibing.rpc.common.User;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.net.Socket;/** * 而且Client的调用显得不是很合理(Stub里只有findById的代码),如果有个findByName的新方法,那么就又得重新改进 * 下面这种写法解决了方法增加的问题 */public class Stub {    public static IUserService getStub() {        InvocationHandler h = new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                Socket s = new Socket("127.0.0.1", 8888);                ByteArrayOutputStream baos = new ByteArrayOutputStream();                DataOutputStream dos = new DataOutputStream(baos);                dos.writeInt(123);                s.getOutputStream().write(baos.toByteArray());                s.getOutputStream().flush();                DataInputStream dis = new DataInputStream(s.getInputStream());                int id = dis.readInt();                String name = dis.readUTF();                User user = new User(id, name);                dos.close();                s.close();                return user;            }        };        Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {IUserService.class}, h);        return (IUserService)o;    }}
package com.mashibing.rpc04;import com.mashibing.rpc.common.IUserService;import com.mashibing.rpc.common.User;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.net.Socket;/** * 但是这里仅仅实现了findByUserId的方法代理,如果要实现其他方法的代理该怎么做呢? * 这里就要从协议层做出改进 * * 服务器端也要做出对应处理 */public class Stub {    public static IUserService getStub() {        InvocationHandler h = new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                Socket s = new Socket("127.0.0.1", 8888);                ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());                String methodName = method.getName();                Class[] parametersTypes = method.getParameterTypes();                oos.writeUTF(methodName);                oos.writeObject(parametersTypes);                oos.writeObject(args);                oos.flush();                DataInputStream dis = new DataInputStream(s.getInputStream());                int id = dis.readInt();                String name = dis.readUTF();                User user = new User(id, name);                oos.close();                s.close();                return user;            }        };        Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {IUserService.class}, h);        return (IUserService)o;    }}
package com.mashibing.rpc04;import com.mashibing.rpc.common.IUserService;import com.mashibing.rpc.common.User;import java.io.*;import java.lang.reflect.Method;import java.net.ServerSocket;import java.net.Socket;public class Server {    private static boolean running = true;    public static void main(String[] args) throws Exception {        ServerSocket ss = new ServerSocket(8888);        while (running) {            Socket s = ss.accept();            process(s);            s.close();        }        ss.close();    }    private static void process(Socket s) throws Exception {        InputStream in = s.getInputStream();        OutputStream out = s.getOutputStream();        ObjectInputStream oos = new ObjectInputStream(in);        DataOutputStream dos = new DataOutputStream(out);        String methodName = oos.readUTF();        Class[] parameterTypes = (Class[])oos.readObject();        Object[] args = (Object[])oos.readObject();        IUserService service = new UserServiceImpl();        Method method = service.getClass().getMethod(methodName, parameterTypes);        User user = (User)method.invoke(service, args);        dos.writeInt(user.getId());        dos.writeUTF(user.getName());        dos.flush();    }}

返回值用Object封装,支持任意类型

关于“rpc通信是如何进行的”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“rpc通信是如何进行的”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4472036/blog/4551213

rpc
AI

开发者交流群×