用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/153273.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌 Chrome 浏览器正推进“追踪保护”功能

导读近日消息&#xff0c;根据国外科技媒体 Windows Latest 报道&#xff0c;谷歌计划在 Chrome 浏览器中推进“追踪保护”&#xff08;Tracking Protection&#xff09;功能&#xff0c;整合浏览器现有隐私功能&#xff0c;保护用户被网站跟踪。 根据一项 Chromium 提案&…

unity 控制玩家物体

创建场景 放上一个plane&#xff0c;放上一个球 sphere&#xff0c;假定我们的球就是我们的玩家&#xff0c;使用控制键w a s d 来控制球也就是玩家移动。增加一个材质&#xff0c;把颜色改成绿色&#xff0c;把材质赋给plane&#xff0c;区分我们增加的白球。 增加组件和脚…

06_Node.js服务器开发

1 服务器开发的基本概念 1.1 为什么学习服务器开发 Node.js开发属于服务器开发&#xff0c;那么作为一名前端工程师为什么需要学习服务器开发呢&#xff1f; 为什么学习服务器开发&#xff1f; 能够和后端程序员更加紧密配合网站业务逻辑前置扩宽知识视野 1.2 服务器开发可…

全息投影技术服务公司【盟云全息】收入急剧下降,存在风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 全息投影技术服务公司【盟云全息】MicroCloud Hologram(HOLO)的股价表现今年以来异常出色&#xff0c;年初至今已经上涨了334%以上&#xff0c;猛兽财经将在本文中分析MicroCloud Hologram股价上涨的原因&#xff0c;以及它…

京东获得店铺的所有商品 API接口分享

item_search_shop-获得店铺的所有商品 公共参数 注册API测试key 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,…

深眸科技自研AI视觉分拣系统,实现物流行业无序分拣场景智慧应用

在机器视觉应用环节中&#xff0c;物体分拣是建立在识别、检测之后的一个环节&#xff0c;通过机器视觉系统对图像进行处理&#xff0c;并结合机械臂的使用实现产品分类。 通过引入视觉分拣技术&#xff0c;不仅可以实现自动化作业&#xff0c;还能提高生产线的生产效率和准确…

react管理系统layOut简单搭建

一、新建立react文件夹&#xff0c;生成项目 npx create-react-app my-app cd my-app npm start 二、安装react-router-dom npm install react-router-dom 三、安装Ant Design of React&#xff08;UI框架库&#xff0c;可根据需求进行安装&#xff09; npm install antd …

短剧是什么?短剧平台的经营模式。短剧平台需要什么资质?

​ 短剧&#xff0c;顾名思义&#xff0c;是一种时长较短的戏剧表演形式。它通常以一个简短的故事或情境为主线&#xff0c;通过角色的表演&#xff0c;展现出一段生动、有趣或富有深意的故事。 短剧的时长通常较短&#xff0c;一般在几分钟到半小时之间&#xff0c;但这并不是…

Nginx + PHP 异常排查,open_basedir 异常处理

新上一个网站&#xff0c;通过域名访问失败&#xff0c;排查方法如下&#xff1a; 开启异常日志 开启域名下&#xff0c;nginx的异常日志&#xff0c;并查看日志 tail -f /var/log/nginx/nginx.localhost.error.log开启php的异常日志&#xff0c;该配置位于php.ini文件下 …

青菜餐饮公司资产负债表之二

一、背景 上一篇文章 青菜餐饮公司资产负债表之一 用一个案例来引导学习资产负债表&#xff0c;要做好资产负债表&#xff0c;最关键的是找准科目&#xff0c;左右平衡。资产和负债的概念基本上都比较好理解&#xff0c;对于没有接触过财务知识的人&#xff0c;所有者权益相对…

nginx+HTTPS证书

申请ssl下载证书 阿里云购买免费证书&#xff0c;可免费申请20个&#xff0c;需要配置域名&#xff0c;域名为单个域名&#xff0c;比如www.xxx.com&#xff0c;必须带前缀。 申请完之后需要创建证书 注&#xff1a;创建证书时阿里云购买的域名可以直接给配好解析&#xff0…

自监督DINO论文笔记

论文名称&#xff1a;Emerging Properties in Self-Supervised Vision Transformers 发表时间&#xff1a;CVPR2021 作者及组织&#xff1a; Facebook AI Research GitHub&#xff1a;https://github.com/facebookresearch/dino/tree/main 问题与贡献 作者认为self-supervise…

Linux系列---【查看mac地址】

查看mac地址命令 查看所有网卡命令 nmcli connection show 查看物理网卡mac地址 ifconfig 删除网卡 nmcli connection delete virbr0 禁用libvirtd.service systemctl disable libvirtd.service 启用libvirtd.service systemctl enable libvirtd.service

基于Spring Boot的网上租贸系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技…

iPhone15手机拓展坞方案,支持手机快充+传输数据功能

手机拓展坞的组合有何意义&#xff1f;首先是数据存储场景&#xff0c;借助拓展坞扩展出的接口&#xff0c;可以连接U盘、移动硬盘等采用USB接口的设备&#xff0c;实现大文件的快速存储或者流转&#xff1b;其次是图片、视频的读取场景&#xff0c;想要读取相机、无人机SD/TF存…

大数据学习(2)Hadoop-分布式资源计算hive(1)

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博>主哦&#x…

【Unity3D编辑器开发】Unity3D中制作一个可以随时查看键盘对应KeyCode值面板,方便开发

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中&#xff0c;会遇到要使用监控键盘输入的KeyCode值来执…

10月10日星期二今日早报简报微语报早读

10月10日&#xff0c;星期二&#xff0c;早报简报微语早读分享。 1、全国铁路国庆黄金周运输发送旅客1.95亿人次&#xff1b; 2、贵州公安&#xff1a;三名抢劫杀人嫌犯潜逃至缅北电诈窝点&#xff0c;全部落网&#xff1b; 3、四川&#xff1a;游客擅自进入未开发开放游览活动…

【debian 12】:debian系统切换中文界面

目录 目录 项目场景 基础参数 原因分析 解决方案 1.ctrlaltT 打开终端 2.查询当前语言环境&#xff08;我的已经设置成了中文 zh_CN.UTF-8&#xff09; 3.打开语言配置界面 4.最后一步&#xff1a;重启 不要放弃任何一个机会&#xff01; 项目场景&#xff1a; 这两…

【three.js】结合vue进行开发第一个3d页面

一、创建vue项目 新建一个项目目录&#xff0c;在集成终端打开&#xff0c;输入 npm init vitelatest 回车后&#xff0c;依次输入项目名&#xff0c;选择vue和js开发 然后安装依赖并运行项目 二、安装three 接下来我们开始安装three npm install three 三、Three.js 的…