当前位置: 首页 > news >正文

利用netty手写rpc框架

前言:利用netty异步事件驱动的网络通信模型,来实现rpc通信

一、大致目录结构:

二、两个端:服务端(发布),客户端(订阅消费),上代码:

1.服务端(发布):

RPCServer:

代码:

public class RpcServer {private Map<String, Object> registryMap = new HashMap<>();private List<String> classCache = new ArrayList<>();// 1.实现发布;实现方式:// 1.1查找指定目录下的所有接口,放入一个集合中// 1.2遍历所有接口,放入一个map中存放接口路径及接口名称// 1.3发送方法相关信息public void publish(String providerPackage) throws Exception {getProviderClass(providerPackage);doRegister();NioEventLoopGroup parentGroup = new NioEventLoopGroup();NioEventLoopGroup childGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(parentGroup, childGroup).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.SO_KEEPALIVE, true).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();pipeline.addLast(new ObjectEncoder());pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));pipeline.addLast(new RpcServerHandler(registryMap));}});ChannelFuture future = serverBootstrap.bind(9999).sync();System.out.println("服务端监听9999端口,启动成功。。。");future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {parentGroup.shutdownGracefully();childGroup.shutdownGracefully();}}private void doRegister() throws Exception {if (classCache.size() > 0) {for (String className :classCache){Class<?> clazz = Class.forName(className);String interfaceName = clazz.getInterfaces()[0].getName();registryMap.put(interfaceName, clazz.newInstance());}}}/*** 获取当前目录下的所有接口,汇总到一个集合中* @param providerPackage*/private void getProviderClass(String providerPackage) {URL resource =         this.getClass().getClassLoader().getResource(providerPackage.replaceAll("\\.", "/"));File file = null;if (resource != null) {file = new File(resource.getFile());}if (file != null) {for (File f : Objects.requireNonNull(file.listFiles())) {if (f.isDirectory()) {getProviderClass(providerPackage + "." + f.getName());} else if (f.getName().endsWith(".class")) {String fileName = f.getName().replace(".class", "").trim();classCache.add(providerPackage + "." + fileName);}}}}}

服务端处理器:用于处理消费端发送过来的接口数据

代码:

public class RpcServerHandler extends ChannelInboundHandlerAdapter {private Map<String, Object> registryMap;public RpcServerHandler(Map<String, Object> registryMap) {this.registryMap = registryMap;}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("rpc-server收到客户端消息:" + msg);if (msg instanceof InvokeMessage) {InvokeMessage method = (InvokeMessage) msg;Object result = "rpc-server端没有该方法";// 判断是否存在该方法if (registryMap.containsKey(method.getClassName())) {Object provider = registryMap.get(method.getClassName());result = provider.getClass().getMethod(method.getMethodName(), method.getParamTypes()).invoke(provider, method.getParamValues());}// 把方法返回结果,发给订阅者ctx.channel().writeAndFlush(result);ctx.close();}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}

接口的实现类:这里的接口是客户端的接口Api

代码:

public class SsenServiceApiImpl implements SsenServiceApi {@Overridepublic String hellRpc(String name) {return name + "实现类方法";}
}

2.客户端:(订阅消费)

这里采用JDK原生的基于接口的动态代理f发

public class RpcProxy {// JDK基于接口的动态代理,用于创建代理对象public static <T> T create(Class<?> clazz) {return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(proxy, method, args);}// 通过netty将接口信息发送给提供者,获取指定方法return RpcInvoke(clazz, method, args);}});}private static Object RpcInvoke(Class<?> clazz, Method method, Object[] args) {NioEventLoopGroup eventGroup = new NioEventLoopGroup();RpcClientHandler rpcClientHandler = new RpcClientHandler();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(eventGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();pipeline.addLast(new ObjectEncoder());pipeline.addLast(new ObjectDecoder(Integer.MAX_VALUE,ClassResolvers.cacheDisabled(null)));pipeline.addLast(rpcClientHandler);}});// 绑定指定服务地址ChannelFuture future = bootstrap.connect("localhost", 9999).sync();// 指定接口信息发送给提供者InvokeMessage invokeMessage = new InvokeMessage();invokeMessage.setClassName(clazz.getName());invokeMessage.setMethodName(method.getName());invokeMessage.setParamTypes(method.getParameterTypes());invokeMessage.setParamValues(args);future.channel().writeAndFlush(invokeMessage).sync();future.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {eventGroup.shutdownGracefully();}return rpcClientHandler.getResult();}}

相关文章:

利用netty手写rpc框架

前言&#xff1a;利用netty异步事件驱动的网络通信模型&#xff0c;来实现rpc通信 一、大致目录结构&#xff1a; 二、两个端&#xff1a;服务端&#xff08;发布&#xff09;&#xff0c;客户端&#xff08;订阅消费&#xff09;&#xff0c;上代码&#xff1a; 1.服务端&am…...

js+views 压缩上传的图片

安装image-conversion插件&#xff0c;在before-upload方法中对上传的图片文件进行处理 遇到的问题&#xff1a; 1、因为在上传文件之前的钩子中对图片进行了压缩处理&#xff0c;所以组件中上传的data会丢失&#xff0c;需要重新赋值 2、imageConversion 的引入需要使用impor…...

【安卓基础5】中级控件

&#x1f3c6;作者简介&#xff1a;|康有为| &#xff0c;大四在读&#xff0c;目前在小米安卓实习&#xff0c;毕业入职 &#x1f3c6;本文收录于 安卓学习大全持续更新中&#xff0c;欢迎关注 &#x1f3c6;安卓学习资料推荐&#xff1a; 视频&#xff1a;b站搜动脑学院 视频…...

Arthas—【学习篇】

1. Arthas官网 arthas 2. 下载 从 Maven 仓库下载 最新版本&#xff0c;点击下载&#xff1a;​编辑在新窗口打开 点击这个 mavrn-central 即可显示下面的图片 ​​ #从 Github Releases 页下载 Releases alibaba/arthas GitHub 3. 解压 将压缩包复制到一个位置&…...

css pointer-events 多层鼠标点击事件

threejs 无法滑动视角&#xff0c;菜单界面覆盖threejs操作事件。 pointer-events /* Keyword values */ pointer-events: auto; pointer-events: none; pointer-events: visiblePainted; /* SVG only */ pointer-events: visibleFill; /* SVG only */ pointer-events: visib…...

k8s中基于alpine的pod无法解析域名问题

现象 在pod内无法解析指定域名 # 执行ping bash-4.4# ping xx-xx-svc-0.xxx-fcp.svc.cluster.local ping: bad address xx-xx-svc-0.xxx-fcp.svc.cluster.local排查经过 # 执行nslookup bash-4.4# nslookup xx-xx-svc-0.xxx-fcp.svc.cluster.local Server: 172.43.0…...

缩小ppt文件大小的办法

之前用别人模版做了个PPT&#xff0c;100多M,文件存在卡顿问题 解决办法&#xff1a; 1.找到ppt中哪个文件过大&#xff0c;针对解决 2.寻找视频/音频文件&#xff0c;减少体积 3.字体文件是不是过多的问题。 一、文件寻找的内容步骤&#xff1a; 步骤&#xff1a; 1.把p…...

vue3中使用 tui-image-editor进行图片处理,并上传

效果图 下载包 pnpm i tui-image-editor pnpm i tui-color-picker调用组件 //html部分 <el-dialog v-model"imgshow" destroy-on-close width"40%" draggable align-center :show-close"true":close-on-click-modal"false">&l…...

18.贪心算法

排序贪心 区间贪心 删数贪心 统计二进制下有多少1 int Getbit_1(int n){int cnt0;while(n){nn&(n-1);cnt;}return cnt; }暴力加一维前缀和优化 #include <iostream> #include <climits> using namespace std; #define int long long const int N2e510; in…...

[AI]部署安装有道QanyThing

前提条件&#xff1a; 1、win10系统更新到最新的版本&#xff0c;系统版本最好为专业版本 winver 查看系统版本&#xff0c;内部版本要大于19045 2、CPU开启虚拟化 3、开启虚拟化功能&#xff0c;1、2、3每步完成后均需要重启电脑&#xff1b; 注&#xff1a;windows 虚拟…...

NLP_BERT与GPT争锋

文章目录 介绍小结 介绍 在开始训练GPT之前&#xff0c;我们先比较一下BERT和 GPT 这两种基于 Transformer 的预训练模型结构&#xff0c;找出它们的异同。 Transformer架构被提出后不久&#xff0c;一大批基于这个架构的预训练模型就如雨后春笋般地出现了。其中最重要、影响…...

放一个还看得过去的后台模板设置模块css样式框架

#小李子9479# 如下图 <div class"grid col-3 margin-top-xl"><?php$clist array(cyan, yellow, purple, red, blue, brown);foreach ($clist as $kk > $vv) {?><div style"max-width:400px;width:100%;padding:10px;"><div cl…...

关于信号强度单位dB和dBm区别

dB&#xff0c;dBm 都是功率增益的单位&#xff0c;不同之处如下&#xff1a; 一、dB 是一个相对值&#xff0c;表示两个量的相对大小关系&#xff0c;没有单位。当考虑甲的功率相比于乙功率大或小多少个dB时&#xff0c;按下面的计算公式&#xff1a;10log&#xff08;甲功率/…...

华清远见作业第四十二天——Qt(第四天)

思维导图&#xff1a; 编程&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTextToSpeech> //语音播报类 QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public Q…...

vue2和vue3区别 浅析

vue2和vue3区别 浅析 数据响应原理 vue2 通过 Object.defineProperty 来更新数据,只会监听使用Object.defineProperty创建的(初始化)的数据&#xff0c;并通过订阅方式进行发布&#xff0c;在初始化之外的数据&#xff0c;不会受到监听&#xff1b; 在数据初始化时&#xf…...

GIT使用和简介

Git 是一个版本控制系统&#xff0c;它可以追踪文件的更改&#xff0c;并可以在不同的分支上进行并行开发。下面是 Git 的基本概念和使用方式的解释&#xff1a; 1. 仓库&#xff08;Repository&#xff09;&#xff1a;仓库是用来存储项目代码的地方。一个仓库可以包含多个文…...

HTTPS(超文本传输安全协议)被恶意请求该如何处理。

HTTPS&#xff08;超文本传输安全协议&#xff09;端口攻击通常是指SSL握手中的一些攻击方式&#xff0c;比如SSL握手协商过程中的暴力破解、中间人攻击和SSL剥离攻击等。 攻击原理 攻击者控制受害者发送大量请求&#xff0c;利用压缩算法的机制猜测请求中的关键信息&#xf…...

QT-模拟电梯上下楼

QT-模拟电梯上下楼 一、演示效果二、核心程序三、下载链接 一、演示效果 二、核心程序 #include "ElevatorController.h" #include <QGridLayout> #include <QLabel> #include <QGroupBox> #include <QGridLayout> #include <QPushButto…...

基于springboot+vue的桂林旅游景点导游平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

设计模式四:适配器模式

1、适配器模式的理解 适配器模式可以理解为有两个现成的类Adaptee和Target&#xff0c;它们两个是不能动的&#xff0c;要求必须使用B这个类来实现一个功能&#xff0c;但是A的内容是能复用的&#xff0c;这个时候我们需要编写一个转换器 适配器模式 Adaptee&#xff1a;被适…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟

2025年4月29日&#xff0c;在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上&#xff0c;可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞&#xff0c;强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...

云原生安全实战:API网关Envoy的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口&#xff0c;负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...

若依项目部署--传统架构--未完待续

若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加&#xff0c;传统开发模式存在效率低&#xff0c;重复劳动多等问题。若依项目通过整合主流技术框架&…...

零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)

经过前面几期的内容我们学习了很多网络安全的知识&#xff0c;而这期内容就涉及到了前面的第六期-RCE模块&#xff0c;第七期-File inclusion模块&#xff0c;第八期-Unsafe Filedownload模块。 什么是"遍历"呢&#xff1a;对学过一些开发语言的朋友来说应该知道&…...