Java核心知识点整理大全15-笔记

Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客

Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客

Java核心知识点整理大全3-笔记_希斯奎的博客-CSDN博客

Java核心知识点整理大全4-笔记-CSDN博客

Java核心知识点整理大全5-笔记-CSDN博客

Java核心知识点整理大全6-笔记-CSDN博客

Java核心知识点整理大全7-笔记-CSDN博客

Java核心知识点整理大全8-笔记-CSDN博客

Java核心知识点整理大全9-笔记-CSDN博客

Java核心知识点整理大全10-笔记-CSDN博客

Java核心知识点整理大全11-笔记-CSDN博客

Java核心知识点整理大全12-笔记-CSDN博客

Java核心知识点整理大全13-笔记-CSDN博客

Java核心知识点整理大全14-笔记-CSDN博客

往期快速传送门👆:


目录

7.1.7. API 管理

8. Netty 与 RPC

8.1.1. Netty 原理

8.1.2. Netty 高性能

8.1.2.1. 多路复用通讯方式

8.1.2.1. 异步通讯 NIO

8.1.2.2. 零拷贝(DIRECT BUFFERS 使用堆外直接内存)

8.1.2.3. 内存池(基于内存池的缓冲区重用机制)

8.1.2.4. 高效的 Reactor 线程模型

Reactor 多线程模型

主从 Reactor 多线程模型

8.1.2.5. 无锁设计、线程绑定

8.1.2.6. 高性能的序列化框架

小包封大包,防止网络阻塞

软中断 Hash 值和 CPU 绑定

8.1.3. Netty RPC 实现

8.1.3.1. 概念

8.1.3.2. 关键技术

8.1.3.3. 核心流程

8.1.3.1. 消息编解码

序列化

8.1.3.1. 通讯过程

核心问题(线程暂停、消息乱序)

通讯流程

存放回调对象 callback 到全局 ConcurrentHashMap

synchronized 获取回调对象 callback 的锁并自旋 wait

监听消息的线程收到消息,找到 callback 上的锁并唤醒

8.1.4. RMI 实现方式


7.1.7. API 管理

SwaggerAPI 管理工具。

8. Netty 与 RPC

8.1.1. Netty 原理

Netty 是一个高性能、异步事件驱动的 NIO 框架,基于 JAVA NIO 提供的 API 实现。它提供了对 TCP、UDP 和文件传输的支持,作为一个异步 NIO 框架,Netty 的所有 IO 操作都是异步非阻塞 的,通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。

8.1.2. Netty 高性能

在 IO 编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者 IO 多路复用技术 进行处理。IO 多路复用技术通过把多个 IO 的阻塞复用到同一个 select 的阻塞上,从而使得系统在 单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O 多路复用的 最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程 的运行,降低了系统的维护工作量,节省了系统资源。 与 Socket 类和 ServerSocket 类相对应,NIO 也提供了 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现。

8.1.2.1. 多路复用通讯方式

Netty 架构按照 Reactor 模式设计和实现,它的服务端通信序列图如下

客户端通信序列图如下:

Netty 的 IO 线程 NioEventLoop 由于聚合了多路复用器 Selector,可以同时并发处理成百上千个 客户端 Channel,由于读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于 频繁 IO 阻塞导致的线程挂起。

8.1.2.1. 异步通讯 NIO

由于 Netty 采用了异步通信模式,一个 IO 线程可以并发处理 N 个客户端连接和读写操作,这从根 本上解决了传统同步阻塞 IO 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极 大的提升。

8.1.2.2. 零拷贝(DIRECT BUFFERS 使用堆外直接内存)

1. Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读写, 不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行 Socket 读写, JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入 Socket 中。相比于堆外直接内存, 消息在发送过程中多了一次缓冲区的内存拷贝。

2. Netty 提供了组合 Buffer 对象,可以聚合多个 ByteBuffer 对象,用户可以像操作一个 Buffer 那样 方便的对组合 Buffer 进行操作,避免了传统通过内存拷贝的方式将几个小 Buffer 合并成一个大的 Buffer。

3. Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel, 避免了传统通过循环 write 方式导致的内存拷贝问题

8.1.2.3. 内存池(基于内存池的缓冲区重用机制)

随着 JVM 虚拟机和 JIT 即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓 冲区 Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽 量重用缓冲区,Netty 提供了基于内存池的缓冲区重用机制。

8.1.2.4. 高效的 Reactor 线程模型

常用的 Reactor 线程模型有三种,Reactor 单线程模型, Reactor 多线程模型, 主从 Reactor 多线程模 型。 Reactor 单线程模型 Reactor 单线程模型,指的是所有的 IO 操作都在同一个 NIO 线程上面完成,NIO 线程的职责如下:

1) 作为 NIO 服务端,接收客户端的 TCP 连接;

2) 作为 NIO 客户端,向服务端发起 TCP 连接;

3) 读取通信对端的请求或者应答消息;

4) 向通信对端发送消息请求或者应答消息

由于 Reactor 模式使用的是异步非阻塞 IO,所有的 IO 操作都不会导致阻塞,理论上一个线程可以独 立处理所有 IO 相关的操作。从架构层面看,一个 NIO 线程确实可以完成其承担的职责。例如,通过 Acceptor 接收客户端的 TCP 连接请求消息,链路建立成功之后,通过 Dispatch 将对应的 ByteBuffer 派发到指定的 Handler 上进行消息解码。用户 Handler 可以通过 NIO 线程将消息发送给客户端。

Reactor 多线程模型

Rector 多线程模型与单线程模型最大的区别就是有一组 NIO 线程处理 IO 操作。 有专门一个 NIO 线程-Acceptor 线程用于监听服务端,接收客户端的 TCP 连接请求; 网络 IO 操作-读、写 等由一个 NIO 线程池负责,线程池可以采用标准的 JDK 线程池实现,它包含一个任务队列和 N 个可用的线程,由这些 NIO 线程负责消息的读取、解码、编码和发送;

主从 Reactor 多线程模型

服务端用于接收客户端连接的不再是个 1 个单独的 NIO 线程,而是一个独立的 NIO 线程池。 Acceptor 接收到客户端 TCP 连接请求处理完成后(可能包含接入认证等),将新创建的 SocketChannel 注册到 IO 线程池(sub reactor 线程池)的某个 IO 线程上,由它负责 SocketChannel 的读写和编解码工作。Acceptor 线程池仅仅只用于客户端的登陆、握手和安全 认证,一旦链路建立成功,就将链路注册到后端 subReactor 线程池的 IO 线程上,由 IO 线程负 责后续的IO 操作。

8.1.2.5. 无锁设计、线程绑定

Netty 采用了串行无锁化设计,在 IO 线程内部进行串行操作,避免多线程竞争导致的性能下降。 表面上看,串行化设计似乎 CPU 利用率不高,并发程度不够。但是,通过调整 NIO 线程池的线程 参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列多个工作线程模型性能更优。

Netty 的 NioEventLoop 读取到消息之后,直接调用 ChannelPipeline 的 fireChannelRead(Object msg),只要用户不主动切换线程,一直会由 NioEventLoop 调用 到用户的 Handler,期间不进行线程切换,这种串行化处理方式避免了多线程操作导致的锁 的竞争,从性能角度看是最优的。

8.1.2.6. 高性能的序列化框架

Netty 默认提供了对 Google Protobuf 的支持,通过扩展 Netty 的编解码接口,用户可以实现其它的 高性能序列化框架,例如 Thrift 的压缩二进制编解码框架。 1. SO_RCVBUF 和 SO_SNDBUF:通常建议值为 128K 或者 256K。

小包封大包,防止网络阻塞

2. SO_TCPNODELAY:NAGLE 算法通过将缓冲区内的小封包自动相连,组成较大的封包,阻止大量 小封包的发送阻塞网络,从而提高网络应用效率。但是对于时延敏感的应用场景需要关闭该优化算 法。

软中断 Hash 值和 CPU 绑定

3. 软中断:开启 RPS 后可以实现软中断,提升网络吞吐量。RPS 根据数据包的源地址,目的地址以 及目的和源端口,计算出一个 hash 值,然后根据这个 hash 值来选择软中断运行的 cpu,从上层 来看,也就是说将每个连接和 cpu 绑定,并通过这个 hash 值,来均衡软中断在多个 cpu 上,提升 网络并行处理性能。

8.1.3. Netty RPC 实现

8.1.3.1. 概念

RPC,即 Remote Procedure Call(远程过程调用),调用远程计算机上的服务,就像调用本地服务一 样。RPC 可以很好的解耦系统,如 WebService 就是一种基于 Http 协议的 RPC。这个 RPC 整体框架 如下:


8.1.3.2. 关键技术

1. 服务发布与订阅:服务端使用 Zookeeper 注册服务地址,客户端从 Zookeeper 获取可用的服务 地址。

2. 通信:使用 Netty 作为通信框架。

3. Spring:使用 Spring 配置服务,加载 Bean,扫描注解。

4. 动态代理:客户端使用代理模式透明化服务调用。

5. 消息编解码:使用 Protostuff 序列化和反序列化消息。

8.1.3.3. 核心流程

1. 服务消费方(client)调用以本地调用方式调用服务;

2. client stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;

3. client stub 找到服务地址,并将消息发送到服务端;

4. server stub 收到消息后进行解码;

5. server stub 根据解码结果调用本地的服务;

6. 本地服务执行并将结果返回给 server stub;

7. server stub 将返回结果打包成消息并发送至消费方;

8. client stub 接收到消息,并进行解码;

9. 服务消费方得到最终结果。

RPC 的目标就是要 2~8 这些步骤都封装起来,让用户对这些细节透明。JAVA 一般使用动态代 理方式实现远程调用。


8.1.3.1. 消息编解码

息数据结构(接口名称+方法名+参数类型和参数值+超时时间+ requestID)

客户端的请求消息结构一般需要包括以下内容:

1. 接口名称:在我们的例子里接口名是“HelloWorldService”,如果不传,服务端就不知道调用哪 个接口了;

2. 方法名:一个接口内可能有很多方法,如果不传方法名服务端也就不知道调用哪个方法;

3. 参数类型和参数值:参数类型有很多,比如有 bool、int、long、double、string、map、list, 甚至如 struct(class);以及相应的参数值;

4. 超时时间:

5. requestID,标识唯一请求 id,在下面一节会详细描述 requestID 的用处。

6. 服务端返回的消息 : 一般包括以下内容。返回值+状态 code+requestID

序列化

目前互联网公司广泛使用 Protobuf、Thrift、Avro 等成熟的序列化解决方案来搭建 RPC 框架,这 些都是久经考验的解决方案。

8.1.3.1. 通讯过程

核心问题(线程暂停、消息乱序)

如果使用 netty 的话,一般会用 channel.writeAndFlush()方法来发送消息二进制串,这个方 法调用后对于整个远程调用(从发出请求到接收到结果)来说是一个异步的,即对于当前线程来说, 将请求发送出来后,线程就可以往后执行了,至于服务端的结果,是服务端处理完成后,再以消息 的形式发送给客户端的。于是这里出现以下两个问题:

1. 怎么让当前线程“暂停”,等结果回来后,再向后执行?

2. 如果有多个线程同时进行远程方法调用,这时建立在 client server 之间的 socket 连接上 会有很多双方发送的消息传递,前后顺序也可能是随机的,server 处理完结果后,将结 果消息发送给 client,client 收到很多消息,怎么知道哪个消息结果是原先哪个线程调用 的?如下图所示,线程 A 和线程 B 同时向 client socket 发送请求 requestA 和 requestB, socket 先后将 requestB 和 requestA 发送至 server,而 server 可能将 responseB 先返 回,尽管 requestB 请求到达时间更晚。我们需要一种机制保证 responseA 丢给 ThreadA,responseB 丢给 ThreadB。

通讯流程

requestID 生成-AtomicLong

1. client 线程每次通过 socket 调用一次远程接口前,生成一个唯一的 ID,即 requestID (requestID 必需保证在一个 Socket 连接里面是唯一的),一般常常使用 AtomicLong 从 0 开始累计数字生成唯一 ID;

存放回调对象 callback 到全局 ConcurrentHashMap

2. 将 处 理 结 果 的 回 调 对 象 callback , 存 放 到 全 局 ConcurrentHashMap 里 面 put(requestID, callback);

synchronized 获取回调对象 callback 的锁并自旋 wait

3. 当线程调用 channel.writeAndFlush()发送消息后,紧接着执行 callback 的 get()方法试 图获取远程返回的结果。在 get()内部,则使用 synchronized 获取回调对象 callback 的 锁,再先检测是否已经获取到结果,如果没有,然后调用 callback 的 wait()方法,释放 callback 上的锁,让当前线程处于等待状态。

监听消息的线程收到消息,找到 callback 上的锁并唤醒

4. 服务端接收到请求并处理后,将 response 结果(此结果中包含了前面的 requestID)发 送给客户端,客户端 socket 连接上专门监听消息的线程收到消息,分析结果,取到 requestID , 再 从 前 面 的 ConcurrentHashMap 里 面 get(requestID) , 从 而 找 到 callback 对象,再用 synchronized 获取 callback 上的锁,将方法调用结果设置到 callback 对象里,再调用 callback.notifyAll()唤醒前面处于等待状态的线程。

 public Object get() {synchronized (this) { // 旋锁while (true) { // 是否有结果了If (!isDone){wait(); //没结果释放锁,让当前线程处于等待状态}else{//获取数据并处理}}}}
private void setDone(Response res) {this.res = res;isDone = true;synchronized (this) { //获取锁,因为前面 wait()已经释放了 callback 的锁了  notifyAll(); // 唤醒处于等待的线程}}

8.1.4. RMI 实现方式

Java 远程方法调用,即 Java RMI(Java Remote Method Invocation)是 Java 编程语言里,一种用 于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远 程方法调用特性使 Java 编程人员能够在网络环境中分布操作。RMI 全部的宗旨就是尽可能简化远程接 口对象的使用。


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

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

相关文章

【Kotlin】类与接口

文章目录 类的定义创建类的实例构造函数主构造函数次构造函数init语句块 数据类的定义数据类定义了componentN方法 继承AnyAny:非空类型的根类型Any?:所有类型的根类型 覆盖方法覆盖属性覆盖 抽象类接口:使用interface关键字函数:funUnit:让…

RocketMq 队列(MessageQueue)

RocketMq是阿里出品(基于MetaQ)的开源中间件,已捐赠给Apache基金会并成为Apache的顶级项目。基于java语言实现,十万级数据吞吐量,ms级处理速度,分布式架构,功能强大,扩展性强。 官方…

Kerberos 高可用配置和验证

参考 https://cloud.tencent.com/developer/article/1078314 https://mp.weixin.qq.com/s?__bizMzI4OTY3MTUyNg&mid2247485861&idx1&snbb930a497f63ac5e63ed20c64643eec5 机器准备 Kerberos主 ip-172-31-22-86.ap-southeast-1.compute.internal 7.common2.hado…

【华为数通HCIP | 网络工程师】821-IGP高频题、易错题之OSPF(7)

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

C语言盐水的故事(ZZULIOJ1214:盐水的故事)

题目描述 挂盐水的时候,如果滴起来有规律,先是滴一滴,停一下;然后滴二滴,停一 下;再滴三滴,停一下...,现在有一个问题:这瓶盐水一共有VUL毫升,每一滴是D毫升&…

【brpc学习实践八】bvar及其应用

什么是bvar bvar是多线程环境下的计数器类库,支持单维度bvar和多维度mbvar,方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing,相比UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销&a…

STM32 SCF文件

文章目录 1 SCF文件2 SCT分散加载文件3 SCF文件编写 1 SCF文件 keil编译器在链接的时候,是根据分散加载(.scf后缀的文件)来确定程序的加载域和运行域的。 加载域就是程序运行前在flash中具体分区情况执行域就是程序运行后,程序在flash和ram中的分区情况…

在Windows系统上安装git-Git的过程记录

01-上git的官网下载git的windows安装版本 下载页面链接: https://git-scm.com/downloads 选择Standalone Installer的版本进行下载: 这里给大家一全git-2.43.0的百度网盘下载链接: https://pan.baidu.com/s/11HwNTCZmtSWj0VG2x60HIA?pwdut…

Linux 基础-常用的命令和搭建 Java 部署环境

文章目录 目录相关查看目录中的内容查看目录当前的完整路径切换目录 文件相关创建文件查看文件内容写文件vim 基础 创建删除创建目录 移动和复制移动(剪切粘贴)复制(复制粘贴) 搭建 Java 部署环境1. 安装 jdk2. 安装 tomcat1). 我们在自己电脑上下好 tomcat2). 从官网下载的 .z…

MySQL的基础知识

目录 关系型数据库 SQL通用语法 数据类型 数值类型 字符串类型 日期类型 SQL分类 DDL 数据库操作 表操作 DML 添加数据 修改数据 删除数据 DQL 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查询 执行顺序 DCL 管理用户 权限控制 函数 字符串…

iar如何全擦芯片内存

Project ->Download -> Erase memory

js逆向-某敏感网站登录参数分析

声明 本文仅供学习参考,如有侵权可私信本人删除,请勿用于其他途径,违者后果自负! 如果觉得文章对你有所帮助,可以给博主点击关注和收藏哦! 前言 目标网站:aHR0cHM6Ly9tZGZnaGcuNXhwb2lqaHRm…

五种多目标优化算法(MSSA、MOAHA、MOPSO、NSGA3、NSGA2)求解微电网多目标优化调度(MATLAB)

一、多目标优化算法简介 (1)多目标鳟海鞘算法MSSA 多目标优化算法:多目标鳟海鞘算法(Multi-objective Salp Swarm Algorithm ,MSSA)-CSDN博客 参考文献: S. Mirjalili, A.H. Gandomi, S.Z. M…

flex布局实战之自动填充剩余

案例目标 文字部分自适应并且居中 图中是一个弹窗&#xff0c;我现在使用flex的布局来实现&#xff0c;标题和关闭按钮。因为是uni-app,所以标签是view 。你可以自行替换为 代码 <view class"popup-box"><view class"title"><view class&…

线程的状态以及状态转移

一. 线程的状态 NEW: 线程刚被创建, 但是并未启动. 还没调用start方法.RUNNABLE: 这里没有区分就绪和运行状态. 因为对于Java对象来说, 只能标记为可运行, 至于什么时候运行, 不是JVM来控制的了, 是OS来进行调度的, 而且时间非常短暂, 因此对于Java对象的状态来说, 无法区分.T…

97、Text2NeRF: Text-Driven 3D Scene Generation with Neural Radiance Fields

简介 论文地址 使用扩散模型来推断文本相关图像作为内容先验&#xff0c;并使用单目深度估计方法来提供几何先验&#xff0c;并引入了一种渐进的场景绘制和更新策略&#xff0c;保证不同视图之间纹理和几何的一致性 实现流程 简单而言&#xff1a; 文本-图片扩散模型生成一…

STM32入门学习(一):STM32 简介与软件安装

参考引用 STM32 入门教程-江科协 1. STM32 简介 1.1 STM32 套件介绍 1.2 STM32 简介 STM32 是 ST 公司基于 ARM Cortex-M 内核开发的 32 位微控制器 应用&#xff1a;嵌入式领域&#xff0c;如智能车、无人机、机器人、无线通信、物联网、工业控制、娱乐电子产品等 1.3 ARM …

go对rabbitmq基本操作

一、安装rabbitmq 1、直接使用docker拉取镜像 docker pull rabbitmq:3.82、启动容器 docker run \-e RABBITMQ_DEFAULT_USERadmin \-e RABBITMQ_DEFAULT_PASS123456 \-v mq-plugins:/plugins \--name rabbit01 \--hostname rabbit01 --restartalways \-p 15672:15672 \-p 5672:…

《C++PrimePlus》第9章 内存模型和名称空间

9.1 单独编译 Visual Studio中新建头文件和源代码 通过解决方案资源管理器&#xff0c;如图所示&#xff1a; 分成三部分的程序&#xff08;直角坐标转换为极坐标&#xff09; 头文件coordin.h #ifndef __COORDIN_H__ // 如果没有被定义过 #define __COORDIN_H__struct pola…

【开源】基于Vue.js的城市桥梁道路管理系统的设计和实现

项目编号&#xff1a; S 025 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S025&#xff0c;文末获取源码。} 项目编号&#xff1a;S025&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥…