RPC架构原理

什么是RPC? 它是干什么的? 有什么用? 怎么用?

RPC概念

RPC(remote Procedure Call), 远程过程调用. 来实现不同机器上的系统之间的调用. 就像访问本地资源一样, 通过网络传输访问远端系统资源.

RPC架构实现原理

图片来源于网络

图片来源于网络

架构中的几个重点

  • Client Code:
    • 客户端代码, 负责发起RPC调用, 为调用方用户提供使用API.
  • Serialization/Deserialization:
    • 负责对RPC调用通过网络传输的内容进行序列化反/序列化, 不同的RPC有着不同的实现机制. 主要分为文本与二进制两大类. 文本类别主要有xml和json两种格式.
  • Sub Proxy:
    • 可以看作一种代理对象, 屏蔽RPC调用过程中复杂的网络处理逻辑, 使得RPC调用透明化, 能够保持与本地调用风格一致
  • Transport:
    • 作为RPC框架底层的通信传输模块, 一般通过Socket在客户端与服务端之间传递请求与应答消息
  • Server Code:
    • 服务端业务逻辑具体实现.

抛转引玉 - RMI

Java RMI(Remote Method Invocation) 基于java的远程方法调用技术, 是java特有的一种RPC实现. 它能使不同主机上的java对象进行通信及方法调用.

图片来源于网络 - RMI调用示意图

RMI 代码示例

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface HelloService extends Remote {
    String sayHello(String someone) throws RemoteException;
}

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {

    protected HelloServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public String sayHello(String someone) throws RemoteException {
        System.out.println("sayHello inpute someone : " + someone);
        return "hello : " + someone;
    }
}

RMI 穿透防火墙
RMI的通信端口是随机产生的, 因此有可能会被防火墙拦截. 为防止防火墙拦截, 需要强制指定RMI的通信端口 示例: MySocketFactory.java

public class MySocketFactory extends RMISocketFactory {
    @Override
    public Socket createSocket(String host, int port) throws IOException {
        return new Socket(host, port);
    }

    @Override
    public ServerSocket createServerSocket(int port) throws IOException {
        if (0 == port) {
            port = 8802;
        }
        System.out.println("rmi nofity port: " + port);
        return new ServerSocket(port);
    }
}
public class ClientMain {
    public static void main(String[] args) throws Exception {
        HelloService helloService = (HelloService) Naming.lookup("rmi://localhost:8801/helloService");

        for (int i = 1; i < 9; i++) {

            System.out.println("RMI 服务调用返回结果: " + helloService.sayHello("hahahh" + i));
        }
    }
}
public class ServerMain {
    public static void main(String[] args) throws Exception {
        LocateRegistry.createRegistry(8801);
        //指定通讯端口, 防止被防火墙拦截
        RMISocketFactory.setSocketFactory(new MySocketFactory());
        HelloService helloService = new HelloServiceImpl();
        Naming.bind("rmi://localhost:8801/helloService", helloService);
        System.out.println("ServerMain provide RPC service now.");
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容