江阴网站建设推广,wordpress 如何改中文字体,东莞各类免费建站,做海报在哪个网站可以找素材文章目录 一、RPC 调用过程二、RPC 动态代理#xff1a;屏蔽远程通讯细节1. 动态代理示例2. 如何将动态代理应用于 RPC 三、RPC序列化与协议编码1. RPC 序列化2. RPC 协议编码2.1. 协议编码的作用2.2. RPC 协议消息组成 四、RPC 网络传输1. 网络传输流程2. 关键优化点 一、RPC… 文章目录 一、RPC 调用过程二、RPC 动态代理屏蔽远程通讯细节1. 动态代理示例2. 如何将动态代理应用于 RPC 三、RPC序列化与协议编码1. RPC 序列化2. RPC 协议编码2.1. 协议编码的作用2.2. RPC 协议消息组成 四、RPC 网络传输1. 网络传输流程2. 关键优化点 一、RPC 调用过程
RPCRemote Procedure Call远程过程调用是一种让不同网络节点上的服务相互调用的技术。它的核心目标是屏蔽远程调用的复杂性使远程服务的调用方式如同本地调用一样简单。在分布式系统中RPC 通过封装底层网络通信细节提高了服务调用的可用性和开发效率。
RPC 调用流程包括 动态代理客户端通过代理对象调用远程方法。序列化将请求数据转换为二进制格式便于传输。协议编码增加数据包的协议标识和长度信息。网络传输通过网络传递数据包。协议解码服务端解析请求包。反序列化将二进制数据转换回原始对象。执行方法调用对应的远程方法并处理请求。响应返回按照相同的序列化、网络传输等流程将响应结果返回给调用方。 二、RPC 动态代理屏蔽远程通讯细节
动态代理Dynamic Proxy是 Java 提供的一种机制允许在运行时动态创建代理对象拦截方法调用并在调用前后执行额外的逻辑。
在 RPC 场景中动态代理的主要作用是屏蔽底层的远程通信细节让客户端可以像调用本地方法一样调用远程服务。
1. 动态代理示例
示例代码
public interface ServerProvider {void sayHello(String str);
}public class ServerProviderImpl implements ServerProvider {Overridepublic void sayHello(String str) {System.out.println(Hello str);}
}import java.lang.reflect.*;/**
- DynamicProxy 实现了 InvocationHandler用于拦截方法调用并执行代理逻辑。
- invoke 方法中1. method.invoke(realObject, args); 通过反射调用真实对象的方法。
*/
public class DynamicProxy implements InvocationHandler {private Object realObject;public DynamicProxy(Object object) {this.realObject object;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return method.invoke(realObject, args);}
}public class Client {public static void main(String[] args) {ServerProvider realServer new ServerProviderImpl();InvocationHandler handler new DynamicProxy(realServer);ServerProvider proxyInstance (ServerProvider) Proxy.newProxyInstance(handler.getClass().getClassLoader(),realServer.getClass().getInterfaces(),handler);proxyInstance.sayHello(world);}
}通过动态代理客户端不直接依赖于 ServerProviderImpl而是通过接口和代理类进行调用这样
解耦了客户端和服务端不需要在客户端硬编码调用远程方法。方便在代理类中加入 RPC 逻辑比如序列化、网络传输等。增强扩展性可以在 invoke 方法中添加日志、权限校验、负载均衡等功能。 2. 如何将动态代理应用于 RPC
(1) 在代理类中加入远程调用逻辑 (2) 客户端使用代理调用远程服务
Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 1. 构造 RPC 请求RpcRequest request new RpcRequest();request.setMethodName(method.getName());request.setParameters(args);// 2. 发送请求到远程服务RpcResponse response RpcClient.sendRequest(request);// 3. 解析响应并返回结果return response.getResult();
}ServerProvider serverProvider (ServerProvider) Proxy.newProxyInstance(getClass().getClassLoader(),new Class[]{ServerProvider.class},new RpcDynamicProxy(http://remote-server)
);
serverProvider.sayHello(world);
如果想进一步实现 RPC 的完整流程可以加入序列化、网络传输、反序列化等模块搭建一个真正的 RPC 组件 三、RPC序列化与协议编码
1. RPC 序列化
序列化是将对象转换成字节流的过程而反序列化则是恢复对象的过程。常见的序列化方式包括
JSON易读易用但额外空间开销较大。Hessian二进制格式序列化后字节数小性能优于 JSON。Protobuf高效、跨语言支持适用于大规模分布式应用。ThriftFacebook 开源的高效序列化框架结合了 RPC 服务框架。 2. RPC 协议编码
2.1. 协议编码的作用
有了序列化功能就可以将客户端的请求对象转化成字节流在网络上传输了这个字节流转换为二进制信息以后会写入本地的 Socket 中然后通过网卡发送到服务端。从编程角度来看每次请求只会发送一个请求包但是从网络传输的角度来看网络传输过程中会将二进制包拆分成很多个数据包这一点也可以从 TCP 传输数据的原理看出。拆分后的多个二进制包会同时发往服务端服务端接收到这些数据包以后将它们合并到一起再进行反序列化以及后面的操作。
实际上协议编码要做的事情就是对同一次网络请求的数据包进行拆分并且为拆分得到的每个数据包定义边界、长度等信息。 2.2. RPC 协议消息组成
RPC 协议消息由 消息头 和 消息体 组成
消息头 包含协议标识、数据长度、请求类型等信息。消息体 是序列化后的数据。
协议编码的核心目标是确保数据包正确地分片、合并并提供必要的描述信息保障网络传输的可靠性。
消息头部分主要存放消息本身的描述信息如图所示。
名称描述魔术位magic协议魔术为解码设计消息头长度header size用来描述消息头长度为扩展设计协议版本version协议版本用于版本兼容消息体序列化类型st描述消息体的序列化类型例如 JSON、gRPC心跳标记hb每次传输都会建立一个长连接隔一段时间向接收方发送一次心跳请求保证对方始终在线单向消息标记ow标记是否为单向消息响应消息标记rp用来标记是请求消息还是响应消息响应消息状态码status code标记响应消息状态码保留字段reserved用于填充消息保证消息的字节是对齐的消息 Idmessage id用来唯一确定一个消息的标识消息体长度body size描述消息体的长度 四、RPC 网络传输
1. 网络传输流程
在 RPC 调用中服务调用方Client需要发送请求给服务提供方Server然后等待服务器处理并返回响应数据。在这个过程中数据在应用程序、操作系统内核、网络传输三个层次之间流动并涉及多个数据复制操作。
从示意图中可以看出数据的流转主要分为两部分请求发送过程、响应接收过程 请求发送流程Client - Server服务调用方Client发起 RPC 请求其数据流动过程如下
步骤操作数据位置1应用程序写入数据业务代码执行RPC调用将数据写入应用缓冲区User Space2数据复制到内核缓冲区操作系统将应用缓冲区的数据复制到内核缓冲区Kernel Space3通过网络发送数据从内核缓冲区被传输到网卡Network Card并通过网络协议如TCP拆分成数据包发送到远程服务器4服务器接收数据服务器端网卡接收数据包并将其存入内核缓冲区5数据复制到应用缓冲区服务器的内核将数据复制到应用缓冲区6应用程序读取数据服务器端应用程序从应用缓冲区中获取数据执行请求逻辑如数据库查询、业务处理 响应接收流程Server - Client服务提供方Server处理完请求后将结果返回给客户端数据流动过程如下
步骤操作具体内容7应用程序写入数据服务器应用程序生成响应数据并写入应用缓冲区8数据复制到内核缓冲区服务器操作系统将数据从应用缓冲区复制到内核缓冲区准备发送9通过网络发送服务器的网卡将数据包发送到客户端10客户端接收数据客户端网卡接收数据包操作系统将其存入内核缓冲区11数据复制到应用缓冲区数据从内核缓冲区复制到应用缓冲区以便应用程序使用12应用程序读取数据客户端应用程序从应用缓冲区中获取响应数据完成 RPC 调用 通过上面对 RPC 调用流程的描述可以看出服务调用方需要经过一系列的数据复制才能通过网络传输将信息发送到服务提供方。此外可以看出网络 IO 传输和数据计算过程存在先后顺序因此当前者出现延迟时会导致后者处于阻塞。另外应用程序中存在同步调用和异步调用因此衍生出了同步阻塞 IOblocking IO、同步非阻塞 IOnon-blocking IO、多路复用 IOmultiplexing IO这几种 IO 模式。下篇分析ing 2. 关键优化点
RPC 网络传输过程涉及多个阶段包括数据在应用缓冲区、内核缓冲区、网络传输中的流转。优化 RPC 传输的关键在于减少数据复制、优化网络通信、使用异步 I/O 机制提高整体性能。
操作具体内容减少数据复制采用 零拷贝Zero-Copy 技术如 mmap、sendfile避免数据在用户态和内核态之间频繁复制优化网络传输使用 长连接Keep-Alive 避免频繁建立 TCP 连接采用 批量发送、数据压缩 来减少数据传输的开销异步 I/O 处理使用 异步 I/O如 Netty、epoll避免同步阻塞提高并发处理能力优化缓冲区管理采用 池化缓冲区Buffer Pool 避免频繁申请和释放内存