1.前言
本文延续了上一篇文章“高性能网络编程(ⅵ):理解高性能网络编程中的输入/输出模型”。
随着互联网的发展,面对大量高并发业务的用户,传统的阻塞式服务器端架构模式已经无能为力。本文(与前一篇文章“高性能网络编程(5):阅读高性能网络编程中的输入/输出模型”相比较)旨在为您提供高性能网络编程中输入/输出模型的有用概述以及网络服务过程模型的比较,从而揭示设计和实现高性能网络体系结构的奥秘。
此外,作者的其他文章,“初学者:到目前为止对Netty的高性能原则和框架架构的最彻底的分析”,“构成即时消息开发的基础知识(6):数据库是使用NoSQL还是使用SQL?读读这个!”,也值得一读,建议大家一起读。
2.关于作者
蔡森陈主要从事服务器开发、需求分析、系统设计、优化和改造。他的主要开发语言是Java。他目前是广州北朝服务器的R&D工程师。
关于广州贝聊天:
高性能网络编程(6):读取高性能网络编程中的线程模型
广州北辽信息技术有限公司成立于2013年8月21日,是一家致力于搭建幼儿园家庭合作教育平台的信息技术公司。
该公司的产品“贝聊”是中国幼儿园家长工作的平台。它致力于帮助幼儿园解决家长工作中的棘手问题,如通过互联网产品和定制解决方案进行展示、通知和沟通,以及促进家庭之间的和谐关系。北辽是伟创(a股学前教育的第一股)、清华蒂奇和网易投资的唯一品牌。
到目前为止,“贝聊”已经覆盖了中国31个省的5万所幼儿园和机构,注册用户超过1000万。下个月用户保留率高达74%,复合增长率为18.94%,领先全行业。
3.C10K系列文章
本文是C10K问题系列文章的第六篇,内容如下:
高性能网络编程(一):一台服务器可以有多少个并发的TCP连接
高性能网络编程(二):十年来著名的C10K并发连接问题
高性能网络编程(3):在未来10年,是时候考虑C10M的并发问题了
高性能网络编程(四):从C10K到C10M的高性能网络应用的理论探索
高性能网络编程(5):读取高性能网络编程中的输入输出模型
高性能网络编程(ⅵ):理解高性能网络编程中的线程模型(本文)
高性能网络编程经典:C10K问题[附件下载]
4.线程模型
前一篇文章“高性能网络编程(ⅵ):阅读高性能网络编程中的输入/输出模型”介绍了服务器如何管理连接并基于输入/输出模型获取输入数据,然后介绍了服务器如何基于进程/线程模型处理请求。
值得注意的是,线程或进程的选择更多地与平台和编程语言相关。
例如,C语言可以同时使用线程和进程(例如,Nginx使用进程,Memcached使用线程),而Java语言通常使用线程(例如,Netty)。为了便于描述,下面使用线程进行描述。
5.线程模型1:传统的阻塞式输入/输出服务模型
高性能网络编程(6):阅读高性能网络编程中的线程模型_1.jpeg
特点:
1)采用分块输入输出模型获取输入数据;
2)每个连接都需要一个独立的线程来完成数据输入、业务处理和数据返回的完整操作。
存在一些问题:
1)当并发数量较大时,需要创建大量的线程来处理连接,这会占用大量的系统资源;
2)连接建立后,如果当前线程暂时没有数据可读,线程会阻塞读操作,造成线程资源的浪费。
6.线程模型2:反应器模式
6.1基本介绍
针对传统阻塞式输入/输出服务模型的两个缺点,常用的解决方案如下:
1)基于输入/输出重用模型:多个连接共享一个阻塞对象,应用程序只需要等待一个阻塞对象而不阻塞所有连接。当连接有新的数据可以处理时,操作系统通知应用程序线程从阻塞状态返回并开始处理业务;
2)基于线程池重用线程资源:不是为每个连接创建一个线程,而是将连接完成后的业务处理任务分配给线程处理,一个线程可以处理多个连接的业务。
与线程池相结合的输入/输出复用是反应器模式的基本设计思想,如下图所示:
高性能网络编程(6):阅读高性能网络编程中的线程模型_2.jpeg
反应堆模式是指服务请求的事件驱动处理模式,服务请求通过一个或多个输入同时传输到服务处理器。
服务器端程序处理传入的多个请求,并将它们同步分派给相应的处理线程。反应堆模式也称为调度程序模式。
也就是说,I/O重用统一的监控事件,并在接收到事件后分发它们(将它们分派给某个进程),这是编写高性能网络服务器所必需的技术之一。
反应器模式有两个关键组件:
1)反应堆:反应堆在单独的线程中运行,该线程负责监视和分发事件,并将它们分发到适当的处理程序以响应IO事件。它就像一家公司的电话接线员,接听客户的电话,并将线路转接到合适的联系人;
2)处理者:当处理者执行输入/输出事件时要完成的实际事件类似于客户想要与之交谈的公司的实际官员。反应堆通过分派适当的处理程序来响应输入/输出事件,这些处理程序执行非阻塞操作。
根据反应器的数量和线程处理资源池的数量,有三种典型的实现方式:
1)单反应器单线程;
2)单反应器多线程;
3)主从反应器多线程。
下面将详细描述这三种实现方式。
6.2单反应器单线程
高性能网络编程(6):阅读高性能网络编程中的线程模型_3.jpeg
其中,Select是由输入/输出复用模型引入的标准网络编程接口,它可以实现应用程序通过一个阻塞对象监听多个连接请求。其他方案类似。
方案描述:
1)1)反应堆对象通过选择监视客户端请求事件,并在接收到事件后通过调度分发它们;
2)如果是连接建立请求事件,接受者通过接受来处理连接请求,然后在连接完成后创建一个处理程序对象来处理后续的业务处理;
3)如果不是连接建立事件,反应器将分发与呼叫连接相对应的处理程序进行响应;
4)处理程序将完成读取→业务处理→发送的完整业务流程。
优点:该模型简单,不存在多线程、进程通信和竞争问题,所有这些都在一个线程中完成。
缺点:性能问题,只有一个线程,无法充分发挥多核处理器的性能。当处理程序处理某个连接上的业务时,整个过程无法处理其他连接事件,这很容易导致性能瓶颈。
可靠性问题、意外线程失控或进入无限循环,将导致整个系统的通信模块不可用,无法接收和处理外部消息,导致节点故障。
使用场景:客户端数量有限,业务处理速度非常快,比如Redis,业务处理的时间复杂度为O(1)。
6.3单反应器多线程
高性能网络编程(6):阅读高性能网络编程中的线程模型_4.jpeg
方案描述:
1)1)反应堆对象通过选择监视客户端请求事件,并在接收到事件后通过调度分发它们;
2)如果是连接请求事件,接受者通过接受来处理连接请求,然后在连接完成后创建一个处理程序对象来处理各种后续事件;
3)如果不是连接建立事件,反应器将分发与呼叫连接相对应的处理程序进行响应;
4)处理者只负责响应事件,不做具体的业务处理。通过“读取”读取数据后,它将被分发到以下工作线程池进行业务处理;
5)工作线程池将分配独立的线程来完成真正的业务处理,以及如何将响应结果发送给处理程序进行处理;
6)在收到响应结果后,6)处理程序通过发送将响应结果返回给客户端。
优点:可以充分利用多核处理器的处理能力。
缺点:多线程数据共享和访问复杂;Reactor负责监控和响应所有事件,并在单个线程中运行,这很容易成为高并发情况下的性能瓶颈。
6.4主从反应器多线程
高性能网络编程(6):阅读高性能网络编程中的线程模型_5.jpeg
鉴于单反应器多线程模型,反应器在单个线程中运行,这在高并发情况下很容易成为性能瓶颈,因此反应器可以在多线程中运行。
方案描述:
1)反应堆主线程的主反应堆对象通过选择监控连接建立事件,接收到事件后通过接受者接收事件,并处理连接建立事件;
2)在2)接受者处理连接建立事件之后,主反应器将反应器的子线程分配给子反应器进行处理;
3)子连接器将连接添加到连接队列中进行监视,并创建一个处理程序来处理各种连接事件;
4)当新事件发生时,子连接器将调用与连接对应的处理程序进行响应;
5)在5)处理程序通过读取来读取数据之后,它将被分发到下面的工作线程池进行业务处理;
6)工作线程池将分配独立的线程来完成真正的业务处理,以及如何将响应结果发送给处理程序进行处理;
7)在收到响应结果后,7)处理程序通过发送将响应结果返回给客户端。
优点:父线程和子线程之间的数据交互简单,责任明确。父线程只需要接收新的连接,子线程完成后续的业务处理。
父线程和子线程之间的数据交互很简单。反应器的主线程只需要将新连接传递给子线程,子线程不需要返回数据。
该模型广泛应用于许多项目,包括Nginx主从反应堆多进程模型、Memcached主从多线程模型和Netty主从多线程模型。
6.5摘要
这三种模式可以用一个比喻来理解:(餐馆经常雇佣接待员来接待顾客,当顾客进来时,服务员会专门为顾客服务)
1)单反应器和单线程,接待员和服务员是同一个人,一路为顾客服务;
2)单反应器多线程,一个接待员,多个服务员,接待员只负责接待;
3)多线程主从反应堆,多个接待员和多个服务员。
反应器模式具有以下优点:
1)响应速度快,不需要被单一的同步时间阻塞,尽管反应堆本身仍然是同步的;
2)编程相对简单,可以最大限度地避免复杂的多线程和同步问题,避免多线程/进程的切换开销;
3)可扩展性,通过增加反应器实例的数量,可以充分利用CPU资源;
4)可重用性,反应器模型本身与具体的事件处理逻辑无关,具有很高的可重用性。
7.线程模型2:代理模型
在反应堆模式下,反应堆等待事件或适用或操作状态发生(例如,文件描述符可以读写,或者套接字可以读写)。
然后将此事件传递给预注册的处理程序(事件处理程序或回调函数),后者将执行实际的读写操作。
读写操作都需要应用同步操作,因此电抗器是一种无阻塞同步网络模型。
如果将输入/输出操作更改为异步,也就是说,将其移交给操作系统,这可以进一步提高性能。这是异步网络模型Proactor。
高性能网络编程(6):阅读高性能网络编程中的线程模型_1.jpeg
该方案与异步输入输出相关,具体方案如下:
1)代理发起者创建代理和处理程序对象,并通过异步操作处理器向内核注册代理和处理程序;
2)异步光处理器处理注册请求和输入输出操作;
3)asymopprocessor通知主动者;完成输入输出操作后;
4)代理根据不同的事件类型调用不同的处理程序进行业务处理;
5)经办人完成业务处理。
你可以看到演员和演员的区别:
1)反应器将在事件发生时通知预先注册的事件(在应用程序线程中完成读取和写入);
2)当事件发生时,Actor完成基于异步输入输出的读写操作(由内核完成),然后在输入输出操作完成后,调用应用程序的处理器进行业务处理。
理论上,代理比代理更有效,异步输入输出充分发挥了直接内存访问的优势。
然而,Proactor有以下缺点:
1)编程复杂性,因为异步操作过程事件的初始化和完成在时间和空间上是相互分离的,所以开发异步应用程序更加复杂。应用程序也可能变得更加难以调试;由于逆流控制;
2)内存使用,缓冲区必须保持在读写操作的时间段内,这可能会导致连续的不确定性,并且每个并发操作都需要一个独立的缓存。与反应堆模式相比,在套接字准备好读取或写入之前,不需要打开缓存;
3)操作系统支持。真正的异步输入输出是在Windows下通过IOCP实现的,但Linux 2.6只是在Linux系统下引入的。目前,异步输入输出并不完美。
因此,在Linux下实现高并发网络编程主要是基于反应器模型。
(本文的第一部分是“高性能网络编程(5):阅读高性能网络编程中的输入/输出模型”,您也可以阅读它。)
附录:更多关于网络编程本质的文章
[1]网络编程基础数据:
TCP/IP的详细说明-第11章UDP:用户数据报协议
TCP/IP的详细说明-第17章TCP:传输控制协议
TCP/IP的详细说明-第18章TCP连接的建立和终止
TCP/IP的详细说明-第21章TCP的超时和重传
技术过去:TCP/IP协议改变世界(珍贵的多画面,手机注意)
易于理解——对TCP协议的深刻理解(一):理论基础
易于理解——对TCP协议的深刻理解(ⅱ): RTT,滑动窗口,拥塞处理
理论经典:三次握手和四波TCP协议详解
理论与实践相结合:无线鲨鱼对TCP三握手四波的数据包捕获分析
计算机网络通信协议图(中文版)
UDP中数据包的最大大小是多少?》
P2P技术的详细说明(一):网络地址转换的详细说明——P2P的详细原理和介绍
P2P技术详解(二):P2P中的网络地址转换穿越(打洞)方案详解
P2P技术详细说明(3):P2P技术的STUN、TURN和ICE的详细说明
易于理解:快速理解P2P技术中的NAT穿透原理
未知网络编程(一):TCP协议中的疑难问题分析(上)
未知网络编程(二):TCP协议中的疑难问题分析(下)
未知的网络编程(3):为什么在关闭TCP连接时要等待时间和关闭等待时间
未知网络编程(4):深入研究和分析TCP异常关机
未知网络编程(5): UDP连接和负载平衡
未知网络编程(ⅵ):深入理解UDP协议并充分利用它
未知网络编程(七):如何使不可靠的UDP可靠?》
惰性网络编程导论(一):网络通信协议的快速理解(上)
惰性网络编程导论(二):网络通信协议的快速理解(下)
网络编程中的懒人介绍(3):快速理解TCP协议就足够了
网络编程中的懒人介绍(4):快速理解TCP和UDP的区别
网络编程中的懒人入门(5):快速理解为什么UDP有时优于TCP
网络编程中的懒人介绍(6):历史上最流行的集线器、交换机和路由器的功能原理介绍
网络编程中的懒人介绍(7):用简单的方式理解HTTP协议
网络编程中的懒人介绍(8):教你写基于TCP的套接字长连接。
网络编程中的懒人介绍(9):通俗的解释,当你有IP地址的时候为什么要用MAC地址?》
技术素养:新一代基于UDP的低延迟网络传输层协议
让互联网更快:分享腾讯新一代QUIC协议的技术实践
现代移动网络短连接优化方法综述:请求速度、弱网络适应和安全保障
“谈谈网络编程在iOS中的长连接”
“移动即时消息开发人员必须阅读(1):易于理解,理解移动网络的“弱”和“慢”
移动即时消息开发者必须阅读(2):历史上最全面的移动弱网络优化方法总结
IPv6技术详解:基本概念、应用现状和技术实践(上)
IPv6技术详解:基本概念、应用现状和技术实践(下)
理解HTTP协议从HTTP/0.9到HTTP/2的历史演变和设计思想;
脑残网络编程导论(1):学习TCP三次握手和四波动画
脑残网络编程导论(2):读写套接字时,我们在读什么和写什么?》
脑残网络编程导论(3):对超文本传输协议的一些必要知识
脑残网络编程导论(4):对HTTP/2服务器推送的快速理解
脑残网络编程入门(5):每天使用的Ping命令是什么?》
脑残网络编程导论(6):什么是公共知识产权和内部网知识产权?什么是自然语言转换?》
以网络游戏服务器的网络接入层设计为例,了解实时通信的技术挑战
更高层次:优秀安卓程序员必须了解的网络基础。
全面了解移动域名系统域名劫持和其他各种疾病:技术原理、问题根源、解决方案等。
“米托应用的移动域名系统优化实践:HTTPS请求时间减少了近一半”
安卓程序员必须知道的网络通信传输层协议——UDP和TCP
面向即时通信开发者的零基通信技术介绍(一):通信交换技术百年发展历程(一)
面向即时消息开发者的零基通信技术介绍(二):通信交换技术百年发展历程(二)
即时通讯开发者零基通讯技术介绍(三):中国通讯模式的百年变迁
面向即时消息开发者的零基通信技术介绍(四):手机的演变,历史上最完整的移动终端发展历史
面向即时通讯开发者的零基通信技术介绍(五):1G到5G,移动通信技术30年的演进历程
即时通讯开发者零基通信技术介绍(六):“基站”技术作为移动终端的连接器
即时通讯开发者零基通信技术介绍(七):移动终端的最大化——“电磁波”
即时消息开发者零基通信技术介绍(8):零基,历史上最强的“天线”原则素养
即时消息开发者零基通信技术介绍(九):“核心网”,无线通信网络的中心
即时通讯开发者零基通讯技术介绍(10):零基,历史上最强的5G技术素养
即时通讯开发者零基通信技术介绍(XI):为什么无线信号不好?一句话就明白了!》
即时消息开发者零基通信技术介绍(12):互联网接入?网络中断了吗?一句话就明白了!》
> >更多类似的文章...
[2] NIO高性能异步网络编程数据:
介绍Java新一代网络编程模型的AIO原理和Linux系统的AIO
关于“为什么选择Netty”的11个问题和答案
关于开源NIO框架的流言蜚语——首先是MINA还是Netty?》
选择内蒂还是米娜:深入研究与比较(一)
选择内蒂还是米娜:深入研究和比较(2)
NIO框架介绍(一):服务器端基于网络4的UDP双向通信演示
NIO框架介绍(2):服务器端基于MINA2的UDP双向通信演示
NIO框架介绍(3):iOS与MINA2和Netty4之间跨平台UDP双向通信的实战
NIO框架介绍(四):安卓与MINA2和网络4之间跨平台UDP双向通信的实战
网络4.x学习(一):字节流的详细说明
Netty 4.x学习(二):渠道和渠道的详细说明
Netty 4.x学习(3):线程模型的详细说明
Apache Mina框架的高级章节(一):IoFilter的详细解释
Apache Mina框架的高级章节(2):IoHandler的详细解释
MINA2线程原理总结(包括简单的测试案例)
Apache MINA2.0开发指南(中文版)[附件下载]
MINA和Netty(在线阅读版)的源代码已经整理出来并发布
用源代码解决多协议数据传输中的TCP粘包和丢包问题
解决Mina中同一类型的多个过滤器实例共存的问题
"实践总结:那些被3.x网升级4.x网(线程)遇到的坑. "
实践总结:网3.x与网4.x的线程模型
Netty安全性详细说明:原理介绍和代码演示(第一部分)
内蒂安全性的详细说明:原理介绍和代码演示(第二部分)
详细解释内蒂优雅的退出机制和原理
NIO框架的详细说明:Netty的高性能
Twitter:如何使用Netty 4来减少JVM的GC开销(翻译)
绝对干货:基于网络的大规模接入推送服务的技术要点
网状干货共享:京东小麦生产级TCP网关技术实践总结
初学者:迄今为止对Netty的高性能原则和框架架构的最彻底的分析
> >更多类似的文章...
即时消息网络-即时消息开发者社区!来源:即时消息网络-即时消息开发者社区!
哇谷im_im即时通讯_私有云_公有云-哇谷云科技官网-JM沟通
IM下载体验 - 哇谷IM-企业云办公IM即时聊天社交系统-JM 沟通下载
IM功能与价格 - 哇谷IM-提供即时通讯IM开发-APP搭建私有化-公有云-私有化云-海外云搭建
新闻动态 - 哇谷IM-即时通讯热门动态博客聊天JM沟通APP
关于哇谷-哇谷IM-提供企业即时通讯IM开发-语音通话-APP搭建私有化-公有云-私有化云-海外云搭建
联系我们 - 哇谷IM-即时通讯IM私有化搭建提供接口与SDK及哇谷云服务
IM云系统即时通讯公有云、私有云、企业云、海外云-哇谷IM团队
im即时通讯社交软件APP红包技术分析(五):微信红包、聊呗红包、诚信红包、高并发技术
公有云和私有云之间有什么区别?类似融云、环信云、网易云、哇谷云?