用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 一、下载插…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
