使用 Netty 实现 RPC 通信框架
使用 Netty 实现 RPC 通信框架
远程过程调用(RPC,Remote Procedure Call) 是分布式系统中非常重要的通信机制。它允许客户端调用远程服务器上的方法,就像调用本地方法一样。RPC 的核心在于屏蔽底层通信细节,使开发者关注业务逻辑。
Netty 作为一个高性能的网络通信框架,非常适合实现 RPC 框架。本篇文章将介绍如何使用 Netty 实现一个简单的 RPC 通信框架。
1. RPC 通信框架基本原理
1.1 核心组成
RPC 框架的核心模块通常包括:
- 服务注册与发现:
- 将服务接口及其实现类的地址注册到中心(如注册中心或简单的服务端映射)。
- 序列化与反序列化:
- 将方法调用、参数等序列化成字节流,传输到远程服务器,服务器再反序列化进行处理。
- 网络通信:
- 使用 Netty 实现客户端和服务端之间的数据传输。
- 动态代理:
- 使用动态代理拦截客户端对接口的调用,将调用信息发送到服务端并返回结果。
1.2 RPC 调用流程
- 客户端:
- 客户端调用代理对象的方法。
- 代理对象将方法、参数打包成 RPC 请求,发送到服务器。
- 服务器:
- 服务器解析 RPC 请求,定位到具体的方法和参数。
- 调用本地方法,获取结果后返回给客户端。
- 客户端:
- 接收服务器的响应,将结果返回给调用者。
2. Netty 实现 RPC 通信框架
2.1 项目结构设计
src/main/java/
├── common/ // 通用模块
│ ├── RpcRequest.java // RPC 请求封装
│ ├── RpcResponse.java // RPC 响应封装
│ ├── Serializer.java // 序列化接口
│ ├── JsonSerializer.java // JSON 序列化实现
├── server/ // 服务端模块
│ ├── RpcServer.java // RPC 服务端
│ ├── ServiceRegistry.java // 服务注册表
├── client/ // 客户端模块
│ ├── RpcClient.java // RPC 客户端
│ ├── RpcProxy.java // 客户端动态代理
2.2 核心代码实现
2.2.1 通用模块
(1) RPC 请求与响应类
RpcRequest 和 RpcResponse 用于封装客户端发送的请求和服务器的响应。
public class RpcRequest {private String methodName; // 方法名private String className; // 类名private Object[] parameters; // 参数private Class<?>[] paramTypes; // 参数类型// Getters and setters
}public class RpcResponse {private Object result; // 方法调用结果private String error; // 错误信息(如果有)// Getters and setters
}
(2) 序列化接口
为确保传输的数据可以跨网络传递,定义序列化与反序列化的接口。
public interface Serializer {byte[] serialize(Object obj); // 序列化<T> T deserialize(byte[] bytes, Class<T> clazz); // 反序列化
}
(3) JSON 序列化实现
使用 Jackson 实现简单的 JSON 序列化。
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonSerializer implements Serializer {private static final ObjectMapper objectMapper = new ObjectMapper();@Overridepublic byte[] serialize(Object obj) {try {return objectMapper.writeValueAsBytes(obj);} catch (Exception e) {throw new RuntimeException("Serialization failed", e);}}@Overridepublic <T> T deserialize(byte[] bytes, Class<T> clazz) {try {return objectMapper.readValue(bytes, clazz);} catch (Exception e) {throw new RuntimeException("Deserialization failed", e);}}
}
2.2.2 服务端模块
(1) 服务注册表
ServiceRegistry 用于存储服务接口与实现类的映射。
import java.util.HashMap;
import java.util.Map;public class ServiceRegistry {private final Map<String, Object> services = new HashMap<>();public void register(String className, Object serviceImpl) {services.put(className, serviceImpl);}public Object getService(String className) {return services.get(className);}
}
(2) RPC 服务端
服务端接收 RPC 请求并调用对应的服务实现。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;public class RpcServer {private final int port;private final ServiceRegistry serviceRegistry;public RpcServer(int port, ServiceRegistry serviceRegistry) {this.port = port;this.serviceRegistry = serviceRegistry;}public void start() throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 4));pipeline.addLast(new LengthFieldPrepender(4));pipeline.addLast(new RpcServerHandler(serviceRegistry));}});ChannelFuture future = bootstrap.bind(port).sync();System.out.println("RPC Server started on port " + port);future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}class RpcServerHandler extends SimpleChannelInboundHandler<RpcRequest> {private final ServiceRegistry serviceRegistry;public RpcServerHandler(ServiceRegistry serviceRegistry) {this.serviceRegistry = serviceRegistry;}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, RpcRequest request) throws Exception {Object service = serviceRegistry.getService(request.getClassName());if (service == null) {ctx.writeAndFlush(new RpcResponse(null, "Service not found"));return;}// 调用服务实现Object result = service.getClass().getMethod(request.getMethodName(), request.getParamTypes()).invoke(service, request.getParameters());ctx.writeAndFlush(new RpcResponse(result, null));}
}
2.2.3 客户端模块
(1) RPC 客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;public class RpcClient {private final String host;private final int port;public RpcClient(String host, int port) {this.host = host;this.port = port;}public RpcResponse send(RpcRequest request) throws InterruptedException {EventLoopGroup group = new NioEventLoopGroup();RpcResponse response = new RpcResponse();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new RpcClientHandler(response));}});Channel channel = bootstrap.connect(host, port).sync().channel();channel.writeAndFlush(request).sync();channel.closeFuture().sync();} finally {group.shutdownGracefully();}return response;}
}class RpcClientHandler extends SimpleChannelInboundHandler<RpcResponse> {private final RpcResponse response;public RpcClientHandler(RpcResponse response) {this.response = response;}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, RpcResponse msg) throws Exception {response.setResult(msg.getResult());response.setError(msg.getError());}
}
(2) 动态代理
import java.lang.reflect.Proxy;public class RpcProxy {private final RpcClient client;public RpcProxy(RpcClient client) {this.client = client;}@SuppressWarnings("unchecked")public <T> T create(Class<T> serviceClass) {return (T) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> {RpcRequest request = new RpcRequest();request.setClassName(serviceClass.getName());request.setMethodName(method.getName());request.setParameters(args);request.setParamTypes(method.getParameterTypes());RpcResponse response = client.send(request);if (response.getError() != null) {throw new RuntimeException(response.getError());}return response.getResult();});}
}
2.3 测试示例
-
定义服务接口和实现:
public interface HelloService {String sayHello(String name); }public class HelloServiceImpl implements HelloService {@Overridepublic String sayHello(String name) {return "Hello, " + name;} } -
服务端注册服务并启动:
ServiceRegistry registry = new ServiceRegistry(); registry.register(HelloService.class.getName(), new HelloServiceImpl());RpcServer server = new RpcServer(8080, registry); server.start(); -
客户端调用服务:
RpcClient client = new RpcClient("localhost", 8080); RpcProxy proxy = new RpcProxy(client);HelloService service = proxy.create(HelloService.class); String result = service.sayHello("Netty"); System.out.println(result); // 输出: Hello, Netty
3. 总结
通过上述代码,我们实现了一个简单的基于 Netty 的 RPC 通信框架,涵盖了服务注册、序列化、网络通信和动态代理等核心模块。
关键点回顾:
- 服务端:通过
ServiceRegistry注册服务,并使用 Netty 接收和处理 RPC 请求。 - 客户端:通过动态代理封装 RPC 调用,简化客户端使用。
- 序列化:使用 JSON 进行数据的序列化和反序列化。
该框架可以作为一个简单的模板,在实际应用中可扩展为支持注册中心(如 Zookeeper)、负载均衡、异步调用等高级功能的完整 RPC 框架。
相关文章:
使用 Netty 实现 RPC 通信框架
使用 Netty 实现 RPC 通信框架 远程过程调用(RPC,Remote Procedure Call) 是分布式系统中非常重要的通信机制。它允许客户端调用远程服务器上的方法,就像调用本地方法一样。RPC 的核心在于屏蔽底层通信细节,使开发者关…...
【机器学习06--贝叶斯分类器】
文章目录 基础理解01 贝叶斯决策论02 极大似然估计03 朴素贝叶斯分类器04 半朴素贝叶斯分类器05 贝叶斯网06 EM算法 补充修正1. 贝叶斯定理与分类的基本概念2. 贝叶斯决策论3. 极大似然估计4. 朴素贝叶斯分类器5. 半朴素贝叶斯分类器6. 贝叶斯网7. EM算法 面试常考 基础理解 本…...
创建vue3项目步骤以及安装第三方插件步骤【保姆级教程】
🎙座右铭:得之坦然,失之淡然。 💎擅长领域:前端 是的,我需要您的: 🧡点赞❤️关注💙收藏💛 是我持续下去的动力! 目录 一. 简单汇总一下创建…...
[146 LRU缓存](https://leetcode.cn/problems/lru-cache/)
分析 维护一个双向链表保存缓存中的元素。 如果元素超过容量阈值,则删除最久未使用的元素。为了实现这个功能,将get(), put()方法获取的元素添加到链表首部。 为了在O(1)时间复杂度执行get()方法,再新建一个映射表,缓存key与链表…...
【Java Nio Netty】基于TCP的简单Netty自定义协议实现(万字,全篇例子)
基于TCP的简单Netty自定义协议实现(万字,全篇例子) 前言 有一阵子没写博客了,最近在学习Netty写一个实时聊天软件,一个高性能异步事件驱动的网络应用框架,我们常用的SpringBoot一般基于Http协议࿰…...
【JavaWeb后端学习笔记】Redis常用命令以及Java客户端操作Redis
redis 1、redis安装与启动服务2、redis数据类型3、redis常用命令3.1 字符串String3.2 哈希Hash3.3 列表List3.4 集合Set(无序)3.5 有序集合zset3.6 通用命令 4、使用Java操作Redis4.1 环境准备4.2 Java操作字符串String4.3 Java操作哈希Hash4.4 Java操作…...
pdb调试器详解
文章目录 1. 启动 pdb 调试器1.1 在代码中插入断点1.2 使用命令行直接调试脚本 2. 常用调试命令2.1 基本命令2.2 高级命令2.3 断点操作 3. 调试过程示例4. 调试技巧4.1 条件断点4.2 自动启用调试4.2.1 运行程序时指定 -m pdb4.2.2在代码中启用 pdb.post_mortem4.2.3 使用 sys.e…...
项目15:简易扫雷--- 《跟着小王学Python·新手》
项目15:简易扫雷 — 《跟着小王学Python新手》 《跟着小王学Python》 是一套精心设计的Python学习教程,适合各个层次的学习者。本教程从基础语法入手,逐步深入到高级应用,以实例驱动的方式,帮助学习者逐步掌握Python的…...
Flink CDC实时同步mysql数据
官方参考资料: https://nightlies.apache.org/flink/flink-cdc-docs-master/zh/docs/connectors/flink-sources/mysql-cdc/ Apache Flink 的 Change Data Capture (CDC) 是一种用于捕获数据库变化(如插入、更新和删除操作)的技术。Flink CDC…...
题解 - 自然数无序拆分
题目描述 美羊羊给喜羊羊和沸羊羊出了一道难题,说谁能先做出来,我就奖励给他我自己做的一样礼物。沸羊羊这下可乐了,于是马上答应立刻做出来,喜羊羊见状,当然也不甘示弱,向沸羊羊发起了挑战。 可是这道题目…...
dfs_bool_void 两种写法感悟
dfs 的两种写法 在看之前实现图的遍历 dfs 和拓扑排序 dfs 实现的代码的时候的感悟 图的遍历 dfs 和拓扑排序 dfs 的区别 0 → 1 ↓ ↓ 2 → 3图的邻接表表示: adjList[0] {1, 2}; adjList[1] {3}; adjList[2] {3}; adjList[3] {};正常的 DFS 遍历&#x…...
MySQL 主从复制与 Binlog 深度解析
目录 1. Binlog的工作原理与配置2. 主从复制的设置与故障排除3. 数据一致性与同步延迟的处理 小结 MySQL的binlog(二进制日志)和主从复制是实现数据备份、容灾、负载均衡以及数据同步的重要机制。在高可用性架构和分布式数据库设计中,binlog同…...
大连理工大学《2024年845自动控制原理真题》 (完整版)
本文内容,全部选自自动化考研联盟的:《大连理工大学845自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦 目录 2024年真题 Part1:2024年完整版真题 2024年真题...
Java性能调优 - 多线程性能调优
锁优化 Synchronized 在JDK1.6中引入了分级锁机制来优化Synchronized。当一个线程获取锁时 首先对象锁将成为一个偏向锁,这样做是为了优化同一线程重复获取锁,导致的用户态与内核态的切换问题;其次如果有多个线程竞争锁资源,锁…...
行为树详解(4)——节点参数配置化
【分析】 行为树是否足够灵活强大依赖于足够丰富的各类条件节点和动作节点,在实现这些节点时,不可避免的,节点本身需要有一些参数供配置。 这些参数可以分为静态的固定值的参数以及动态读取设置的参数。 静态参数直接设置为Public即可&…...
计算机网络中的三大交换技术详解与实现
目录 计算机网络中的三大交换技术详解与实现1. 计算机网络中的交换技术概述1.1 交换技术的意义1.2 三大交换技术简介 2. 电路交换技术2.1 理论介绍2.2 Python实现及代码详解2.3 案例分析 3. 分组交换技术3.1 理论介绍3.2 Python实现及代码详解3.3 案例分析 4. 报文交换技术4.1 …...
《杨辉三角》
题目描述 给出 n(1≤n≤20)n(1≤n≤20),输出杨辉三角的前 nn 行。 如果你不知道什么是杨辉三角,可以观察样例找找规律。 输入格式 无 输出格式 无 输入输出样例 输入 #1复制 6 输出 #1复制 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 C语言…...
ARM学习(35)单元测试框架以及MinGW GCC覆盖率报告
单元测试框架以及MinGW GCC覆盖率报告 1、单元测试与覆盖率简介 随着代码越写越多,越来越需要注意自测的重要性,基本可以提前解决90%的问题,所以就来介绍一下单元测试,单元测试是否测试充分,需要进行评价,覆盖率就是单元测试是否充分的评估工具。 例如跑过单元测试后,…...
边缘计算+人工智能:让设备更聪明的秘密
引言:日常生活中的“智能”设备 你是否发现,身边的设备正变得越来越“聪明”? 早上醒来时,智能音箱已经根据你的日程播放舒缓音乐;走进厨房,智能冰箱提醒你今天的食材库存;而在城市道路上&…...
neo4j知识图谱AOPC的安装方法
AOPC下载链接:aopc全版本github下载 APOC,全称为Awesome Procedures On Cypher,是Neo4j图数据库的一个非常强大和流行的扩展库。它极大地丰富了Cypher查询语言的功能,提供了超过450个过程(procedures)和函数…...
为AI智能体项目选择与接入高性价比大模型API服务
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为AI智能体项目选择与接入高性价比大模型API服务 在构建AI智能体或自动化工作流时,开发者面临的核心挑战往往集中在两个…...
AutoML、NAS与超参数调优:工程落地的三层协同方法论
1. 这不是“一键炼丹”,而是给算法工程师配一套智能扳手 AutoML、NAS 和超参数调优——这三个词最近几年在机器学习工程圈里出现的频率,几乎和“模型上线”“数据质量差”“GPU又爆了”一样高。但现实很骨感:我带过三支不同行业的算法团队&am…...
Unity背包系统设计终极指南:ScriptableObject+事件总线+对象池
1. 为什么“背包系统”不是功能模块,而是游戏世界的呼吸节奏 在Unity项目里,我见过太多团队把背包系统当成一个“做完就扔”的中间件:美术给图标、策划填Excel表格、程序写个List 塞进UI面板,跑通基础增删就打上✅。结果呢&#x…...
iOS系统更新策略解析:从安全补丁到版本选择,如何理性应对系统升级
1. 从iOS 17.6.1看苹果的系统更新策略:一次“小修小补”背后的深意最近关于iOS 18和iOS 18.1的讨论铺天盖地,各种AI功能、界面大改的传闻让人眼花缭乱。但如果你像我一样,日常接触大量不同型号的iPhone用户,就会发现一个有趣的现象…...
DeepSeek V2安全对齐能力深度拆解(含对抗攻击测试报告+合规审计清单)
更多请点击: https://codechina.net 第一章:DeepSeek V2安全对齐能力深度拆解(含对抗攻击测试报告合规审计清单) DeepSeek V2 在设计阶段即嵌入多层安全对齐机制,涵盖输入过滤、策略蒸馏、响应重加权与后验校验四大核…...
5分钟搞定!RK3588开发板Ubuntu系统终极配置指南 [特殊字符]
5分钟搞定!RK3588开发板Ubuntu系统终极配置指南 🚀 【免费下载链接】ubuntu-rockchip Ubuntu for Rockchip RK35XX Devices 项目地址: https://gitcode.com/gh_mirrors/ub/ubuntu-rockchip 还在为RK3588开发板的系统配置发愁吗?别担心…...
收藏!2026大模型风口来了,小白程序员如何抓住高薪机会?必看!
文章指出2026年是技术红利年,大模型领域竞争格局变化明显。国内开源模型如DeepSeek、GLM等取得巨大进展,领先全球。从业者待遇提升,应届生薪酬普遍破百万。招聘方更看重新技能,如万亿MoE、Agent等。文章强调AGI的核心是通用性&…...
ABAP云迁移中SAML Bearer断言实战指南
1. 这不是“配置一下就能用”的流程——SAML Bearer Assertion 在 ABAP 云迁移中到底在替谁干活?你刚接手一个 SAP S/4HANA Cloud 扩展项目,客户要求“把本地 ABAP 系统里的用户身份,安全地透传到新上线的 Node.js 微服务里”。运维同事甩来一…...
WinUtil:一键解决Windows系统优化与软件安装的终极指南
WinUtil:一键解决Windows系统优化与软件安装的终极指南 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil 你是否曾为新电脑安装系统…...
CrewAI 多智能体 Unity 自动开发项目的三轮迭代复盘
这是一篇技术讨论文章,不是产品宣传。我把 MyCrew 项目从 v1(一个 CrewAI 模板 demo)到 v2(弃用的桌面应用)再到 v3(当前 188 commits、约 6 万行代码的 Tauri FastAPI 工程)的全部弯路、踩坑、…...
