RPC 框架 2022-02-08 程序之旅 暂无评论 452 次阅读 ## RPC 框架 > 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在 Java 领域中有很多可以实现远程通讯的技术,例如:RMI、Hessian、SOAP、ESB 和 JMS 等。其基本原理是基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 TCP、UDP 等,TCP、UDP 都是基于 Socket 概念上为某类应用场景而扩展出来的传输协议。 ### RPC 概念 全称 remote procedure call,即远程过程调用。借助 RPC 可以做到像本地调用一样调用远程服务。`RPC 并不是一个具体的技术,而是只整个网络远程调用过程`。 ```sequence 方法 A - 方法 B: 本地调用 方法 B -- 方法 A: 结果返回 ``` ```sequence note over 服务 1 ,服务 2: 远程调用 note over 服务 1 ,服务 2: 返回结果 ``` 一个完整的 RPC 框架里边包含了四个核心的组件,分别是 Client,Client Stub,Server 以及 Server Stub,这个 Stub 可以理解为存根。 - 客户端(Client),服务的调用方。 - 客户端存根(Client Stub),存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。 - 服务端(Server),真正的服务提供者。 - 服务端存根(Server Stub),接收客户端发送过来的消息,将消息解包,并调用本地的方法。 ### RMI Java RMI,即远程方法调用 (Remote Method Invocation),一种用于实现远程调用(RPC-Remote procedure call)的 Java API,能直接传输序列化后的 Java 对象。RMI 的实现依赖于 Java 虚拟机,因此只能支持一个 JVM 到另一个 JVM 的调用。 #### 代码示例使用 ##### 需求分析 1. 服务端提供 ID 查询用户的方法 2. 客户端调用服务端方法,并返回用户对象 3. 要求使用 RMI 进行远程通讯 ##### 代码实现 服务端 ```java /** * 服务端 */ public class RMIServer { public static void main(String[] args) { try { //1.注册Registry实例. 绑定端口 Registry registry = LocateRegistry.createRegistry(9998); //2.创建远程对象 IUserService userService = new UserServiceImpl(); //3.将远程对象注册到RMI服务器上即(服务端注册表上) registry.rebind("userService", userService); System.out.println("---RMI服务端启动成功----"); } catch (RemoteException e) { e.printStackTrace(); } } } ``` 客户端 ```java /** * 客户端 */ public class RMIClient { public static void main(String[] args) throws RemoteException, NotBoundException { //1.获取Registry实例 Registry registry = LocateRegistry.getRegistry("127.0.0.1", 9998); //2.通过Registry实例查找远程对象 IUserService userService = (IUserService) registry.lookup("userService"); User user = userService.getByUserId(2); System.out.println(user.getId() + "----" + user.getName()); } } ``` 接口及其实现类 ```java public interface IUserService extends Remote { User getByUserId(int id) throws RemoteException; } public class UserServiceImpl extends UnicastRemoteObject implements IUserService { Map userMap = new HashMap(); public UserServiceImpl() throws RemoteException { super(); User user1 = new User(); user1.setId(1); user1.setName("张三"); User user2 = new User(); user2.setId(2); user2.setName("李四"); userMap.put(user1.getId(), user1); userMap.put(user2.getId(), user2); } @Override public User getByUserId(int id) throws RemoteException { return userMap.get(id); } } ``` ### Netty 实现 RPC #### 需求分析 使用 Netty 实现一个简单的 RPC 框架,消费者和提供者约定接口和协议,消费者远程调用提供者的服务。 - 创建一个接口,定义抽象方法。用于消费者和提供者之间的约定; - 创建一个提供者,该类需要监听消费者的请求,并按照约定返回数据; - 创建一个消费者,该类需要透明的调用自己不存在的方法,内部需要使用 Netty 进行数据通信 - 提供者与消费者数据传输使用 json 字符串数据格式 - 提供者使用 Netty 集成 Spring Boot 环境实现 #### 代码实现 代码库:https://gitee.com/teaegg/netty-rpc.git 打赏: 微信, 支付宝 标签: RPC, Netty 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。