用netty实现简易rpc
文章目录
- rpc介绍:
- rpc调用流程:
- 代码:
rpc介绍:
RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。
rpc调用流程:
代码:
public interface HelloService {String hello(String msg);
}
public class HelloServiceImpl implements HelloService {@Overridepublic String hello(String msg) {System.out.println("读取到客户端信息:" + msg);if (msg != null) {return "已收到客户端信息【" + msg + "】";} else {return "已收到客户端信息";}}
}
public class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {// 接收客户端发送的信息,并调用服务// 规定每次发送信息时 都以"HelloService#hello#开头“, 其中最后一个#后面的为参数String message = msg.toString();System.out.println("最初消息:" + message);if (message.startsWith("HelloService#hello#")) {String arg = message.substring(19);System.out.println("接收的参数:" + arg);String result = new HelloServiceImpl().hello(arg);ctx.writeAndFlush(result);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 出现异常时关闭通道ctx.close();}
}
public class NettyServer {/*** 启动服务** @param host 主机地址* @param port 线程端口*/private static void startServer0(String host, int port) {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() { // workerGroup@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// String的编码解码器pipeline.addLast(new StringEncoder());pipeline.addLast(new StringDecoder());pipeline.addLast(new NettyServerHandler()); // 自定义业务处理器}});// 绑定端口并启动ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();System.out.println("服务器启动:");// 监听关闭channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {throw new RuntimeException(e);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}public static void startServer(String host, int port) {startServer0(host, port);}
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable {private ChannelHandlerContext channelHandlerContext;private String result; // 服务端返回的数据private String param; // 客户端调用方法时传入的参数/*** 与服务器建立连接时被调用** @param ctx* @throws Exception*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("channelActive 被调用");this.channelHandlerContext = ctx;}/*** 收到服务器数据时被调用** @param ctx* @param msg* @throws Exception*/@Overridepublic synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(" channelRead 被调用 ");result = msg.toString();// 唤醒等待的线程。notifyAll();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}/*** 当某个线程执行NettyClientHandler任务时,会调用get()方法,get()方法会阻塞当前线程,* 直到任务执行完成并返回结果或抛出异常。** @return* @throws Exception*/@Overridepublic synchronized Object call() throws Exception {System.out.println("call--1 ");channelHandlerContext.writeAndFlush(param);
// TimeUnit.MILLISECONDS.sleep(5 * 1000);wait(); // 等待channelRead()方法的调用System.out.println("call--2 ");return result;}/*** 设置参数** @param param*/public void setParam(String param) {this.param = param;}
}
public class NettyClient {// 设置为cpu核数个线程private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());private static NettyClientHandler nettyClientHandler;private static void initClient() {nettyClientHandler = new NettyClientHandler();EventLoopGroup group = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true) // tcp无延迟.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringEncoder());pipeline.addLast(new StringDecoder());pipeline.addLast(nettyClientHandler);}});try {ChannelFuture sync = bootstrap.connect("127.0.0.1", 7000).sync();} catch (InterruptedException e) {throw new RuntimeException(e);}}public Object getBean(final Class<?> serviceClass, final String providerName) {/*** newProxyInstance()方法的第三个参数为实现了java.lang.reflect.InvocationHandler接口的类,*/return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> {if (nettyClientHandler == null) {System.out.println("nettyClientHandler 被初始化");initClient();}System.out.println("进入到匿名内容类");nettyClientHandler.setParam(providerName + args[0]);return executorService.submit(nettyClientHandler).get();});}
}
public class ServerBootStrapService {public static void main(String[] args) {NettyServer.startServer("127.0.0.1",7000);}
}
public class ConsumerBootStrap {public final static String ProviderName = "HelloService#hello#";public static void main(String[] args) throws InterruptedException {NettyClient nettyClient = new NettyClient();/*** helloService为代理对象*/HelloService helloService = (HelloService) nettyClient.getBean(HelloService.class, ProviderName);for (int i = 0; ; ) {TimeUnit.MILLISECONDS.sleep(2000);/*** 当helloService调用hello()方法时,会进入到 实现了InvocationHandler类中的invoke()方法,也就是这个匿名内部类:(proxy, method, args) -> {* if (nettyClientHandler == null) {* initClient();* }* nettyClientHandler.setParam(providerName + args[0]);* return executorService.submit(nettyClientHandler).get();*/helloService.hello("哈喽,哈喽: " + i++);}}
}
gitee地址:https://gitee.com/okgoodfine/rpc-netty
相关文章:

用netty实现简易rpc
文章目录 rpc介绍:rpc调用流程:代码: rpc介绍: RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接…...

【计算机网络】第三章课后习题答案
习题目录: 【3-01】数据链路(即逻辑链路)与链路(即物理链路)有何区别?"链路接通了"与"数据链路接通了"的区别何在? 【3-02】数据链路层中的链路控制包括哪些功能…...

cesium 地图蒙版遮罩效果
示例代码 <!DOCTYPE html> <html lang"en"><head><!-- Use correct character set. --><meta charset"utf-8" /><!-- Tell IE to use the latest, best version. --><meta http-equiv"X-UA-Compatible"…...

根据前序遍历结果构造二叉搜索树
根据前序遍历结果构造二叉搜索树-力扣 1008 题 题目说明: 1.preorder 长度>1 2.preorder 没有重复值 直接插入 解题思路: 数组索引[0]的位置为根节点,与根节点开始比较,比根节点小的就往左边插,比根节点大的就往右…...

微信小程序指定某个元素强制重新渲染
之前写过 vue强制让某个元素重新渲染 利用了vue中的 v-if会控制元素是否挂载 以及 $nextTick 等待响应式更改生效再执行的特性 小程序也都有类似的方法 我们可以这样 wxml <view wx:if"{{min true}}">你好</view>用 wx:if 作用和v-if是一样的 js th…...

国际教材概念基础
各种区别 缩写 A-LEVEL(大学预科):General Certificate of Education Advanced Level AP:Advanced Placement(美国地区:美高AP) GCSE:General Certificate of Secondary Educati…...

2023全国大学生软件测试大赛开发者测试练习题满分答案(PairingHeap2023)
2023全国大学生软件测试大赛开发者测试练习题满分答案(PairingHeap2023) 题目详情题解代码(直接全部复制到test类中即可) 提示:该题只需要分支覆盖得分即可,不需要变异得分 题目详情 题解代码(…...

介绍一下tokens
“Tokens” 是一个计算机科学和自然语言处理领域常用的术语,通常用于表示文本中的最小单位。在这个上下文中,我将解释一下 “tokens” 的含义以及它们在不同领域中的用途: 自然语言处理 (NLP): 在自然语言处理中,“token” 是指文…...

机器学习、深度学习相关的项目集合【自行选择即可】
【基于YOLOv5的瓷砖瑕疵检测系统】 YOLOv5是一种目标检测算法,它是YOLO(You Only Look Once)系列模型的进化版本。YOLOv5是由Ultralytics开发的,基于一阶段目标检测的概念。其目标是在保持高准确率的同时提高目标检测的速度和效率…...

百面机器学习书刊纠错
百面机器学习书刊纠错 P243 LSTM内部结构图 2023-10-7 输入门的输出 和 candidate的输出 进行按元素乘积之后 要和 遗忘门*上一层的cell state之积进行相加。...

vue2安装cesium并使用
一、安装 1.安装cesium npm install cesium1.95.0 -S 2.安装所需 npm install copy-webpack-plugin10.2.4 -D 二、配置 1.配置vue.config.js vue 中引入cesium 需要用copy-webpack-plugin 把一些文件拷贝到打包目录 // vue.config.js const CopyWebpackPlugin require…...

基于Docker来部署Nacos的注册中心
基于Docker来部署Nacos的注册中心 准备MySQL数据库表nacos.sql,用来存储Nacos的数据。 最终表结构如下: 在本地nacos/custom.env文件中,有一个MYSQL_SERVICE_HOST也就是mysql地址,需要修改为你自己的虚拟机IP地址: …...

黑马JVM总结(三十一)
(1)类加载器-概述 启动类加载器-扩展类类加载器-应用程序类加载器 双亲委派模式: 类加载器,加载类的顺序是先依次请问父级有没有加载,没有加载自己才加载,扩展类加载器在getParent的时候为null 以为Boots…...

【C++】list基本接口+手撕 list(详解迭代器)
父母就像迭代器,封装了他们的脆弱...... 手撕list目录: 一、list的常用接口及其使用 1.1list 构造函数与增删查改 1.2list 特殊接口 1.3list 排序性能分析 二、list 迭代器实现(重点难点) 关于迭代器的引入知识:…...

PowerShell pnpm : 无法加载文件 C:\Users\lenovo\AppData\Roaming\npm\pnpm.ps1
1、右键点击【开始】,打开Windows PowerShell(管理员) 2、运行命令set-ExecutionPolicy RemoteSigned 3、根据提示,输入A,回车 此时管理员权限已经可以运行pnpm 如果vsCode还报该错误 继续输入 4、右键点击【开始】,打…...

mysql面试题33:Blob和text有什么区别
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Blob和text有什么区别 Blob和text是数据库中存储大文本数据的两种数据类型&#…...

docker版jxTMS使用指南:4.6版升级内容
4.6版jxTMS已经发布,升级了多个重大能力,本系列文章将逐一进行讲解。 docker版本的使用,请查看:docker版jxTMS使用指南 4.0版jxTMS的说明,请查看:4.0版升级内容 4.2版jxTMS的说明,请查看&…...

java最优建树算法
建树算法 树的数据结构 {"code": "1111","name": "","parentcode": "0000","children": null }, {"code": "2222","name": "","parentcode": &q…...

mysql面试题30:什么是数据库连接池、应用程序和数据库建立连接的过程、为什么需要数据库连接池、你知道哪些数据库连接池
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:什么是数据库连接池? 数据库连接池是一种用于管理和复用数据库连接的技术。它是在应用程序和数据库之间建立一组数据库连接,并以池的形式存储起…...

【Vue】vscode格式刷插件Prettier以及配置项~~保姆级教程
文章目录 前言一、下载插件二、在项目内创建配置文件1.在根目录创建,src同级2.写入配置3.每个字段含义 总结 前言 vscode格式刷,有太多插件了,但是每个的使用,换行都不一样。 这里我推荐一个很多人都推荐了的Prettier 一、下载插…...

.NET 8 中的调试增强功能
作者:James Newton-King 排版:Alan Wang 开发人员喜欢 .NET 强大且用户友好的调试体验。您可以在您选择的 IDE 中设置断点,启动已经附加上调试器的程序,逐步执行代码并查看 .NET 应用程序的状态。 在 .NET 8 中,我们致…...

1310. 数三角形
知识点:(a, b)与(c, d)两点连线上点的个数为:gcd(x, y) 1(包括端点) (设横坐标差的绝对值为x, 纵坐标差的绝对值为y ) 思路:先算出选三个点的所有情况,再减去三点共线的情况 共线的斜率为0时特判 当共线…...

数据库基础(一)
数据库面试基础 注,本文章内容主要来自于JAVAGUIDE,只是结合网上资料和自己的知识缺陷进行一点补充,需要准备面试的请访问官方网址。 一、范式 参考链接 函数依赖:一张表中,确定X则必定能确定Y,则X->…...

Factory-Method
Factory-Method 动机 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具…...

【C++】神奇字符串(力扣481)
神奇字符串的规律: 神奇字符串 s 仅由 ‘1’ 和 ‘2’ 组成,并需要遵守下面的规则: 神奇字符串 s 的神奇之处在于,串联字符串中 1 和 2 的连续出现次数可以生成该字符串。 s 的前几个元素是 s “1221121221221121122……” 。如果…...

elasticsearch索引的数据类型以及别名的使用
在上篇文章写了关于elasticsearch索引的数据类型,这里就详细说下索引的增删改查以及其他的一些操作吧。 1、索引的增、删、改、查 先新建一个索引结构,代码如下 PUT test-3-2-1 {"mappings": {"properties": {"id": {&…...

分布式锁2:基于redis实现分布式锁
一 redis实现分布式锁 1.1 原理 setnxexpiredel 命令实现redis的分布式锁;其中 setnx 不存在则新增;存在则忽略。即先用setnx来抢锁,如果抢到之后,再用expire给锁设置一个过期时间,防止锁忘记了释放。例如…...

【Vue面试题十六】、Vue.observable你有了解过吗?说说看
文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官:Vue.observable你有了解…...

Centos7使用nginx搭建rtmp流媒体服务器
为什么写这篇文章 2023年10月份,公司系统中有个需求,需要使用摄像头记录工程师在维修设备时的工作状态,找到了一家做执法记录仪的厂商,通过厂商发过来的文档了解到该执法记录仪支持通过rtmp协议推流至服务器,第一次接…...

Springboot+vue4S店车辆管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue4S店车辆管理系统(有报告),Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的4S店车辆管理系统,采用M(…...