Jack Jiang

我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
posts - 467, comments - 13, trackbacks - 0, articles - 0

     摘要: 本文原题“程序员应如何理解高并发中的协程”,转载请联系作者。1、系列文章引言1.1 文章目的作为即时通讯技术的开发者来说,高性能、高并发相关的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或许你对具有这些技术特征的技术框架比如:Java的Netty、Php的workman、Go的gnet等熟练掌握。但真正到了面视或者技术实践过程...  阅读全文

posted @ 2021-01-18 14:51 Jack Jiang 阅读(175) | 评论 (0)编辑 收藏

     摘要: 本文原题“从小白到高手,你需要理解同步与异步”,转载请联系作者。1、系列文章引言1.1 文章目的作为即时通讯技术的开发者来说,高性能、高并发相关的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或许你对具有这些技术特征的技术框架比如:Java的Netty、Php的workman、Go的gnet等熟练掌握。但真正到了面视或者技术实践...  阅读全文

posted @ 2021-01-12 14:15 Jack Jiang 阅读(195) | 评论 (0)编辑 收藏

本文原题“终于明白了,一文彻底理解I/O多路复用”,转载请联系作者。

1、系列文章引言

1.1 文章目的

作为即时通讯技术的开发者来说,高性能、高并发相关的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或许你对具有这些技术特征的技术框架比如:Java的Netty、Php的workman、Go的nget等熟练掌握。但真正到了面视或者技术实践过程中遇到无法释怀的疑惑时,方知自已所掌握的不过是皮毛。

返璞归真、回归本质,这些技术特征背后的底层原理到底是什么?如何能通俗易懂、毫不费力真正透彻理解这些技术背后的原理,正是《从根上理解高性能、高并发》系列文章所要分享的。

1.2 文章源起

我整理了相当多有关IM、消息推送等即时通讯技术相关的资源和文章,从最开始的开源IM框架MobileIMSDK,到网络编程经典巨著《TCP/IP详解》的在线版本,再到IM开发纲领性文章《新手入门一篇就够:从零开发移动端IM》,以及网络编程由浅到深的《网络编程懒人入门》、《脑残式网络编程入门》、《高性能网络编程》、《不为人知的网络编程》系列文章。

越往知识的深处走,越觉得对即时通讯技术了解的太少。于是后来,为了让开发者门更好地从基础电信技术的角度理解网络(尤其移动网络)特性,我跨专业收集整理了《IM开发者的零基础通信技术入门》系列高阶文章。这系列文章已然是普通即时通讯开发者的网络通信技术知识边界,加上之前这些网络编程资料,解决网络通信方面的知识盲点基本够用了。

对于即时通讯IM这种系统的开发来说,网络通信知识确实非常重要,但回归到技术本质,实现网络通信本身的这些技术特征:包括上面提到的线程池、零拷贝、多路复用、事件驱动等等,它们的本质是什么?底层原理又是怎样?这就是整理本系列文章的目的,希望对你有用。

1.3 文章目录

从根上理解高性能、高并发(一):深入计算机底层,理解线程与线程池

从根上理解高性能、高并发(二):深入操作系统,理解I/O与零拷贝技术

从根上理解高性能、高并发(三):深入操作系统,彻底理解I/O多路复用》(* 本文

《从根上理解高性能、高并发(四):深入操作系统,彻底理解同步与异步 (稍后发布..)》

《从根上理解高性能、高并发(五):高并发高性能服务器到底是如何实现的 (稍后发布..)》

1.4 本篇概述

接上篇《深入操作系统,理解I/O与零拷贝技术》,本篇是高性能、高并发系列的第3篇文章,上篇里我们讲到了I/O技术,本篇将以更具象的文件这个话题入手,带你一步步理解高性能、高并发服务端编程时无法回避的I/O多路复用及相关技术。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注。公众号上的链接是:点此进入

2、本文作者

应作者要求,不提供真名,也不提供个人照片。

本文作者主要技术方向为互联网后端、高并发高性能服务器、检索引擎技术,网名是“码农的荒岛求生”,公众号“码农的荒岛求生”。感谢作者的无私分享。

3、什么是文件?

在正式展开本文的内容之前,我们需要先预习一下文件以及文件描述符的概念。

程序员使用I/O最终都逃不过文件这个概念。

在Linux世界中文件是一个很简单的概念,作为程序员我们只需要将其理解为一个N byte的序列就可以了:

b1, b2, b3, b4, ....... bN

实际上所有的I/O设备都被抽象为了文件这个概念,一切皆文件(Everything is File),磁盘、网络数据、终端,甚至进程间通信工具管道pipe等都被当做文件对待。

所有的I/O操作也都可以通过文件读写来实现,这一非常优雅的抽象可以让程序员使用一套接口就能对所有外设I/O操作。

常用的I/O操作接口一般有以下几类:

  • 1)打开文件,open;
  • 2)改变读写位置,seek;
  • 3)文件读写,read、write;
  • 4)关闭文件,close。

程序员通过这几个接口几乎可以实现所有I/O操作,这就是文件这个概念的强大之处。

4、什么是文件描述符?

在上一篇《深入操作系统,理解I/O与零拷贝技术》中我们讲到:要想进行I/O读操作,像磁盘数据,我们需要指定一个buff用来装入数据。

一般都是这样写的:

read(buff);

但是这里我们忽略了一个关键问题:那就是,虽然我们指定了往哪里写数据,但是我们该从哪里读数据呢?

从上一节中我们知道,通过文件这个概念我们能实现几乎所有I/O操作,因此这里少的一个主角就是文件。

那么我们一般都怎样使用文件呢?

举个例子:如果周末你去比较火的餐厅吃饭应该会有体会,一般周末人气高的餐厅都会排队,然后服务员会给你一个排队序号,通过这个序号服务员就能找到你,这里的好处就是服务员无需记住你是谁、你的名字是什么、来自哪里、喜好是什么、是不是保护环境爱护小动物等等,这里的关键点就是:服务员对你一无所知,但依然可以通过一个号码就能找到你。

同样的:在Linux世界要想使用文件,我们也需要借助一个号码,根据“弄不懂原则”,这个号码就被称为了文件描述符(file descriptors),在Linux世界中鼎鼎大名,其道理和上面那个排队号码一样。

因此:文件描述仅仅就是一个数字而已,但是通过这个数字我们可以操作一个打开的文件,这一点要记住。

有了文件描述符,进程可以对文件一无所知,比如文件在磁盘的什么位置、加载到内存中又是怎样管理的等等,这些信息统统交由操作系统打理,进程无需关心,操作系统只需要给进程一个文件描述符就足够了。

因此我们来完善上述程序:

int fd = open(file_name); // 获取文件描述符

read(fd, buff);

怎么样,是不是非常简单。

5、文件描述符太多了怎么办?

经过了这么多的铺垫,终于要到高性能、高并发这一主题了。

从前几节我们知道,所有I/O操作都可以通过文件样的概念来进行,这当然包括网络通信。

如果你有一个IM服务器,当三次握手建议长连接成功以后,我们会调用accept来获取一个链接,调用该函数我们同样会得到一个文件描述符,通过这个文件描述符就可以处理客户端发送的聊天消息并且把消息转发给接收者。

也就是说,通过这个描述符我们就可以和客户端进行通信了:

// 通过accept获取客户端的文件描述符

int conn_fd = accept(...);

Server端的处理逻辑通常是接收客户端消息数据,然后执行转发(给接收者)逻辑:

if(read(conn_fd, msg_buff) > 0) {

do_transfer(msg_buff);

}

是不是非常简单,然而世界终归是复杂的,当然也不是这么简单的。

接下来就是比较复杂的了。

既然我们的主题是高并发,那么Server端就不可能只和一个客户端通信,而是可能会同时和成千上万个客户端进行通信。这时你需要处理不再是一个描述符这么简单,而是有可能要处理成千上万个描述符。

为了不让问题一上来就过于复杂,我们先简单化,假设只同时处理两个客户端的请求。

有的同学可能会说,这还不简单,这样写不就行了:

if(read(socket_fd1, buff) > 0) { // 处理第一个

do_transfer();

}

if(read(socket_fd2, buff) > 0) { // 处理第二个

do_transfer();

在上一篇《深入操作系统,理解I/O与零拷贝技术》中我们讨论过,这是非常典型的阻塞式I/O,如果此时没有数据可读那么进程会被阻塞而暂停运行。这时我们就无法处理第二个请求了,即使第二个请求的数据已经就位,这也就意味着处理某一个客户端时由于进程被阻塞导致剩下的所有其它客户端必须等待,在同时处理几万客户端的server上。这显然是不能容忍的。

聪明的你一定会想到使用多线程:为每个客户端请求开启一个线程,这样一个客户端被阻塞就不会影响到处理其它客户端的线程了。注意:既然是高并发,那么我们要为成千上万个请求开启成千上万个线程吗,大量创建销毁线程会严重影响系统性能。

那么这个问题该怎么解决呢?

这里的关键点在于:我们事先并不知道一个文件描述对应的I/O设备是否是可读的、是否是可写的,在外设的不可读或不可写的状态下进行I/O只会导致进程阻塞被暂停运行。

因此要优雅的解决这个问题,就要从其它角度来思考这个问题了。

6、“不要打电话给我,有需要我会打给你”

大家生活中肯定会接到过推销电话,而且不止一个,一天下来接上十个八个推销电话你的身体会被掏空的。

这个场景的关键点在于:打电话的人并不知道你是不是要买东西,只能来一遍遍问你。因此一种更好的策略是不要让他们打电话给你,记下他们的电话,有需要的话打给他们,这样推销员就不会一遍一遍的来烦你了(虽然现实生活中这并不可能)。

在这个例子中:你,就好比内核,推销者就好比应用程序,电话号码就好比文件描述符,和你用电话沟通就好比I/O。

现在你应该明白了吧,处理多个文件描述符的更好方法其实就存在于推销电话中。

因此相比上一节中:我们通过I/O接口主动问内核这些文件描述符对应的外设是不是已经就绪了,一种更好的方法是,我们把这些感兴趣的文件描述符一股脑扔给内核,并霸气的告诉内核:“我这里有1万个文件描述符,你替我监视着它们,有可以读写的文件描述符时你就告诉我,我好处理”。而不是弱弱的问内核:“第一个文件描述可以读写了吗?第二个文件描述符可以读写吗?第三个文件描述符可以读写了吗?。。。”

这样:应用程序就从“繁忙”的主动变为了清闲的被动,反正文件描述可读可写了内核会通知我,能偷懒我才不要那么勤奋。

这是一种更加高效的I/O处理机制,现在我们可以一次处理多路I/O了,为这种机制起一个名字吧,就叫I/O多路复用吧,这就是 I/O multiplexing。

7、I/O多路复用(I/O multiplexing)

multiplexing一词其实多用于通信领域,为了充分利用通信线路,希望在一个信道中传输多路信号,要想在一个信道中传输多路信号就需要把这多路信号结合为一路,将多路信号组合成一个信号的设备被称为Multiplexer(多路复用器),显然接收方接收到这一路组合后的信号后要恢复原先的多路信号,这个设备被称为Demultiplexer(多路分用器)。

如下图所示:

回到我们的主题。

所谓I/O多路复用指的是这样一个过程:

  • 1)我们拿到了一堆文件描述符(不管是网络相关的、还是磁盘文件相关等等,任何文件描述符都可以);
  • 2)通过调用某个函数告诉内核:“这个函数你先不要返回,你替我监视着这些描述符,当这堆文件描述符中有可以进行I/O读写操作的时候你再返回”;
  • 3)当调用的这个函数返回后我们就能知道哪些文件描述符可以进行I/O操作了。

也就是说通过I/O多路复用我们可以同时处理多路I/O。那么有哪些函数可以用来进行I/O多路复用呢?

以Linux为例,有这样三种机制可以用来进行I/O多路复用:

  • 1)select;
  • 2)poll;
  • 3)epoll。

接下来我们就来介绍一下牛掰的I/O多路复用三剑客。

8、I/O多路复用三剑客

本质上:Linux上的select、poll、epoll都是阻塞式I/O,也就是我们常说的同步I/O。

原因在于:调用这些I/O多路复用函数时如果任何一个需要监视的文件描述符都不可读或者可写那么进程会被阻塞暂停执行,直到有文件描述符可读或者可写才继续运行。

8.1 select:初出茅庐

在select这种I/O多路复用机制下,我们需要把想监控的文件描述集合通过函数参数的形式告诉select,然后select会将这些文件描述符集合拷贝到内核中。

我们知道数据拷贝是有性能损耗的,因此为了减少这种数据拷贝带来的性能损耗,Linux内核对集合的大小做了限制,并规定用户监控的文件描述集合不能超过1024个,同时当select返回后我们仅仅能知道有些文件描述符可以读写了,但是我们不知道是哪一个。因此程序员必须再遍历一边找到具体是哪个文件描述符可以读写了。

因此,总结下来select有这样几个特点:

  • 1)我能照看的文件描述符数量有限,不能超过1024个;
  • 2)用户给我的文件描述符需要拷贝的内核中;
  • 3)我只能告诉你有文件描述符满足要求了,但是我不知道是哪个,你自己一个一个去找吧(遍历)。

因此我们可以看到,select机制的这些特性在高并发网络服务器动辄几万几十万并发链接的场景下无疑是低效的。

8.2 poll:小有所成

poll和select是非常相似的。

poll相对于select的优化仅仅在于解决了文件描述符不能超过1024个的限制,select和poll都会随着监控的文件描述数量增加而性能下降,因此不适合高并发场景。

8.3 epoll:独步天下

在select面临的三个问题中,文件描述数量限制已经在poll中解决了,剩下的两个问题呢?

针对拷贝问题:epoll使用的策略是各个击破与共享内存。

实际上:文件描述符集合的变化频率比较低,select和poll频繁的拷贝整个集合,内核都快被烦死了,epoll通过引入epoll_ctl很体贴的做到了只操作那些有变化的文件描述符。同时epoll和内核还成为了好朋友,共享了同一块内存,这块内存中保存的就是那些已经可读或者可写的的文件描述符集合,这样就减少了内核和程序的拷贝开销。

针对需要遍历文件描述符才能知道哪个可读可写这一问题,epoll使用的策略是“当小弟”。

在select和poll机制下:进程要亲自下场去各个文件描述符上等待,任何一个文件描述可读或者可写就唤醒进程,但是进程被唤醒后也是一脸懵逼并不知道到底是哪个文件描述符可读或可写,还要再从头到尾检查一遍。

但epoll就懂事多了,主动找到进程要当小弟替大哥出头。

在这种机制下:进程不需要亲自下场了,进程只要等待在epoll上,epoll代替进程去各个文件描述符上等待,当哪个文件描述符可读或者可写的时候就告诉epoll,epoll用小本本认真记录下来然后唤醒大哥:“进程大哥,快醒醒,你要处理的文件描述符我都记下来了”,这样进程被唤醒后就无需自己从头到尾检查一遍,因为epoll小弟都已经记下来了。

因此我们可以看到:在epoll这种机制下,实际上利用的就是“不要打电话给我,有需要我会打给你”这种策略,进程不需要一遍一遍麻烦的问各个文件描述符,而是翻身做主人了——“你们这些文件描述符有哪个可读或者可写了主动报上来”。

这种机制实际上就是大名鼎鼎的事件驱动——Event-driven,这也是我们下一篇的主题。

实际上:在Linux平台,epoll基本上就是高并发的代名词。

9、本文小结

基于一切皆文件的设计哲学,I/O也可以通过文件的形式实现,高并发场景下要与多个文件交互,这就离不开高效的I/O多路复用技术。

本文我们详细讲解了什么是I/O多路复用以及使用方法,这其中以epoll为代表的I/O多路复用(基于事件驱动)技术使用非常广泛,实际上你会发现但凡涉及到高并发、高性能的场景基本上都能见到事件驱动的编程方法,当然这也是下一篇我们要重点讲解的主题《从根上理解高性能、高并发(四):深入操作系统,彻底理解同步与异步》,敬请期待!

附录:更多高性能、高并发文章精选

高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少

高性能网络编程(二):上一个10年,著名的C10K并发连接问题

高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了

高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索

高性能网络编程(五):一文读懂高性能网络编程中的I/O模型

高性能网络编程(六):一文读懂高性能网络编程中的线程模型

高性能网络编程(七):到底什么是高并发?一文即懂!

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

微信后台基于时间序的海量数据冷热分级架构设计实践

微信技术总监谈架构:微信之道——大道至简(演讲全文)

如何解读《微信技术总监谈架构:微信之道——大道至简》

快速裂变:见证微信强大后台架构从0到1的演进历程(一)

17年的实践:腾讯海量产品的技术方法论

腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面

以微博类应用场景为例,总结海量社交系统的架构设计步骤

新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践

从新手到架构师,一篇就够:从100到1000万高并发的架构演进之路

本文已同步发布于“即时通讯技术圈”公众号。

▲ 本文在公众号上的链接是:点此进入。同步发布链接是:http://www.52im.net/thread-3287-1-1.html

posted @ 2021-01-05 15:06 Jack Jiang 阅读(221) | 评论 (0)编辑 收藏

1、系列文章引言

1.1 文章目的

作为即时通讯技术的开发者来说,高性能、高并发相关的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或许你对具有这些技术特征的技术框架比如:Java的Netty、Php的workman、Go的nget等熟练掌握。但真正到了面视或者技术实践过程中遇到无法释怀的疑惑时,方知自已所掌握的不过是皮毛。

返璞归真、回归本质,这些技术特征背后的底层原理到底是什么?如何能通俗易懂、毫不费力真正透彻理解这些技术背后的原理,正是《从根上理解高性能、高并发》系列文章所要分享的。

1.2 文章源起

我整理了相当多有关IM、消息推送等即时通讯技术相关的资源和文章,从最开始的开源IM框架MobileIMSDK,到网络编程经典巨著《TCP/IP详解》的在线版本,再到IM开发纲领性文章《新手入门一篇就够:从零开发移动端IM》,以及网络编程由浅到深的《网络编程懒人入门》、《脑残式网络编程入门》、《高性能网络编程》、《不为人知的网络编程》系列文章。

越往知识的深处走,越觉得对即时通讯技术了解的太少。于是后来,为了让开发者门更好地从基础电信技术的角度理解网络(尤其移动网络)特性,我跨专业收集整理了《IM开发者的零基础通信技术入门》系列高阶文章。这系列文章已然是普通即时通讯开发者的网络通信技术知识边界,加上之前这些网络编程资料,解决网络通信方面的知识盲点基本够用了。

对于即时通讯IM这种系统的开发来说,网络通信知识确实非常重要,但回归到技术本质,实现网络通信本身的这些技术特征:包括上面提到的线程池、零拷贝、多路复用、事件驱动等等,它们的本质是什么?底层原理又是怎样?这就是整理本系列文章的目的,希望对你有用。

1.3 文章目录

1.4 本篇概述

接上篇《深入计算机底层,理解线程与线程池》,本篇是高性能、高并发系列的第2篇文章,在这里我们来到了I/O这一话题。你有没有想过,当我们执行文件I/O、网络I/O操作时计算机底层到底发生了些什么?对于计算机来说I/O是极其重要的,本篇将带给你这个问的答案。

2、本文作者

应作者要求,不提供真名,也不提供个人照片。

本文作者主要技术方向为互联网后端、高并发高性能服务器、检索引擎技术,网名是“码农的荒岛求生”,公众号“码农的荒岛求生”。感谢作者的无私分享。

3、不能执行I/O的计算机是什么?

相信对于程序员来说I/O操作是最为熟悉不过的了,比如:

  • 1)当我们使用C语言中的printf、C++中的"<<",Python中的print,Java中的System.out.println等时;
  • 2)当我们使用各种语言读写文件时;
  • 3)当我们通过TCP/IP进行网络通信时;
  • 4)当我们使用鼠标龙飞凤舞时;
  • 5)当我们拿起键盘在评论区指点江山亦或是埋头苦干努力制造bug时;
  • 6)当我们能看到屏幕上的漂亮的图形界面时等等。

以上这一切,都是I/O!

想一想:如果没有I/O计算机该是一种多么枯燥的设备,不能看电影、不能玩游戏,也不能上网,这样的计算机最多就是一个大号的计算器。

既然I/O这么重要,那么到底什么才是I/O呢?

4、什么是I/O?

I/O就是简单的数据Copy,仅此而已!

这一点很重要!

既然是copy数据,那么又是从哪里copy到哪里呢?

如果数据是从外部设备copy到内存中,这就是Input。

如果数据是从内存copy到外部设备,这就是Output。

内存与外部设备之间不嫌麻烦的来回copy数据就是Input and Output,简称I/O(Input/Output),仅此而已。

5、I/O与CPU

现在我们知道了什么是I/O,接下来就是重点部分了,大家注意,坐稳了。

我们知道现在的CPU其主频都是数GHz起步,这是什么意思呢?

简单说就是:CPU执行机器指令的速度是纳秒级别的,而通常的I/O比如磁盘操作,一次磁盘seek大概在毫秒级别,因此如果我们把CPU的速度比作战斗机的话,那么I/O操作的速度就是肯德鸡。

也就是说当我们的程序跑起来时(CPU执行机器指令),其速度是要远远快于I/O速度的。那么接下来的问题就是二者速度相差这么大,那么我们该如何设计、该如何更加合理的高效利用系统资源呢?

既然有速度差异,而且进程在执行完I/O操作前不能继续向前推进,那么显然只有一个办法,那就是等待(wait)。

同样是等待,有聪明的等待,也有傻傻的等待,简称傻等,那么是选择聪明的等待呢还是选择傻等呢?

假设你是一个急性子(CPU),需要等待一个重要的文件,不巧的是这个文件只能快递过来(I/O),那么这时你是选择什么事情都不干了,深情的注视着门口就像盼望着你的哈尼一样专心等待这个快递呢?还是暂时先不要管快递了,玩个游戏看个电影刷会儿短视频等快递来了再说呢?

很显然,更好的方法就是先去干其它事情,快递来了再说。

因此:这里的关键点就是快递没到前手头上的事情可以先暂停,切换到其它任务,等快递过来了再切换回来。

理解了这一点你就能明白执行I/O操作时底层都发生了什么。

接下来让我们以读取磁盘文件为例来讲解这一过程。

6、执行I/O时底层都发生了什么

在上一篇《深入计算机底层,理解线程与线程池》中,我们引入了进程和线程的概念。

在支持线程的操作系统中,实际上被调度的是线程而不是进程,为了更加清晰的理解I/O过程,我们暂时假设操作系统只有进程这样的概念,先不去考虑线程,这并不会影响我们的讨论。

现在内存中有两个进程,进程A和进程B,当前进程A正在运行。

如下图所示:

进程A中有一段读取文件的代码,不管在什么语言中通常我们定义一个用来装数据的buff,然后调用read之类的函数。

就像这样:

read(buff);

这就是一种典型的I/O操作,当CPU执行到这段代码的时候会向磁盘发送读取请求。

注意:与CPU执行指令的速度相比,I/O操作操作是非常慢的,因此操作系统是不可能把宝贵的CPU计算资源浪费在无谓的等待上的,这时重点来了,注意接下来是重点哦。

由于外部设备执行I/O操作是相当慢的,因此在I/O操作完成之前进程是无法继续向前推进的,这就是所谓的阻塞,即通常所说的block。

操作系统检测到进程向I/O设备发起请求后就暂停进程的运行,怎么暂停运行呢?很简单:只需要记录下当前进程的运行状态并把CPU的PC寄存器指向其它进程的指令就可以了。

进程有暂停就会有继续执行,因此操作系统必须保存被暂停的进程以备后续继续执行,显然我们可以用队列来保存被暂停执行的进程。

如下图所示,进程A被暂停执行并被放到阻塞队列中(注意:不同的操作系统会有不同的实现,可能每个I/O设备都有一个对应的阻塞队列,但这种实现细节上的差异不影响我们的讨论)。

这时操作系统已经向磁盘发送了I/O请求,因此磁盘driver开始将磁盘中的数据copy到进程A的buff中。虽然这时进程A已经被暂停执行了,但这并不妨碍磁盘向内存中copy数据。

注意:现代磁盘向内存copy数据时无需借助CPU的帮助,这就是所谓的DMA(Direct Memory Access)。

这个过程如下图所示:

让磁盘先copy着数据,我们接着聊。

实际上:操作系统中除了有阻塞队列之外也有就绪队列,所谓就绪队列是指队列里的进程准备就绪可以被CPU执行了。

你可能会问为什么不直接执行非要有个就绪队列呢?答案很简单:那就是僧多粥少,在即使只有1个核的机器上也可以创建出成千上万个进程,CPU不可能同时执行这么多的进程,因此必然存在这样的进程,即使其一切准备就绪也不能被分配到计算资源,这样的进程就被放到了就绪队列。

现在进程B就位于就绪队列,万事俱备只欠CPU。

如下图所示:

当进程A被暂停执行后CPU是不可以闲下来的,因为就绪队列中还有嗷嗷待哺的进程B,这时操作系统开始在就绪队列中找下一个可以执行的进程,也就是这里的进程B。

此时操作系统将进程B从就绪队列中取出,找出进程B被暂停时执行到的机器指令的位置,然后将CPU的PC寄存器指向该位置,这样进程B就开始运行啦。

如下图所示:

注意:接下来的这段是重点中的重点!

注意观察上图:此时进程B在被CPU执行,磁盘在向进程A的内存空间中copy数据,看出来了吗——大家都在忙,谁都没有闲着,数据copy和指令执行在同时进行,在操作系统的调度下,CPU、磁盘都得到了充分的利用,这就是程序员的智慧所在。

现在你应该理解为什么操作系统这么重要了吧。

此后磁盘终于将全部数据都copy到了进程A的内存中,这时磁盘通知操作系统任务完成啦,你可能会问怎么通知呢?这就是中断。

操作系统接收到磁盘中断后发现数据copy完毕,进程A重新获得继续运行的资格,这时操作系统小心翼翼的把进程A从阻塞队列放到了就绪队列当中。

如下图所示:

注意:从前面关于就绪状态的讨论中我们知道,操作系统是不会直接运行进程A的,进程A必须被放到就绪队列中等待,这样对大家都公平。

此后进程B继续执行,进程A继续等待,进程B执行了一会儿后操作系统认为进程B执行的时间够长了,因此把进程B放到就绪队列,把进程A取出并继续执行。

注意:操作系统把进程B放到的是就绪队列,因此进程B被暂停运行仅仅是因为时间片到了而不是因为发起I/O请求被阻塞。

如下图所示:

进程A继续执行,此时buff中已经装满了想要的数据,进程A就这样愉快的运行下去了,就好像从来没有被暂停过一样,进程对于自己被暂停一事一无所知,这就是操作系统的魔法。

现在你应该明白了I/O是一个怎样的过程了吧。

这种进程执行I/O操作被阻塞暂停执行的方式被称为阻塞式I/O,blocking I/O,这也是最常见最容易理解的I/O方式,有阻塞式I/O就有非阻塞式I/O,在这里我们暂时先不考虑这种方式。

在本节开头我们说过暂时只考虑进程而不考虑线程,现在我们放宽这个条件,实际上也非常简单,只需要把前图中调度的进程改为线程就可以了,这里的讨论对于线程一样成立。

7、零拷贝(Zero-copy)

最后需要注意的一点就是:上面的讲解中我们直接把磁盘数据copy到了进程空间中,但实际上一般情况下I/O数据是要首先copy到操作系统内部,然后操作系统再copy到进程空间中。

因此我们可以看到这里其实还有一层经过操作系统的copy,对于性能要求很高的场景其实也是可以绕过操作系统直接进行数据copy的,这也是本文描述的场景,这种绕过操作系统直接进行数据copy的技术被称为Zero-copy,也就零拷贝,高并发、高性能场景下常用的一种技术,原理上很简单吧。

PS:对于搞即时通讯开发的Java程序员来说,著名的高性能网络框架Netty就使用了零拷贝技术,具体可以读《NIO框架详解:Netty的高性能之道》一文的第12节。如果对于Netty框架很好奇但不了解的话,可以因着这两篇文章入门:《新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析》、《史上最通俗Netty入门长文:基本介绍、环境搭建、动手实战》。

8、本文小结

本文讲解的是程序员常用的I/O(包括所谓的网络I/O),一般来说作为程序员我们无需关心,但是理解I/O背后的底层原理对于设计比如IM这种高性能、高并发系统是极为有益的,希望这篇能对大家加深对I/O的认识有所帮助。

接下来的一篇《从根上理解高性能、高并发(三):深入操作系统,彻底理解I/O多路复用》将要分享的是I/O技术的一大突破,正是因为它,才彻底解决了高并发网络通信中的C10K问题(见《高性能网络编程(二):上一个10年,著名的C10K并发连接问题),敬请期待!

附录:更多高性能、高并发文章精选

高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少

高性能网络编程(二):上一个10年,著名的C10K并发连接问题

高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了

高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索

高性能网络编程(五):一文读懂高性能网络编程中的I/O模型

高性能网络编程(六):一文读懂高性能网络编程中的线程模型

高性能网络编程(七):到底什么是高并发?一文即懂!

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

微信后台基于时间序的海量数据冷热分级架构设计实践

微信技术总监谈架构:微信之道——大道至简(演讲全文)

如何解读《微信技术总监谈架构:微信之道——大道至简》

快速裂变:见证微信强大后台架构从0到1的演进历程(一)

17年的实践:腾讯海量产品的技术方法论

腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面

以微博类应用场景为例,总结海量社交系统的架构设计步骤

新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践

从新手到架构师,一篇就够:从100到1000万高并发的架构演进之路

本文已同步发布于“即时通讯技术圈”公众号。

▲ 本文在公众号上的链接是:点此进入。同步发布链接是:http://www.52im.net/thread-3280-1-1.html

posted @ 2020-12-28 14:42 Jack Jiang 阅读(201) | 评论 (0)编辑 收藏

     摘要: 本文原题“聊聊TCP连接耗时的那些事儿”,本次收录已征得作者同意,转载请联系作者。有少许改动。1、系列文章引言1.1 文章目的作为即时通讯技术的开发者来说,高性能、高并发相关的技术概念早就了然与胸,什么线程池、零拷贝、多路复用、事件驱动、epoll等等名词信手拈来,又或许你对具有这些技术特征的技术框架比如:Java的Netty、Php的workman、Go的nget等熟练掌...  阅读全文

posted @ 2020-12-23 16:19 Jack Jiang 阅读(401) | 评论 (0)编辑 收藏

本文由淘宝消息业务团队李历岷(花名骨来)原创分享,首次发表于公众号“淘系技术”,有修订和改动。

1、引言

本文来自淘宝消息业务团队的技术实践分享,分析了电商IM消息平台在非传统IM应用场景下的高发并、强互动群聊和直播业务中的技术特点,总结并分享了在这些场景下实现大量多对多实时消息分发投递的一些架构方面的设计实践。

目前,阿里的IM消息业务团队负责新零售领域 IM 消息平台的建设,通过 IM即时通讯产品(push、聊天机器人、单聊、群聊、消息号和聊天室)构建连接消费者和商家的沟通和触达渠道,每天处理百亿级的消费规模,支撑了直播互动、客服服务、商家群运营、品牌资讯、营销推送等电商领域 BC 互通的业务场景。

本文同步发布于:http://www.52im.net/thread-3252-1-1.html

2、技术背景

2020年双11,第一次改变节奏,从光棍节变成双节棍,从一个峰变成了两个峰,在新的挑战下,如何做好技术保障,做好技术支撑,所有技术人都进入了一个新的学习过程。

新的形势下,显著特点是时间跨度长、活动周期长以及用户互动玩法更多。从单用户CC分享到群内分享,以及直播间互动消息等,作为电商的IM消息平台,承接着整个互动的场地。

用户在整个“互动消息”场景下,可以进行实时分享、聊天、客服沟通、商家优惠、商家优惠活动和红包以及商品秒杀等。

“消息”作为用户和用户之间架起“连接”的重要桥梁,消息连接了用户和用户、用户和商家、用户和平台等。

如何做到高并发强互动下消息有序地呈现在用户面前,是消息团队亘古不变的主题,尤其是在用户的互动行为不确定性情况下,在面对不确定性的流量和规模时,系统应该怎样做到“丝般顺滑”的体验呢?本文将带着读者一起来进行深入探讨。

3、强互动消息场景的技术挑战

不同于传统社区IM消息平台,电商IM消息平台有自已的互动场景特点。

3.1 直播间

淘宝直播带来新的流量变化,百万在线已经成为常态化,大量的直播间7X24小时直播带货,用户在直播频道页频繁地进出不同的直播间。

有时候被某个直播间吸引,停在那里等着优惠、红包和宝贝,随着主播在直播间喊一嗓子,推送一张宝贝卡片,几十万人蜂拥而至秒杀。这样的场景每天都在上演 ...

3.2 互动PK群

主互动玩法“超级星秀猫瓜分20亿红包”开启的时候,意味着大量互动拉赞、分享到好友、分享到群成为流量的入口,无论淘口令/图片等。

大量的消息卡片被转发、二次转发带来的分享裂变效应,每天09:00和晚上22:00成为活跃的峰值,每个组队的用户拉群互赞,这样的场景从10月20日到11月11日持续每天固定时段上演 ...

3.3 不确定性流量

分享面板入口一次列表排布改变,营销活动的一次优惠推送,直播频道页一次运营活动都可能导致直播间/群的流量瞬间波动。

纷涌而至的用户带来了大量的互动行为,各种点击/分享/消息发送纷至沓来。

如何应对这样的流量和规模,作为平台系统,必须能够做到应对不确定性流量能力和机制,必须从流量入口到流量出口端到端考虑整体的全链路架构,是否存在单点瓶颈和缺口。

尤其在大促前期,系统架构梳理、强弱依赖梳理、上下游链路串联、破坏性压测、脉冲流量压测和全链路压测保障和优化,以及配合相关的流量控制、预案保护、业务流量隔离机制、资源调控等手段,才得以做到“不确定性流量”向“确定性流量”转变,才可以更大程度上保障系统高可用和极致用户体验。

4、强互动群聊中的消息架构实践

4.1 传统IM中“写扩散”架构的瓶颈

随着2018年淘系电商首推“双11合伙人计划”,更简单直接的双11玩法,给大众带来更多期待和惊喜。

尤其是盖楼互赞活动更是把“群聊”推上风口浪尖, 在手淘APP内部分享比在微信和钉钉等社交/企业软件分享更加便捷和高效,用户不停地在群内互动分享拉赞、通过好友助力提升盖楼积分。

基于传统的IM架构技术,尤其在群内聊天或者分享,每条消息按照群内人数进行写扩散,按照主互动500人群规模来计算,平均群大小320+,1:N的写入必然导致写入DB的RT以及存储压力,按照DB库承接120w/s写入速度,导致消息上行3K/s的极限,而实际参与互动分享的用户在峰值的时候远大于这部分互动分享和聊天消息流量。

其次集群的写入不可能完全给IM聊天消息,还有其它的营销活动、交易、物流等通知类型的消息。

基于传统IM的“写扩散”架构,在高并发、强互动场景下遇到了瓶颈,导致消息大量的延迟下推,影响最终用户体验。

4.2 “读扩散”架构的应用

基于写扩散架构的消息扩散比是1:N,那能否做到消息扩散比是1:1呢?

答案是肯定的:针对群内的消息可以分为“非个性化消息”和“个性化消息”,所谓“非个性化消息”就是大家看到都是一样的,应该只需要写一条数据,群内成员可以共享取这条数据(所谓“个性化消息”,指定某个成员发送的单边消息,譬如进群欢迎语等)。

在群内,99.99%都是“非个性化消息”,也就是可以从1:N压缩到1:1写入。

基于这个理论假设,需要考虑“读扩散”让每个用户的消息从对应的“群会话消息队列同步“数据,而不是从”用户队列同步“数据。

其中同步队列围绕队列offset偏移量进行,通过队列的自增syncId保证有序,每个客户端维护相应的队列的同步位点,采取“客户端存储位点的去中心化“方案,实现”下行消息的推拉“结合。

通过队列位点syncId进行比对,如果服务端消息队列syncId-客户端队列syncId=1,表示云端消息无空洞,否则携带客户端的队列和对应的syncId到云端重新同步区间数据,实现最终一致性。

传统的IM产品:腾讯QQ、腾讯微信、网易云通讯、抖音IM、钉钉IM、脉脉IM、支付宝IM。

PS:市面上APP80%都具备IM聊天能力,均采取写扩散简单模式进行云端消息同步。

4.3 “读扩散”、“写扩散”技术方案对比

4.3.1)写扩散技术:

优点:

  • 1)整体架构简洁,方案简单,维护用户同步队列实现数据同步机制;
  • 2)无论是单聊还是群聊等会话消息,写入用户维度同步队列,集中获取同步数据;
  • 3)推和拉情况下,存储模型和数据处理简单,且天然支持个性化数据。

缺点:

  • 1)群会话消息,天然存在1:N写入扩散比,存储压力N倍压力,在线用户收到消息延迟增大;
  • 2)多个群内消息队列混合在同步队列,无优先级处理能力,无法针对互动群等做隔离。

4.3.2)读扩散技术:

优点:

  • 1)降低写扩散N倍的DB存储压力,减少下行在线用户端到端扩散的RT时间;
  • 2)提升消息上行集群整体的吞吐量,用户体验更流畅;
  • 3)端到端实现会话级别的同步优先级队列,实现差异化服务。

缺点:

  • 1)整体架构偏复杂,需要维护每个动态会话消息同步队列,端侧需要实时感知新增的动态同步队列;
  • 2)客户端冷启动需要分散读取多个会话消息同步队列数据,对于存储会带来读QPS压力。

4.4 读写扩散混合模式

核心在于架构的演进推进“读写扩散混合模式“落地,结合两者的优点进行云端一体化数据同步技术,覆盖几千万互动群用户,保证整体峰值上行消息以及用户在群内端到端延迟体验,做到一条上行消息500ms以内到达群内其他用户端侧,让整体用户体验提升明显,群内强互动成为可能。

5、电商直播互动中的消息架构实践

5.1 技术挑战

电商直播呈现大直播若干个(大于30W同时在线)、中直播间几百个、小直播几万个这样分布,尤其是晚会和主播带来的热点直播间效应,对系统整体的IM消息架构存在热点带来严重挑战。

热点问题的产生需要从不确定性的流量来源说起。

直播间人员规模天然和群聊不一样(单个群<=500人),一个直播间可以突破40万-200万之间设备同时在线。

直播间在另一个层面是“特殊的群”,群维护了群和群成员强关系,直播间维护直播和设备之间的订阅弱关系,在扩散维度群按照500人进行分库分表切片模式分发下行消息,直播间需要以直播间几十万设备作为分段切片进行分发。同时直播间的指令消息如果不加以干预,会形成超大的流量热点和扩散问题。那么针对这个问题如何应对?

直播间互动全链路和核心处理节点简易时序图如下:

 

即:观众互动消息 -> 网关接入 -> 应用系统Buffer(秒级直播间维度消息) -> 编码、合并、批量消息流 -> 直播间维度设备扩散 -> 设备长连通道推送 -> 设备接收 -> 解码消息 -> 业务处理。

5.2 应对手段

5.2.1)充分利用直播间在线人数:

针对大直播间和小直播间区分对待,充分利用在线人数这个关键性指标。

譬如小直播间不做buffer队列处理(所谓buffer,就是维护topic维度的缓冲队列),支持N秒或消息条数的异步flush机制,实现削峰过程。

其中针对“可靠消息”进行持久化缓存存储,如果当前消息推送失败,重试3次或者下一条消息再次携带失败的可靠消息,整体按照推拉结合的方式,端侧做重复消息去重控制。

5.2.2)用户进出房间关系维护:

从用户第一次进直播间,发起订阅请求,最终通过大小直播间分片进行路由到指定的直播间,针对特殊大直播间提前做好集群分片。

或者通过每天的离线数据分析大直播间的账号,主播开播创建直播间的时候,提前做好分片确定性,在脉冲绑定关系的时候,流量分散到N台订阅集群进行绑定关系建立。

5.2.3)流控策略考虑:

流控不等于一刀切,而是针对不同的subType指令进行控制。

针对可靠消息(红包、优惠、宝贝卡片)等进行持久化存储,利用多次消息下推携带机制,同时兼顾端侧拉取机制,保证消息最终一致性且在3秒以内到达端侧。

5.2.4)一致性hash问题-热点直播间:

一致性Hash的架构必然存在热点问题,如果在直播间进行分散架构,必然存在指令风暴问题。基于此,需要进行Hash热点二次打散处理。

针对这样的热点问题技术上是可行的,热点问题散列到多台IP机器上进行流量承接,另外需要考虑直播间维度的统计数据分布式合并等问题,需要用到分布式锁并发写入统计数据,且直播维度数据合并计算,类似JDKStriped64原理。

6、“群聊”和“直播互动”的消息架构差异思考

因为早期两套系统各自演进应对不同的流量和产品需求,用户规模化和产品要求带来的差异化架构。

对比“群聊”和“直播间互动”两类互动场景,群聊基于消息、会话、会话视图以及附加消息存储和消息漫游能力进行整体设计。而对于直播间来说,围绕直播间大规模实时互动进行抽象设计,充分实现buffer/批量/订阅关系切片等机制。

对于关系来说:群关系是强关系,需要用户确认加群,才可以进群、退群、查看群好友等。对于直播间来说是弱关系,用户进直播、退出直播都是自动完成关系建立和取消,当然用户可以后续进入回放直播间。

因此:在功能上和模型设计上需要进一步思考,尤其现有回放直播间需要一套录制/回放指令机制,保存互动指令等关键性指令数据,而这点在消息IM场景完全支持了,包括用户可以漫游历史消息等。

技术的发展不会一尘不变,针对合适的场景进行差异化架构和设计才是最重要的,同样在应对不确定性流量这个场景下,解决问题的方式是不完全相同的,这个过程需要反复迭代和优化,围绕端到端用户体验这个核心目标进行技术演进才是最重要的价值选择和方向判断。

7、不确定性流量的消息QoS思考

不确定性的流量如何转为确定性流量,是技术必须要解决的“确定性”问题。

尤其面对流量需要确定性进行分解,分优先级保障不同的消息QoS能力是“高可用架构”永恒不变的主题,就像应用系统的限流,需要分场景进行流控一样。

基于这样的思考推演,QoS分级机制来承诺消息服务SLA,最终才可以做到隔离/优先级/差异化处理,完成整体的消息顺滑体验。

 

8、写在最后

面对不确定性的流量,需要进行流量再细分以及面向不同的场景采取不同的处理方案去应对,惯用的手段是指令合并处理、链路隔离和共享、租户存储隔离、流量打标机制区分场景来源等,以及有相对确定性的流量大脑进行观测,在峰值流量来临之前,需要具备流量感知和预警机制,做好流量的优先级划分,应急预案是快速失败限流还是慢速等待消费以及优先级控制等机制。

同时在系统层面,需要做到水平扩展能力,也就是能否通过弹性扩容的方式应对高流量的峰值,另外需要做到整体全链路合理的架构设计,避免“写入放大”以及“读取放大”的单点问题产生,需要针对入口流量和出口流量进行比对,是否可以做到上下游1:1的情况下,尽可能地避免单点瓶颈带来集群瓶颈乃至整体不可用。

“高可用架构“是技术人员永恒不变的主题之一,随着用户规模增长以及集中流量爆发的情形下,更需要敏锐地找到全链路单点问题,提前预判定义出面临的问题。然后给出合理的优化方案,最终灰度切流以及全链路压测验证保证整体方案有序推进,尤其面对的在线系统优化,好比开着飞机换轮胎一样。具备优化效果数据和监控是衡量每一步的预期收益,只有这样才可以做好“架构演进”,才可以持续交付更好的用户产品体验,赢得用户的喜爱,以及互动效果和产品流畅性才可以得到用户满意度提升。架构演进是个动态化的过程,需要持续投入和改进,推动全链路整体落地。

附录:更多相关资料

[1] 有关阿里巴巴的文章分享:

阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处

现代IM系统中聊天消息的同步和存储方案探讨

阿里技术分享:深度揭秘阿里数据库技术方案的10年变迁史

阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路

来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享

钉钉——基于IM技术的新一代企业OA平台的技术挑战(视频+PPT) [附件下载]

阿里技术结晶:《阿里巴巴Java开发手册(规约)-华山版》[附件下载]

重磅发布:《阿里巴巴Android开发手册(规约)》[附件下载]

作者谈《阿里巴巴Java开发手册(规约)》背后的故事

《阿里巴巴Android开发手册(规约)》背后的故事

干了这碗鸡汤:从理发店小弟到阿里P10技术大牛

揭秘阿里、腾讯、华为、百度的职级和薪酬体系

淘宝技术分享:手淘亿级移动端接入层网关的技术演进之路

难得干货,揭秘支付宝的2维码扫码技术优化实践之路

淘宝直播技术干货:高清、低延时的实时视频直播技术解密

阿里技术分享:电商IM消息平台,在群聊、直播场景下的技术实践

[2] 有关IM架构设计的文章:

浅谈IM系统的架构设计

简述移动端IM开发的那些坑:架构设计、通信协议和客户端

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

从零到卓越:京东客服即时通讯系统的技术架构演进历程

蘑菇街即时通讯/IM服务器开发之架构选择

腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT

微信后台基于时间序的海量数据冷热分级架构设计实践

微信技术总监谈架构:微信之道——大道至简(演讲全文)

如何解读《微信技术总监谈架构:微信之道——大道至简》

快速裂变:见证微信强大后台架构从0到1的演进历程(一)

17年的实践:腾讯海量产品的技术方法论

移动端IM中大规模群消息的推送如何保证效率、实时性?

现代IM系统中聊天消息的同步和存储方案探讨

IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

WhatsApp技术实践分享:32人工程团队创造的技术神话

微信朋友圈千亿访问量背后的技术挑战和实践总结

王者荣耀2亿用户量的背后:产品定位、技术架构、网络方案等

IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面

以微博类应用场景为例,总结海量社交系统的架构设计步骤

快速理解高性能HTTP服务端的负载均衡技术原理

子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)

新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践

一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践

阿里技术分享:深度揭秘阿里数据库技术方案的10年变迁史

阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路

社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等

社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进

社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节

社交软件红包技术解密(四):微信红包系统是如何应对高并发的

社交软件红包技术解密(五):微信红包系统是如何实现高可用性的

社交软件红包技术解密(六):微信红包系统的存储层架构演进实践

社交软件红包技术解密(七):支付宝红包的海量高并发技术实践

社交软件红包技术解密(八):全面解密微博红包技术方案

社交软件红包技术解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等

社交软件红包技术解密(十):手Q客户端针对2020年春节红包的技术实践

社交软件红包技术解密(十一):解密微信红包随机算法(含代码实现)

即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途

多维度对比5款主流分布式MQ消息队列,妈妈再也不担心我的技术选型了

从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路

从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结

从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

瓜子IM智能客服系统的数据架构设计(整理自现场演讲,有配套PPT)

阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处

微信后台基于时间序的新一代海量数据存储架构的设计实践

IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!

阿里技术分享:电商IM消息平台,在群聊、直播场景下的技术实践

>> 更多同类文章 ……

本文已同步发布于“即时通讯技术圈”公众号:

▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3252-1-1.html

posted @ 2020-12-18 22:04 Jack Jiang 阅读(216) | 评论 (0)编辑 收藏

     摘要: 本文作者张彦飞,原题“图解Linux网络包接收过程”,内容有少许改动。1、引言因为要对百万、千万、甚至是过亿的用户提供各种网络服务,所以在一线互联网企业里面试和晋升后端开发同学的其中一个重点要求就是要能支撑高并发,要理解性能开销,会进行性能优化。而很多时候,如果你对网络底层的理解不深的话,遇到很多线上性能瓶颈你会觉得狗拿刺猬,无从下手。这篇文章将用图解的方式,从操作系统这一...  阅读全文

posted @ 2020-12-09 15:13 Jack Jiang 阅读(237) | 评论 (0)编辑 收藏

     摘要: 本文由朱益盛、杨晖、傅啸分享,来自IBM Developer社区,原题“使用 Java 开发兼容 IPv6 的网络应用程序”,本次收录时有改动。1、引言前几天,有个群友跟我讨论用 MobileIMSDK 写的IM服务端想支持IPv6的问题。因为众所周之的原因,IPv4早就不够用,现在国内从国家层面都在大力推广IPv6的普及,所以包括事业单位、国企在内,现在搞信息化...  阅读全文

posted @ 2020-12-07 19:31 Jack Jiang 阅读(521) | 评论 (0)编辑 收藏

     摘要: 本文由淘宝直播音视频算法团队原创分享,原题“5G时代|淘宝直播高画质低延时技术探索”,收录时有改动。1、引言目前,5G技术应用正在逐步推进,相比目前广泛使用的4G, 它具有更高的速率,更大的容量,同时延迟更低, 可靠性更高。在5G时代,得益于网络带宽的提升,视频未来将成为主流的传播媒介。越来越多的业务和应用将视频化、直播化。 大量互动的内容将通过5G以低延时的方式以视频的形...  阅读全文

posted @ 2020-11-26 15:41 Jack Jiang 阅读(288) | 评论 (0)编辑 收藏

     摘要: 原作者江成军,原题“还在被Java NIO虐?该试试Netty了”,收录时有修订和改动。1、阅读对象本文适合对Netty一无所知的Java NIO网络编程新手阅读,为了做到这一点,内容从最基本介绍到开发环境的配置,再到第一个Demo代码的编写,事无巨细都用详细的图文进行了说明。所以本文这对于新手来说帮助很大,但对于老司机来说,就没有必要了。老司机请绕道哦。PS:是的,用Ja...  阅读全文

posted @ 2020-11-18 14:35 Jack Jiang 阅读(472) | 评论 (0)编辑 收藏

仅列出标题
共47页: First 上一页 22 23 24 25 26 27 28 29 30 下一页 Last 
Jack Jiang的 Mail: jb2011@163.com, 联系QQ: 413980957, 微信: hellojackjiang