消息队列高手课
李玥
京东零售技术架构部资深架构师
立即订阅
8426 人已学习
课程目录
已完结 41 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 优秀的程序员,你的技术栈中不能只有“增删改查”
免费
预习 | 怎样更好地学习这门课?
基础篇 (8讲)
01 | 为什么需要消息队列?
02 | 该如何选择消息队列?
03 | 消息模型:主题和队列有什么区别?
04 | 如何利用事务消息实现分布式事务?
05 | 如何确保消息不会丢失?
06 | 如何处理消费过程中的重复消息?
07 | 消息积压了该如何处理?
08 | 答疑解惑(一) : 网关如何接收服务端的秒杀结果?
进阶篇 (21讲)
09 | 学习开源代码该如何入手?
10 | 如何使用异步设计提升系统性能?
11 | 如何实现高性能的异步网络传输?
12 | 序列化与反序列化:如何通过网络传输结构化的数据?
13 | 传输协议:应用程序之间对话的语言
14 | 内存管理:如何避免内存溢出和频繁的垃圾回收?
加餐 | JMQ的Broker是如何异步处理消息的?
15 | Kafka如何实现高性能IO?
16 | 缓存策略:如何使用缓存来减少磁盘IO?
17 | 如何正确使用锁保护共享数据,协调异步线程?
18 | 如何用硬件同步原语(CAS)替代锁?
19 | 数据压缩:时间换空间的游戏
20 | RocketMQ Producer源码分析:消息生产的实现过程
21 | Kafka Consumer源码分析:消息消费的实现过程
22 | Kafka和RocketMQ的消息复制实现的差异点在哪?
23 | RocketMQ客户端如何在集群中找到正确的节点?
24 | Kafka的协调服务ZooKeeper:实现分布式系统的“瑞士军刀”
25 | RocketMQ与Kafka中如何实现事务?
26 | MQTT协议:如何支持海量的在线IoT设备?
27 | Pulsar的存储计算分离设计:全新的消息队列设计思路
28 | 答疑解惑(二):我的100元哪儿去了?
案例篇 (7讲)
29 | 流计算与消息(一):通过Flink理解流计算的原理
30 | 流计算与消息(二):在流计算中使用Kafka链接计算任务
31 | 动手实现一个简单的RPC框架(一):原理和程序的结构
32 | 动手实现一个简单的RPC框架(二):通信与序列化
33 | 动手实现一个简单的RPC框架(三):客户端
34 | 动手实现一个简单的RPC框架(四):服务端
35 | 答疑解惑(三):主流消息队列都是如何存储消息的?
测试篇 (2讲)
期中测试丨10个消息队列热点问题自测
免费
期末测试 | 消息队列100分试卷等你来挑战!
结束语 (1讲)
结束语 | 程序员如何构建知识体系?
消息队列高手课
登录|注册

11 | 如何实现高性能的异步网络传输?

李玥 2019-08-15
你好,我是李玥。上一节课我们学习了异步的线程模型,异步与同步模型最大的区别是,同步模型会阻塞线程等待资源,而异步模型不会阻塞线程,它是等资源准备好后,再通知业务代码来完成后续的资源处理逻辑。这种异步设计的方法,可以很好地解决 IO 等待的问题。
我们开发的绝大多数业务系统,都是 IO 密集型系统。跟 IO 密集型系统相对的另一种系统叫计算密集型系统。通过这两种系统的名字,估计你也能大概猜出来 IO 密集型系统是什么意思。
IO 密集型系统大部分时间都在执行 IO 操作,这个 IO 操作主要包括网络 IO 和磁盘 IO,以及与计算机连接的一些外围设备的访问。与之相对的计算密集型系统,大部分时间都是在使用 CPU 执行计算操作。我们开发的业务系统,很少有非常耗时的计算,更多的是网络收发数据,读写磁盘和数据库这些 IO 操作。这样的系统基本上都是 IO 密集型系统,特别适合使用异步的设计来提升系统性能。
应用程序最常使用的 IO 资源,主要包括磁盘 IO 和网络 IO。由于现在的 SSD 的速度越来越快,对于本地磁盘的读写,异步的意义越来越小。所以,使用异步设计的方法来提升 IO 性能,我们更加需要关注的问题是,如何来实现高性能的异步网络传输。
今天,咱们就来聊一聊这个话题。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《消息队列高手课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(25)

  • 游弋云端
    关于JAVA的网络,之前有个比喻形式的总结,分享给大家:
    例子:有一个养鸡的农场,里面养着来自各个农户(Thread)的鸡(Socket),每家农户都在农场中建立了自己的鸡舍(SocketChannel)
    1、BIO:Block IO,每个农户盯着自己的鸡舍,一旦有鸡下蛋,就去做捡蛋处理;
    2、NIO:No-Block IO-单Selector,农户们花钱请了一个饲养员(Selector),并告诉饲养员(register)如果哪家的鸡有任何情况(下蛋)均要向这家农户报告(select keys);
    3、NIO:No-Block IO-多Selector,当农场中的鸡舍逐渐增多时,一个饲养员巡视(轮询)一次所需时间就会不断地加长,这样农户知道自己家的鸡有下蛋的情况就会发生较大的延迟。怎么解决呢?没错,多请几个饲养员(多Selector),每个饲养员分配管理鸡舍,这样就可以减轻一个饲养员的工作量,同时农户们可以更快的知晓自己家的鸡是否下蛋了;
    4、Epoll模式:如果采用Epoll方式,农场问题应该如何改进呢?其实就是饲养员不需要再巡视鸡舍,而是听到哪间鸡舍的鸡打鸣了(活跃连接),就知道哪家农户的鸡下蛋了;
    5、AIO:Asynchronous I/O, 鸡下蛋后,以前的NIO方式要求饲养员通知农户去取蛋,AIO模式出现以后,事情变得更加简单了,取蛋工作由饲养员自己负责,然后取完后,直接通知农户来拿即可,而不需要农户自己到鸡舍去取蛋。

    作者回复: 这个比喻非常赞👍

    2019-08-15
    3
    75
  • 业余草
    多回到队列上来吧。Netty几乎很多Java课都会讲到。。。

    作者回复: 我们还是需要一个例子能让大家理解异步网络传输的。

    2019-08-15
    19
  • 芥末小龙
    玥哥秋安:我今天看了这个课程我觉得就有同学要说,老师你是不是跑题了,首先我要说一下为什么要说今天这讲课,并且用netty来举栗子。
    第一:了解一下异步网络传输的原理
    第二:用Netty来举栗子是因为Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
    第三:rocketMQ的底层就是用Netty实现的。
    第四:可以看一下第9节课如果学习开源代码,然后在看一下rocketMQ的源码。然后根据MQ的Producer,Consumer,Broker,NameSrv等的底层实现是不是理解了玥哥的良苦用心。
    个人见解勿喷!
    2019-08-16
    12
  • godtrue
    课后思考及建议
    没有对比就没有伤害,尤其对于学习,对比一下就知道那个课程优秀,那个更优秀。

    首先,我觉得如何实现高性能的网络通信,是必须要讲的,这个原理是脱离具体语言的,和什么实现框架也没什么关系。
    不过篇幅有限老师只能讲解一下她的精髓,如果想一点点弄明白,建议看看李林峰大哥的《netty权威指南(第二版)》她用了三章来讲解网络通信模型的演进。
    另外,我同时在学kafka的专栏,我发现一个现象,两位老师都没有先将一个消息的全生命历程先细致的讲一下,学习过丁奇老师的MySQL,他上来就讲解了一下一个SQL语句是怎么执行的。我觉得很有整体感,知道整个过程之后其实下面再细致的讲解都是性能优化的事情啦!
    我猜想其他各种系统,尤其是和数据打交道的都类似,只要一个完整的流程知道了,下面好多知识都是在为这个系统的性能、健壮性、高可用性、自身的其他特性在加强。
    所以,我提过这样的问题,也建议先讲一下一条消息从发送到接收都经历了那些关键环节或组件,对一条消息的全生命历程有个整体的认识。然后再讲每个关键环节为什么这么实现,其性能最佳吞吐量最高。然后再讲各个组件是怎么紧密配合的,如果我知道一个软件是什么?又清楚他由什么组成?每一部分为什么如此设计?那些设计是通用的那些设计比较独特?我觉得我就理解了这个软件
    老师的课程非常优秀,哈哈,我觉得听了我的建议还可以再优秀一点点

    作者回复: 感谢你的建议!

    2019-08-23
    2
    7
  • linqw
    学习完高性能网络传输,写下自己的理解和疑惑,老师有空帮忙看下哦
    Netty服务端会存在两个线程池NioEventLoopGroup,一个线程池主要用来处理客户端的连接,一般设置单线程NioEventLoop,在Linux中可能是EpollEventLoop,要是服务端监控多个端口可以设置多个线程,服务端接收到客户端的连接会创建Channel通道,Channel通道中会有收发缓存,服务端会定时监控Channel通道是否已经断开,在一定时间没有收到客户端的心跳包,把客户端的Channel从服务端移除,还可以设置服务端接收连接的队列,还有一个处理线程池NioEventLoopGroup,里面会有多个线程NioEventLoop,然后每个NioEventLoop都会有一个Selector,然后可以多个channel绑定到NioEventLoop的Selector中,即一个Channel只能被一个NioEventLoop处理,一个NioEventLoop可以处理多个Channel,即收到Channel数据,NioEventLoop执行Handler,包括解码、拆包等Handler,服务端返回响应消息对Channel进行编码等Handler。
    尝试回答下课后习题接收数据这个流程Netty是一个NioEventLoop会有一个Selector,原先的Nio是只有一个Selector进行处理所有的连接收发事件,这样的话比如NioEventLoopGroup中有10个NioEventLoop,这样的话就有10个Selector,比如有10000读写请求,每个Selector就可以维持1000
    2019-08-15
    4
  • xhrg
    1 本文按理说应该讲的是消息队列中网络的使用,但是实际作者讲的是java的网络基础编程和netty的入门介绍。

    2 实际的网络传输,比如rocketmq在发送端也是异步的,而不是同步。

    3 对于java的BIO,NIO,包括netty的入门demo,网上文章很多。如何在消息队列的中间件开发中,能高效使用netty,或者说NIO,也不是一件容易的事。
    2019-08-15
    1
    3
  • leslie
    Java基础太差:几乎不懂;故而其实本课程学习让我觉得越多Java相关的非常吃力,希望老师后面的课程里面纯Java的东西能浅一点或者告知Java的理解大概要什么水平。
    刘超老师的趣谈linux在跟着学、张磊的深入剖析Kubernetes目前学了一遍。我想从用这种方式去理解或解释不知道原理是否类似正确吧:希望老师提点或者下堂课时解答。
    其实Netty基于NIO就像Kubernetes其实是基于Cgroup和Namespace一样:其实Netty是使用了NIO的Selecor去处理线程的异步机制,Netty在它的基础上去优化了其线程控制和连接管理并追加了缓存管理,请老师指正;谢谢。
    努力跟着学习,努力跟着做题;希望完课的时候能从另外一个高度/层次去理解和使用消息队列。

    作者回复: 放心,我们这门课使用的任何语言都不会特别深入,更多的是讲实现原理,语言只是讲解和举例的载体。

    2019-08-15
    3
  • 川杰
    老师,以下是我的理解:异步网络框架中,通过线程池处理接收消息的情况,和同步相比,好处在于,同步框架下,一个连接必须有两个线程(等数据的线程、处理数据的线程),当连接过多时会有大量频繁的上下文切换;而异步框架利用线程池接管了(等数据的线程)的作用,减少了上下文切换、线程的创建销毁的开销;
    问题是:虽然线程池完成了数据接收的功能,但加入消息发送方发来了大量的消息,因为线程池的线程数量毕竟是有限的,此时是否就会出现消息不能及时转发给数据处理线程的情况呢?

    作者回复: 你说的这个问题是有可能出现的。

    2019-08-15
    1
  • 一步
    希望老师多讲讲MQ 相关的,不要深入某一个语言某一个类库或者框架进行讲解的,有的同学语言不熟悉,代码也看不懂的,某一个类库或者框架实现的细节也不知道的

    作者回复: 我们这节课和接下来的几节课讲的都是实现消息队列必须的一些技术,同学应该重点来理解我们讲解的原理,但是要真正掌握这些原理,还是需要依托与某一个语言或者框架来实际操作一下的。

    2019-08-15
    1
  • 不似旧日
    有点枯燥,有点难.
    2019-11-27
  • 不似旧日
    不行, 不太适合我有点高深了, 我先缓缓以后学
    2019-11-22
  • 达文西
    关于同步/异步,阻塞/非阻塞的定义,可以参考这篇博客https://www.cnblogs.com/dolphin0520/p/3916526.html
    2019-10-10
  • 长期规划
    讲的非常好,Nginx的能支撑高并发,也是多路复用,底层原理一样,因为都依赖OS的seIect,epoⅠⅠ
    2019-09-23
  • go...go
    听过音频后,有所感悟整理如下:
    同步模式下: 多个连接对应多个线程。连接存活不活跃的情况下,线程始终处于等待资源的状态。 存在线程资源浪费/占用内存的情况。当同时存在多个活跃连接时,连接越多线程越多,线程线上下文切换越频繁,从而产生其他开销。
    异步模式下:多个连接对应单个或少量线程。连接不活跃的时候,只有少部分线程处于等待资源的状态。资源浪费和内存占用较少。当同时存在多个活跃连接的时候,将写入动作以事件的方式发送给相应的处理组件。处理组件的线程数量可控,在满足业务需要的情况下,线程上下文切换相对减少。
    两种模式在少量连接请求的情况下,处理效果差不多。但随着请求的增多,同步模式会更早的达到性能瓶颈。
    2019-09-14
  • 杰哥长得帅
    同步的时候,每个连接都需要阻塞一个线程来等待数据,大量的连接数就会需要相同数量的数据接收线程。当这些 TCP 连接都在进行数据收发的时候,会导致什么情况呢?对,会有大量的线程来抢占 CPU 时间,造成频繁的 CPU 上下文切换,导致 CPU 的负载升高,整个系统的性能就会比较慢。

    老师能详细解释下 “大量线程用于数据接收时,为什么又会有大量线程来抢占cpu时间” 吗

    作者回复: 因为接收数据这些操作都需要cpu来执行。接收数据的这个操作,实际上就是把数据从socket 缓冲区复制到用户程序的内存空间,然后执行用户代码去解析数据等其他业务逻辑,这些操作都需要CPU来执行。

    2019-09-02
  • 秋风画扇
    IO阻塞线程导致load升高吧,不是cpu
    2019-08-28
  • 凌霄
    jsf中netty使用一个线程组boss线程(一个端口一个boss线程)专门处理accept,使用一个线程组work专门处理io,work线程再调用业务线程。
    2019-08-22
  • 奎因
    我是 Python 开发者,基于 Python 内置的 low level api 中的异步 io 对象编写了一个异步的 websocket

    作者回复: 方便的话可以给大家分享一下代码哟

    2019-08-19
  • Colin
    我觉得这一章完全可以带过
    2019-08-18
  • 来碗绿豆汤
    今天坐了8个小时火车,正好把课程看一遍。老师课程写的非常好,一口气读完毫无枯燥敢。回答一下今天的问题:同一个数据在不同操作系统中的表示形式不同,可能导致程序无法被读出;内存里面的数据还会包含很多对象引用,类应用,这些存的都是内存地址,当你再次加载到内存时,这些引用都是失效的。
    2019-08-17
收起评论
25
返回
顶部