深入理解消息队列:如何实现高性能的异步网络传输?

2 物理层(三):数据传输的方式,同步传输和异步传输 如计算机内部或近距离设备的数据传输,如计算机和打印机之间的并行通信一般通过计算机上的并行端口(LPT)进行。定义:并行传输是指数据以成组的方式在多个并行的信道上同时传输,即多个数据位并排同时在线路上传输,相应地需要若干根传输线。定义:串行传输是指数据在信道上一位一位的逐个传输,从发送端到接收端只需一根传输线。4)传输单位:帧(数据块和前后的同步信号一起构成了一个数据单位,称为帧)4)传输单位:帧(字符,与前面的起始位,及后面的逻辑位构成一个数据单位)1)传输内容:一个大的数据块(一组数据或一个报文) 阅读详情
本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等

异步与同步模型最大的区别是,同步模型会阻塞线程等待资源,而异步模型不会阻塞线程,它是等资源准备好后,再通知业务代码来完成后续的资源处理逻辑。这种异步设计的方法,可以很好地解决 IO 等待的问题。

我们开发的绝大多数业务系统,它都是 IO 密集型系统。跟 IO 密集型系统相对的另一种系统叫计算密集型系统。通过这两种系统的名字,估计你也能大概猜出来 IO 密集型系统是什么意思。

IO 密集型系统大部分时间都在执行 IO 操作,这个 IO 操作主要包括网络 IO 和磁盘 IO,以及与计算机连接的一些外围设备的访问。与之相对的计算密集型系统,大部分时间都是在使用 CPU 执行计算操作。我们开发的业务系统,很少有非常耗时的计算,更多的是网络收发数据,读写磁盘和数据库这些 IO 操作。这样的系统基本上都是 IO 密集型系统,特别适合使用异步的设计来提升系统性能。

应用程序最常使用的 IO 资源,主要包括磁盘 IO 和网络 IO。由于现在的 SSD 的速度越来越快,对于本地磁盘的读写,异步的意义越来越小。所以,使用异步设计的方法来提升 IO性能,我们更加需要关注的问题是,如何来实现高性能的异步网络传输。

今天,咱们就来聊一聊这个话题。

理想的异步网络框架应该是什么样的?

在我们开发的程序中,如果要实现通过网络来传输数据,需要用到开发语言提供的网络通信类库。大部分语言提供的网络通信基础类库都是同步的。一个 TCP 连接建立后,用户代码会获得一个用于收发数据的通道。每个通道会在内存中开辟两片区域用于收发数据的缓存。

发送数据的过程比较简单,我们直接往这个通道里面来写入数据就可以了。用户代码在发送时写入的数据会暂存在缓存中,然后操作系统会通过网卡,把发送缓存中的数据传输到对端的服务器上。

只要这个缓存不满,或者说,我们发送数据的速度没有超过网卡传输速度的上限,那这个发送数据的操作耗时,只不过是一次内存写入的时间,这个时间是非常快的。所以,发送数据的时候同步发送就可以了,没有必要异步。

比较麻烦的是接收数据。对于数据的接收方来说,它并不知道什么时候会收到数据。那我们能直接想到的方法就是,用一个线程阻塞在那儿等着数据,当有数据到来的时候,操作系统会先把数据写入接收缓存,然后给接收数据的线程发一个通知,线程收到通知后结束等待,开始读取数据。处理完这一批数据后,继续阻塞等待下一批数据到来,这样周而复始地处理收到的数据。

这就是同步网络 IO 的模型。同步网络 IO 模型在处理少量连接的时候,是没有问题的。但是如果要同时处理非常多的连接,同步的网络 IO 模型就有点儿力不从心了。

因为,每个连接都需要阻塞一个线程来等待数据,大量的连接数就会需要相同数量的数据接收线程。当这些 TCP 连接都在进行数据收发的时候,会导致什么情况呢?对,会有大量的线程来抢占 CPU 时间,造成频繁的 CPU 上下文切换,导致 CPU 的负载升高,整个系统的性能就会比较慢。

所以,我们需要使用异步的模型来解决网络 IO 问题。怎么解决呢?

你可以先抛开你知道的各种语言的异步类库和各种异步的网络 IO 框架,想一想,对于业务开发者来说,一个好的异步网络框架,它的 API 应该是什么样的呢?

我们希望达到的效果,无非就是,只用少量的线程就能处理大量的连接,有数据到来的时候能第一时间处理就可以了。

对于开发者来说,最简单的方式就是,事先定义好收到数据后的处理逻辑,把这个处理逻辑作为一个回调方法,在连接建立前就通过框架提供的 API 设置好。当收到数据的时候,由框架自动来执行这个回调方法就好了。

实际上,有没有这么简单的框架呢?

使用Netty来实现异步网络通信

在 Java 中,大名鼎鼎的 Netty 框架的 API 设计就是这样的。接下来我们看一下如何使用Netty 实现异步接收数据。

//创建一组线性
EventLoopGroup group = new NioEventLoopGroup();
try{
	//初始化Server
	ServerBootstrap serverBootstrap = new ServerBootstrap();
	serverBootstrap.group(group);
	serverBootstrap.channel(NioServerSocketChannel.class);
	serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));
	//设置收到数据后的处理的Handler
	serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
		protected void initChannel(SocketChannel socketChannel) throws Exception {
			socketChannel.pipeline().addLast(new MyHandler());
		}
	}
	);
	//绑定端口,开始提供服务
	ChannelFuture channelFuture = serverBootstrap.bind().sync();
	channelFuture.channel().closeFuture().sync();
}
catch(Exception e){
	e.printStackTrace();
}
finally {
	group.shutdownGracefully().sync();
}

这段代码它的功能非常简单,就是在本地 9999 端口,启动了一个 Socket Server 来接收数据。我带你一起来看一下这段代码:

  1. 首先我们创建了一个 EventLoopGroup 对象,命名为 group,这个 group 对象你可以简单把它理解为一组线程。这组线程的作用就是来执行收发数据的业务逻辑。
  2. 然后,使用 Netty 提供的 ServerBootstrap 来初始化一个 Socket Server,绑定到本地 9999 端口上。
  3. 在真正启动服务之前,我们给 serverBootstrap 传入了一个 MyHandler 对象,这个MyHandler 是我们自己来实现的一个类,它需要继承 Netty 提供的一个抽象类:ChannelInboundHandlerAdapter,在这个 MyHandler 里面,我们可以定义收到数据后的处理逻辑。这个设置 Handler 的过程,就是我刚刚讲的,预先来定义回调方法的过程。
  4. 最后就可以真正绑定本地端口,启动 Socket 服务了。

服务启动后,如果有客户端来请求连接,Netty 会自动接受并创建一个 Socket 连接。你可以看到,我们的代码中,并没有像一些同步网络框架中那样,需要用户调用 Accept() 方法来接受创建连接的情况,在 Netty 中,这个过程是自动的。

当收到来自客户端的数据后,Netty 就会在我们第一行提供的 EventLoopGroup 对象中,获取一个 IO 线程,在这个 IO 线程中调用接收数据的回调方法,来执行接收数据的业务逻辑,在这个例子中,就是我们传入的 MyHandler 中的方法。

Netty 本身它是一个全异步的设计,我们上节课刚刚讲过,异步设计会带来额外的复杂度,所以这个例子的代码看起来会比较多,比较复杂。但是你看,其实它提供了一组非常友好API。

真正需要业务代码来实现的就两个部分:一个是把服务初始化并启动起来,还有就是,实现收发消息的业务逻辑 MyHandler。而像线程控制、缓存管理、连接管理这些异步网络 IO中通用的、比较复杂的问题,Netty 已经自动帮你处理好了,有没有感觉很贴心?所以,非常多的开源项目使用 Netty 作为其底层的网络 IO 框架,并不是没有原因的。

在这种设计中,Netty 自己维护一组线程来执行数据收发的业务逻辑。如果说,你的业务需要更灵活的实现,自己来维护收发数据的线程,可以选择更加底层的 Java NIO。其实,Netty 也是基于 NIO 来实现的。

使用NIO来实现异步网络通信

在 Java 的 NIO 中,它提供了一个 Selector 对象,来解决一个线程在多个网络连接上的多路复用问题。什么意思呢?在 NIO 中,每个已经建立好的连接用一个 Channel 对象来表示。我们希望能实现,在一个线程里,接收来自多个 Channel 的数据。也就是说,这些Channel 中,任何一个 Channel 收到数据后,第一时间能在同一个线程里面来处理。

我们可以想一下,一个线程对应多个 Channel,有可能会出现这两种情况:

  1. 线程在忙着处理收到的数据,这时候 Channel 中又收到了新数据;
  2. 线程闲着没事儿干,所有的 Channel 中都没收到数据,也不能确定哪个 Channel 会在什么时候收到数据。

Selecor 通过一种类似于事件的机制来解决这个问题。首先你需要把你的连接,也就是Channel 绑定到 Selector 上,然后你可以在接收数据的线程来调用 Selector.select() 方法来等待数据到来。这个 select 方法是一个阻塞方法,这个线程会一直卡在这儿,直到这些Channel 中的任意一个有数据到来,就会结束等待返回数据。它的返回值是一个迭代器,你可以从这个迭代器里面获取所有 Channel 收到的数据,然后来执行你的数据接收的业务逻辑。

你可以选择直接在这个线程里面来执行接收数据的业务逻辑,也可以将任务分发给其他的线
程来执行,如何选择完全可以由你的代码来控制。

总结

传统的同步网络 IO,一般采用的都是一个线程对应一个 Channel 接收数据,很难支持高并发和高吞吐量。这个时候,我们需要使用异步的网络 IO 框架来解决问题。

然后我们讲了 Netty 和 NIO 这两种异步网络框架的 API 和他们的使用方法。这里面,你需要体会一下这两种框架在 API 设计方面的差异。Netty 自动地解决了线程控制、缓存管理、连接管理这些问题,用户只需要实现对应的 Handler 来处理收到的数据即可。而 NIO是更加底层的 API,它提供了 Selector 机制,用单个线程同时管理多个连接,解决了多路复用这个异步网络通信的核心问题。

C++高性能Web爬虫实战:从libcurl异步下载到Gumbo解析的架构设计 Web爬虫作为自动化数据采集的核心技术,其本质是通过网络协议模拟浏览器行为,从互联网中提取结构化信息。其工作原理通常遵循HTTP/HTTPS协议栈,涉及DNS解析、TCP连接、请求响应处理等底层网络通信。在技术价值层面,高性能爬虫能够实现大规模、高并发的数据抓取,为搜索引擎、市场监控、舆情分析等应用提供实时数据支撑。面对需要7x24小时稳定运行、每秒处理成千上万请求的资源敏感场景,如金融数据监控或对抗严密反爬策略时,传统的解释型语言往往遇到性能瓶颈。此时,基于C++的**异步非阻塞**架构结合**libcu 阅读详情

相关推荐

201、深入理解Clojure高性能编程

本文深入探讨了Clojure高性能编程的各个方面,包括用户界面应用的性能考量、工作负载与资源利用分析、硬件延迟对性能的影响、Clojure的核心理念与抽象、性能优化的关键领域以及实际应用中的性能优化案例。通过具体的技术和工具介绍,如Criterium延迟分析、类型提示、Transients使用等,帮助开发者更好地理解和应用Clojure性能优化技术。

gin88的博客 560

阻塞和非阻塞网络、异步和非异步网络区别点

阻塞和非阻塞主要区别在于是否等待对方响应,而异步和非异步主要区别在于回调操作的方式。在实际的网络编程中,我们需要根据具体的需求选择合适的方式来进行开发,以满足程序的特定需求。

qq_41979948的博客 1345

深入理解分布式技术 - Kafka 高性能原理剖析

文章目录概述磁盘顺序读写批量操作优化Sendfile 零拷贝MMAP 技术小结 概述 Kafka 所实现的高性能不需要太高配置的机器,它使用普通服务器就能实现 TB 级别的传输性能。这一点也是 Kafka 对外宣传的一个特性,也正是因为这一点,Kafka 被广泛运用于大数据处理、流式计算、各类日志监控等需要处理海量数据的场景。 为什么呢? 磁盘顺序读写 Kafka 消息是存储在磁盘上的,众所周知,普通的机械磁盘读取是比较慢的,那 Kafka 文件在磁盘上,如何实现高性能的读写呢? Kafka 对磁盘

小工匠 2万+

网络传输的异步、同步传输的实现原理

异步传输和同步传输

m0_57679698的博客 4948

全面理解异步IO模型——从并发到异步——进击的Java程序员

作者:禅与计算机程序设计艺术 1.简介 一、引言 在计算机科学中,多线程或称为并发编程,是指允许多个任务(线程)同时执行的代码编写方式。但在实际项目开发中,由于系统资源有限等因素的限制,多线程往往不够高效,所以需要通过异步IO模型来提升程序运行效率。本文将介绍一下异

AI天才研究院 1923

基于Redis与ServiceStack.NET的高性能缓存优化方案

简单说,就是把一堆命令打包一次性发过去,Redis按顺序执行完后再把所有结果一起返回。原来是一问一答:Server: OKServer: OK...现在变成:数学模型上看:串行耗时 ≈ N × RTTPipeline耗时 ≈ RTT + Σ(执行时间)当N很大时,性能提升接近N倍!来看一组真实测试数据(局域网环境):并发数单条延迟(ms)Pipeline总延迟(ms)吞吐提升倍数1000.82.1~38x。

weixin_42146230的博客 1034

异步网络模型

转载自:http://tech.youzan.com/yi-bu-wang-luo-mo-xing/ 异步网络模型 异步网络模型在服务开发中应用非常广泛,相关资料和开源库也非常多。项目中,使用现成的轮子提高了开发效率,除了能使用轮子,还是有必要了解一下轮子的内部构造。 这篇文章从最基础的5种I/O模型切入,到I/O事件处理模型,再到并发模式,最后以Swoole开源库来做具体分析,逐步深入

哲 5618

解决 Clawdbot 对接 Minimax 出现 401 (Token is unusable) 的问题排查与修复

即便确认 API Key 有效且余额充足,该问题仍可能在 Clawdbot 中持续出现,而在其他工具(如 curl 或 Postman)中测试正常。

hampeter的博客 3075

数据交互的消息队列:实现异步数据传输和解耦

1.背景介绍 在现代的大数据时代,数据交互和数据处理已经成为企业和组织中不可或缺的一部分。随着数据量的增加,传统的同步数据处理方式已经无法满足业务需求。因此,异步数据传输和解耦成为了一种新的解决方案。这篇文章将深入探讨异步数据传输和解耦的核心概念、算法原理、具体实现以及未来发展趋势。 2.核心概念与联系 2.1 异步数据传输 异步数据传输是指在不同系统之间,数据不需要立即得到响应,而是可以...

AI天才研究院 933

BUPT软件安全实验三

可以看出栈溢出对程序运行的安全性有很大的威胁,如果不对栈进行保护,只要系统中存在栈溢出漏洞,即可令攻击者通过非正当方法获取操作权限。(6)解决思考题,即:在不修改StackOverrun程序源代码的情况下,构造shellcode,通过JMP ESP的方式实现通过记事本打开shellcode.txt(可使用CreateProcessA或WinExec等API)。查看缓冲区信息,可以看到dest指向地址0x0012FAF0,其为数组的存放起始位置,也就是shellcode注入的起始位置。

7xun's space 1966

ESP32 Arduino学习篇 (一) 引脚和串口的基本使用

简单来讲arduino就是通过源代码控制开发板的信号输入输出从而实现对一些电子元件的控制,例如LED灯,蜂鸣器,按键arduino程序首先来讲arduino程序是基于C语言,而实现类似对于LED灯和蜂鸣器的简单控制只需简单C语言知识即可实现。arduino程序是基于函数的,而在arduino的库有很多函数,我们只需要调用即可。arduino的程序主体是**setup()函数和loop()**函数以及其它在使用过程中需要构建的函数:setup()函数。

DOF526570的博客 1万+

异步访问 不接收_深入理解消息队列:如何实现高性能的异步网络传输?

推荐阅读:一线大厂为什么面试必问分布式?在一次又一次的失败中,我总结了这份万字的《MySQL性能调优笔记》并发编程详解:十三个工具类,十大设计模式,从理论基础到案例实战异步与同步模型最大的区别是,同步模型会阻塞线程等待资源,而异步模型不会阻塞线程,它是等资源准备好后,再通知业务代码来完成后续的资源处理逻辑。这种异步设计的方法,可以很好地解决 IO 等待的问题。我们开发的绝大多数业务系统,它都是 I...

weixin_39963440的博客 107

QGIS:安装Deepness插件+应用

简单的描述了deepness的安装应用历程,重点是记录博主本次遇到的坑

fengyi157的博客 2336

java高性能异步消息_深入理解消息队列:如何实现高性能的异步网络传输?

异步与同步模型最大的区别是,同步模型会阻塞线程等待资源,而异步模型不会阻塞线程,它是等资源准备好后,再通知业务代码来完成后续的资源处理逻辑。这种异步设计的方法,可以很好地解决 IO 等待的问题。我们开发的绝大多数业务系统,它都是 IO 密集型系统。跟 IO 密集型系统相对的另一种系统叫计算密集型系统。通过这两种系统的名字,估计你也能大概猜出来 IO 密集型系统是什么意思。IO 密集型系统大部分时间...

weixin_32637683的博客 226

图片边界矢量化-地理配准

无地理和投影信息的JPG图片,通过ArcGIS进行地理配准(Georeferencing)完成数字化边界。

u012727861的博客 1907

Obsidian与RAG:知识管理的未来之战

摘要: 本文对比了传统RAG、Obsidian和llm-wiki-skill三种知识管理方案。传统RAG依赖查询时临时检索,知识无法积累;Obsidian需人工整理,成本高但结构化强;llm-wiki-skill通过AI在摄入时自动编译知识为结构化Wiki,实现持续增值。核心差异在于知识处理时机——llm-wiki-skill将"查询时检索"转变为"摄入时编译",通过三层Markdown结构(sources/concepts/entities)和自动双向链接构建可进化

ZhangJiqun&191cm&85kg 620

深入理解NNG轻量级消息库的核心架构与实现原理

NNG(nanomsg-next-generation)作为下一代轻量级无代理消息库,在分布式系统通信领域展现出卓越的性能表现和技术优势。本教程将带领读者深入探索NNG的内部架构设计,从核心组件到扩展机制,全面解析这一高效通信解决方案的实现细节。 ## 🔍 NNG架构设计哲学与核心思想 NNG的设计遵循"简单即美"的工程理念,通过模块化的架构设计实现了功能强大而代码简洁的完美平衡。其核心设计

gitblog_00446的博客 1119

把核心变干净的代价与回报:为什么推动 Clean Core,几乎绕不开 SAP Integration Suite 与 API Management

Clean Core的核心价值在于构建可持续升级的ERP系统架构,其关键不在于减少代码或限制扩展,而是通过解耦和治理实现系统边界的清晰划分。这一理念将推动企业从传统的"私搭乱建"式集成向平台化工程转型,而SAP Integration Suite和API Management正是实现这一转型的核心组件。 Integration Suite作为集成中枢,通过统一平台、可复用内容库和事件驱动架构,将碎片化连接转变为标准化能力;API Management则负责建立接口治理体系,通过统一入口、

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 243

深入理解三高架构:高可用性、高性能、高扩展性的最佳实践

在现代互联网环境下,随着用户规模和业务需求的快速增长,系统架构的设计变得尤为重要。为了确保系统能够在高负载和复杂场景下稳定运行,"三高架构"(高可用性、高性能、高扩展性)成为技术架构设计中的核心理念。 本篇技术博客将详细解析三高架构的概念、特点及实现方法,结合实际案例,帮助读者深入理解这一重要架构设计思路。

fudaihb的博客 1942

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Spring Boot 集成 ActiveMQ 实现异步消息通信(一)

简化配置流程、消息转换器(MessageConverter)的使用、生产环境中的最佳实践。

1165

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Chain33网络层架构:P2P网络与消息队列的通信机制

Chain33作为高度模块化、遵循KISS原则的区块链开发框架,其网络层架构是确保节点间高效通信的核心。本文将深入解析Chain33的P2P网络与消息队列通信机制,帮助开发者快速理解框架的网络交互原理。 ## P2P网络模块:节点发现与连接管理 Chain33的P2P网络模块位于[p2p/](https://link.gitcode.com/i/e9d9a08eb7eee1ed466b8a69

gitblog_00761的博客 983

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

3个角度11个技术点剖析Kafka高性能背后的原理

Kafka 是一款性能非常优秀的消息队列,每秒处理的消息体量可以达到千万级别。 今天来聊一聊 Kafka 高性能背后的技术原理,接下来从生产消息、存储消息、消费消息 3 个角度11个技术点进行剖析。

1105

NNG源码架构解析:深入理解轻量级消息传递库的实现原理

🚀 NNG(nanomsg-next-generation)是一个革命性的轻量级消息传递库,它继承了nanomsg的设计理念,同时在性能、可靠性和安全性方面进行了全面优化。作为一款无代理(brokerless)的消息传递解决方案,NNG为开发者提供了简单易用的API来解决常见的消息传递问题,如发布/订阅、RPC风格的请求/回复或服务发现。 ## 🏗️ NNG核心架构概览 NNG的源码架构设

gitblog_00630的博客 596

深入理解nodejs-websocket原理:从协议解析到性能优化

nodejs-websocket是一个轻量级的Node.js模块,专为WebSocket服务器和客户端实现而设计。它提供了简单易用的API,让开发者能够快速构建实时通信应用。本文将从WebSocket协议解析入手,深入探讨nodejs-websocket的内部工作原理,并分享实用的性能优化技巧,帮助你构建高效稳定的实时应用。 ## 📋 WebSocket协议基础:从握手到数据传输 WebSo

gitblog_01065的博客 1057
上一篇: 如何学习源码?阿里架构师教你一招攻破源码难关
下一篇: Java技术面试到底要准备哪些面试题?别找了,这个GitHub完美的帮你解决
Java_Cappuccino
博客等级 码龄7年 17粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值