RPC(2)------ Netty(NIO) + 多种序列化协议 + JDK动态代理实现

news2024/11/27 10:33:47

依赖包解释

Guava
包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 所有这些工具每天都在被Google的工程师应用在产品服务中。

Jackson
用来序列化和反序列化 json 的 Java 的开源框架.

  1. jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json
  2. jackson-annotations,注解包,提供标准注解功能;
  3. jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。

netty一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。

版本回顾

在前面实现的RPC(1)------Java BIO + JDK原生序列化 + JDK动态代理实现 中,是基于java多线程的阻塞调用,每次客户端调用,服务端都会开启一个线程来处理客户端请求,这也是上个版本的缺点。这次基于netty的版本就是针对上个版本的缺陷来做出的优化,代码见V2.0

基于NIO的RPC实现

本次更新主要是在rpc-core模块,将前一个基于socket实现的功能放在socket包下,codec包下是序列化和反序列化代码,netty包下是基于netty实现的rpc客户端和服务端;serializer包下是实现的几种不同的序列化算法。

在这里插入图片描述

关于netty的基本组件介绍可以参考netty快速入门

netty client

首先创建NioEventLoopGroup线程组,然后创建bootstrap对象,配置参数

public class NettyClient implements RpcClient {

    private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);
    private static final Bootstrap bootstrap;

    private CommonSerializer serializer;

    static {
        EventLoopGroup group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.SO_KEEPALIVE, true);
    }

    private String host;
    private int port;

    public NettyClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

然后是实现sendrequest方法,这个和socket实现的一样,发送客户端请求,然后等待请求结果返回,功能一样,我们主要看netty的实现方式。

  1. 首先初始化channel以及绑定handler
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new CommonDecoder())//in
                        .addLast(new CommonEncoder(serializer))//out
                        .addLast(new NettyClientHandler());//in
            }
        });
  1. 然后绑定端口,连接服务器发送请求
//sync方法是等待异步操作执行完毕
ChannelFuture future = bootstrap.connect(host, port).sync();
            logger.info("客户端连接到服务器 {}:{}", host, port);
            Channel channel = future.channel();
            if (channel != null) {
                channel.writeAndFlush(rpcRequest).addListener(future1 -> {
                    if (future1.isSuccess()) {
                        logger.info(String.format("客户端发送消息: %s", rpcRequest.toString()));
                    } else {
                        logger.error("发送消息时有错误发生: ", future1.cause());
                    }
                });
  1. 然后在channel上获取返回信息,这个信息是在NettyClientHandler处理器上添加的
//主线程会在执行完bind().sync()方法后,不执行后面的代码
                channel.closeFuture().sync();
                AttributeKey<RpcResponse> key = AttributeKey.valueOf("rpcResponse" + rpcRequest.getRequestId());
                RpcResponse rpcResponse = channel.attr(key).get();
                RpcMessageChecker.check(rpcRequest, rpcResponse);
                return rpcResponse.getData();

服务端也类似,这里不再详细贴出

核心理解,pipeline执行流程

pipeline是存储通道处理器(Handler)的链表,在netty中,通道处理器分为两种:

  1. 入站处理器:一般都是ChannelInboundHandlerAdapter以及它的子类实现。
  2. 出站处理器:一般都是ChannelOutboundHandlerAdapter以及它的子类实现。
    一个是in,一个是out,入站处理器只处理入站请求,出站处理器只处理出站请求。
    了解到次,我们看一下服务端的pipeline和客户端的pipeline

服务端接收到请求时

服务端接收到请求时,即相对于服务端来说,数据是入站请求,执行入站处理器,handler从左到右执行,执行CommonDecoder(反序列化)和NettyServerHandler,CommonEncoder是出站处理器,不执行.
在这里插入图片描述

服务端返回到请求结果时

服务端处理完请求之后返回结果时,对于服务端来说,数据是出站请求,执行出站处理器,handler从右到左执行,只执行出站处理器CommonEncoder(序列化).
在这里插入图片描述

客户端也是这样分析

在这里插入图片描述

序列化方法不在详细说明

V2.0和V1.0对比

定义协议包

Magic Number 魔数,表识一个 MRF 协议包,0xCAFEBABE
Package Type 包类型,标明这是一个调用请求还是调用响应
Serializer Type 序列化器类型,标明这个包的数据的序列化方式
Data Length 数据字节的长度,反序列化时读取数据
Data Bytes 传输的对象,通常是一个RpcRequest或RpcClient对象,取决于Package Type字段,对象的序列化方式取决于Serializer Type字段。

netty通信

小问题

  1. HessianSerializer序列化时,反序列化为什么不需要类型clazz,而是直接readObject?
    Hessian协议是"自描述"的,查看序列化后的16进制序列和Hseeian协议提供的"码表"就可以解码出来所有的。详情看这篇

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows部署Jar包的三种方式

文章目录1、cmd命令启动2、bat脚本启动2.1 启动jar包2.2 关闭服务3、使用WinSW3.1 重命名3.2 xml配置3.3 安装服务3.4 卸载服务3.5 启动和停止服务1、cmd命令启动 这种方式比较简单&#xff0c;但是窗口关闭后服务也就被杀死了&#xff0c;命令如下 java -jar xxx.jar2、bat脚…

nignx(安装,正反代理,安装tomcat设置反向代理,ip透传)

1安装nginx 安装wget Yum install -y wget 下载(链接从官网找到右键获取) 以下过程root 安装gcc Yum -y install gcc c 安装pcre Yum install -y pcre pcre-devel Openssl Yum install -y openssl openssl-devel 安装zlib Yum install -y zlib zlib-devel 安装make Yum inst…

纯手动搭建hadoop集群记录001_搭建虚拟机_调通网络_配置静态IP_安装JDK---大数据之Hadoop3.x工作笔记0162

1.首先准备机器,172.19.126.115 172.19.126.116 172.19.126.117 我准备了3台 Windows机器 2.然后我打算在Windows机器上使用虚拟机,搭建3台Centos虚拟机来进行安装hadoop 3.这里我们的3台windows机器中的,3台linux虚拟机也使用了3个IP,分别是 172.19.126.120 172.19.126.1…

Redis 删除策略和内存淘汰策略

文章目录一、过期数据二、数据删除策略2-1 定时删除2-2 惰性删除2-3 定期删除三、内存淘汰策略3-1 新数据进入检测3-2 影响数据逐出的相关配置3-3 八种数据逐出策略提示&#xff1a;以下是本篇文章正文内容&#xff0c;Redis系列学习将会持续更新 一、过期数据 Redis中的数据特…

jvm知识点

jvm面试总结 类加载机制? 如何把类加载到jvm中 ? 装载–>链接–>初始化–>使用–>卸载 装载: ClassFile–>字节流–>类加载器将字节流所代表的静态结构转化为方法区的运行时数据结构在我们的堆中生成一个代表这个类的java.lang.Class对象 链接: 验证–…

MATLAB/Simulink 通信原理及仿真学习(三)

文章目录MATLAB/Simulink 通信原理及仿真学习&#xff08;三&#xff09;3. 通信信号与系统分析3.1 离散信号和系统3.1.1 离散信号3.1.2 离散时间信号3.1.3 信号的能量和功率3.2 傅里叶&#xff08;Fourier&#xff09;分析3.2.1 连续时间信号的Fourier变换3.2.2 离散时间信号的…

IDEA-使用插件远程连接Redis

前言 IDEA连接Redis可视化&#xff0c;可以在IDEA中&#xff0c;删除存储的缓存等操作 使用 点击工具栏的File->Settings->Plugins&#xff0c;然后进行搜索Redis,我这里下载过了 然后点击Install进行下载&#xff0c;下载好后&#xff0c;重启IDE 然后会提示&#xf…

什么是Struts2?有哪些优势

Java中Strutsl是最早的基于MVC模式的轻量级Web框架&#xff0c;它能够合理地划分代码结构&#xff0c;并包含验证框架、国际化框架等多种实用工具框架。但是随着技术的进步&#xff0c;Struts1的局限性也越来越多地暴露出来。为了符合更加灵活、高效的开发需求&#xff0c;Stru…

求职者:“我有五年测试经验”面试官: “不,你只是把一年的工作经验用了五年”

最近看到很多软件测试由于公司裁员而需要重新求职的。他们普遍具有4年甚至更长的工作经验。但求职结果往往都不太理想。 我在与部分软件测试求职者交谈的过程中发现&#xff0c;很多人的工作思路不清晰&#xff0c;技能不扎实&#xff0c;没有持续学习的习惯&#xff0c;但对于…

非对称密钥PKCS#1和PKCS#8格式互相转换(Java)

目录一、序言二、代码示例1、Maven依赖2、工具类封装三、测试用例1、密钥文件2、公私钥PKCS1和PKCS8格式互相转换一、序言 之前在 《前后端RSA互相加解密、加签验签、密钥对生成》 中提到过PKCS#1格式和PKCS#8格式密钥的区别以及如何生成密钥。实际有些场景中有可能也会涉及到…

过来人的忠告:如何入门网络安全?

前沿概述 随着2017年《网络安全法》颁布和2019年《等保2.0》正式实施&#xff0c;以及越来越多大学开设网络空间安全、电子对抗等专业&#xff0c;网络安全也被大家熟知&#xff0c;很多人想入行网络安全。作为信息安全毕业&#xff0c;也在安全领域摸爬滚打十年的我&#xff…

和平精英五曜赐福返场,老款玛莎返场来了

和平精英五曜赐福返场&#xff0c;老款玛莎返场来了&#xff01;新款如何选择&#xff01; 关于返场的新消息&#xff0c;都说云南百收SEO解说消息不准&#xff0c;之前看过文章的应该会知道&#xff0c;全网只有云南百收SEO解说发了。玛莎返场&#xff0c;快喊你的阿姨来看&a…

wordpress 网站备份

一个网站从建站完成之日&#xff0c;备份的问题就要提上日程。不论是后期的更换服务器&#xff0c;更换域名&#xff0c;未知故障导致网站崩溃&#xff0c;数据丢失&#xff0c;只要我们有完整的备份&#xff0c;就能将损失降到最低。wordpress网站的备份方法多种多样&#xff…

将闲置的Ipad作为Windows的副屏(Twomon SE)

目录一、前言二、方法第一步 安装软件第二步 使用步骤三、注意一、前言 在看网课的时候&#xff0c;总有种不得劲的感觉&#xff0c;来来回回的切换就很糟心~~无意间看见闲置的板砖&#xff08;Ipad&#xff09;&#xff0c;计上心来-- _ – 期间也尝试过免费的软件&#xff…

【面试题】TCP如何保证传输可靠性?TCP流量控制实现、拥塞控制、ARQ协议、停止等待ARQ、连续ARQ

文章目录1. TCP 如何保证传输的可靠性&#xff1f;2.TCP 如何实现流量控制&#xff1f;3.TCP 的拥塞控制是怎么实现的&#xff1f;3.ARQ 协议了解吗?4.停止等待 ARQ 协议5.连续 ARQ 协议1. TCP 如何保证传输的可靠性&#xff1f; 基于数据块传输 &#xff1a;应用数据被分割成…

【C++】C++入门(上)

前言&#xff1a; C是在C语言的基础上不断添加东西形成的一门语言&#xff0c;在C语言的基础上引入了面向对象的思想。因此C既是面向对象的语言&#xff0c;也是面向过程的语言。因为C是以C语言为基础的&#xff0c;所以基本上C兼容所有的C语言。目前最常用的版本是C98和C11这两…

Java通过SNMP4J管理设备

一、Windows开启SNMP服务这里以Windows11为例&#xff1a;1、安装SNMP服务(1)通过winx快捷键打开电脑“设置”&#xff0c;然后在“应用”中选择”可选功能“。(2)点击”可选功能“的”查看功能“(3)找到并勾选“WMI SNMP 供应商"&#xff0c;再点击”下一步“。这里借用下…

【MySQL】sql中explain解释和应用

这里写目录标题学习原因MySQL中explain的使用和用法解释explain的使用explain 运行结果的意义文字展示表格展示参考资料&#xff1a;结束语学习原因 在对sql的优化过程中使用了explain对指定的sql进行查看它的运行效果&#xff0c;以便找出sql的性能特点并进行优化 MySQL中ex…

20230222解决在WIN7下的UltraEdit9不能新建文件但是可以打开TXT文件

20230222解决在WIN7下的UltraEdit9不能新建文件但是可以打开TXT文件 2023/2/22 17:34 UltraEdit-32 Cannot edit file Cant create tempory file 确定 解决方式&#xff1a; C:\Users\Administrator\AppData\Local\Temp目录下的内容清除即可。 Temp文件夹竟然写满了&#xff…

Python进阶知识

目录 一、装饰器和闭包 1、装饰器 decorator 2、闭包 closure 二、迭代器与生成器 二、面向对象编程 1、概念 2、类和对象 2.1 概念 2.2 定义类和创建对象 2.3 __init__(self): 2.4 self的理解 3、魔术方法 3.1__str__() 3.2 __new__() 4、析构方法 5、类的继…