[译]多线程网络服务模型

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

多线程网络服务模型

/*** 谨献给Yoyo** 原文出处:https://www.toptal.com/software/guide-to-multi-processing-network-server-models* @author dogstar.huang <chanzonghuang@gmail.com> 2016-04-02*/

作为多年来一直在编写高性能网络代码的人(我的博士论文主题是适配多核系统分布式应用的高速缓存服务),现在我看到了很多完全不知道或忽略讨论网络服务模型基本原理的教程。因此,本文旨在希望能为大家提供有用的概览以及网络服务模型的比较,以揭开编写高性能网络代码的神秘面纱。

本文主要针对“系统程序员”,即与他们的应用程序的底层细节工作、实现网络服务代码的后端开发。这通常是在C++或C来完成,虽然时下大部分现代语言和框架通过各种级别的效率提供了体面的底层功能。

既然通过增加内核更容易扩展CPU,我会把这作为常识,而本质却是调整软件以便最大化使用这些内核。因此,问题就变成如何在能在多个CPU上并行执行的线程(或进程)中分区软件。

我也将理所当然地认为读者意识到,“并发”基本上意味着“多任务处理”,即一些代码实例(无论是相同或不同的代码,这并不重要),在同一时间是活跃的。并发可以在单个CPU上实现,并且通常前现代时期是这样的。具体地,并发可以通过在单个CPU上的多个进程或线程之间快速切换来实现。这是老式的、单CPU系统如何管理在同一时间运行众多应用程序的方式,在某种程度上,用户会觉得应用程序是在同时执行,尽管实际上并没有。另一方面,平行度,从字面上看具体意味着代码通过多个CPU或CPU内核在同一时间执行。

分区应用程序(到多个进程或线程)

出于这个讨论的目的,假如我们谈论线程或全过程,它基本上是不相关的。现代操作系统(而Windows显然是个例外)把进程看待像线程一样轻量级(或在某些情况下,反之亦然,线程都获得了功能,这使得它们像进程一样重量级)。如今,进程和线程之间的主要区别是在跨进程或跨线程通信和数据共享的功能。其中,进程和线程之间的区别是很重要的,我会进行适当的备注,否则,在这些部分可以安全地考虑“线程”和“过程”是可以互换的。

通用网络应用任务与网络服务模型

这篇文章具体处理网络服务代码,这部分需要实现以下三个任务:

  • 任务#1:建立(和拆除)的网络连接
  • 任务#2:网络通信(IO)
  • 任务#3:有用的工作;例如负载或者应用程序为什么存在的原因

关于跨进程分区分区这三个任务,这里有几个普遍的网络服务模型,即:

  • MP:多进程
  • SPED:单进程,事件驱动
  • SEDA:分阶段的事件驱动架构
  • AMPED:非对称多进程事件驱动
  • SYMPED:对称多处理事件驱动

这些都是在学术界使用的网络服务模型的名字,我记得“在野外”的同义词发现至少其中的一些。(名字本身,当然,并不是那么重要的 -- 真正的价值是如何洞悉代码是怎么回事。)

这些网络服务模型,每一个都会在下面的部分中进一步说明。

多进程(MP)模型

MP的网络服务模型是每个人都会首选用来学习的一个,特别是学习多线程的时候。在MP模型中,有一个“master”进程,接收连接(任务#1)。一旦建立了连接,主进程创建一个新的进程,并把连接的socket传给它,所以一个进程一个连接。这个新的进程然后通常和此连接以简单、连续、锁步的方式工作:进程从连接中读取一些东西(任务#2),然后做一些计算(任务#3),然后写一些东西给它(再次 任务#2)。

模型MP是很容易实现的,而且实际工作极为出色只要进程总数维持很低很低。有多低?答案取决于任务#2和任务#3蕴含了什么。经验法则,可以说进程数或线程数不应超过CPU内核的两倍。一旦有在同一时间激活太多进程,操作系统则趋于花费了太多在于时间抖动(即,围绕可用的CPU内核上平衡进程或线程)和这样的应用通常最终花费几乎所有的CPU的一次在“SYS”(或内核)代码,实际上却做了一点点真正有用的工作。

优点:实现很简单,只要连接数很少可以工作得非常好。

缺点:如果进程数增长太大则趋于使得操作系统过载过重,并且可能会有延迟抖动网络IO等待,直到有效载荷(计算)阶段结束。

单进程事件驱动(SPED)模型

该SPED网络服务器模型,因最近一些高调的网络服务应用程序,如Nginx而出名。基本上,它在同一个进程做了这三项任务,在它们之间之间复用。为了提高效率,它需要像epoll和kqueue的一些相当先进的核心功能。在这种模型下,代码是由传入的连接和数据“事件”驱动,并且实现了一个看起来像这样的“事件循环”:

  • 问操作系统是否有任何新的网络“事件”(如新的连接或输入数据)
  • 如果有新的可用连接,建立他们(任务#1)
  • 如果有可用的数据,读取它(任务#2)并对它采取行动(任务3#)
  • 重复,直到服务器退出

所有这一切都在一个单一的进程中完成,并且可以非常有效地完成,因为它完全避免了进程之间的上下文切换,这通常会造成MP模型严重的性能问题。这里唯一的上下文切换来自系统调用,而这些又通过仅作用于有某些事件绑定的具体连接而使得切换最小化。该模型可以同时处理数万的连接,只要有效载荷工作(任务#3)不是太复杂或是资源密集型的。

尽管这种方式有两大缺点:

  • 1、由于三个任务都在一个单一的循环迭代中顺序进行,有效载荷工作(任务#3)和所有东西都是同步完成的,也就是说,如果它需要很长的时间来计算到由客户端接收的数据的响应,当正在做这点时其他东西都会停止,而这会在延迟中引入潜在的巨大波动。

  • 2、只使用一个CPU内核。这样再次是有好处,绝对限制了来自操作系统要求的上下文切换数量,从而提高了整体性能,但有明显的不足就是其他任何可用的CPU内核都无事可做。

这是对于需要更先进的模型的理由。

优点:可以是具有高性能,在操作系统易于实现(即,需要最少量的OS干预)。只需要一个CPU内核。

缺点:仅利用单个CPU(不管可用的数量)。如果有效载荷工作不统一,会导致非均匀的响应延迟。

分阶段的事件驱动架构(SEDA)模型

该SEDA网络服务模型有点复杂。它把复杂的,事件驱动的应用程序分解到一组由队列连接的阶段。尽管如果不仔细实现,它的性能会跟MP情况中同一问题而受到影响。它的工作原理是这样的:

  • 有效载荷工作(任务#3)会尽可能地分成多个阶段,或模块。每个模块实现了驻留在其自己单独的进程中单个特定功能(可认为是“微服务”或“微内核”),并且这些模块经由消息队列相互通信。此架构可以表示为节点图,其中节点是进程,边是消息队列。

  • 一个单一进程执行任务#1(通常遵循SPED模型),它将新连接交付于特定的条目点节点。这些节点可以是传递数据给其他节点进行计算,或者也可以是实现有效载荷处理(任务3#)的纯网络节点(任务#2)。通常没有“master”进程(例如,一个收集并聚集响应,并将其通过连接发送返回),因为每一个节点都可以通过自身进行响应。

理论上,这种模式可以是任意复杂的,因为节点图可能具有循环,连接到其他类似的应用程序,或是连接到实际上是在远程系统上执行的节点。但在实践中,即使有定义良好的消息和高效的队列,它会变得笨拙难以思考,并且把系统的行为作为一个整体来推理。相比于SPED的模式,来往传递的消息可能会破坏该模型的性能,如果每个节点的工作都是很简短的话。该模型的效率显然比SPED模型的要低,所以它通常采用在有效载荷的工作复杂且耗时的情况。

优点:软件架构师最终的梦想:一切都分割成整齐而又独立的模块。

缺点:复杂度随模块数量而爆炸,并且消息队列仍然比直接内存共享慢得多。

非对称多进程事件驱动(AMPED)模型

该AMPED网络服务是SEDA驯服的,更易于模型的一个版本。没有过多不同的模块和进程,也没有多过的消息队列。下面是它如何工作的:

  • 以SPED风格在一个单一的“master”进程中实现任务#1和任务#2。这是网络IO的唯一进程。
  • 在一个单独的“worker”进程中实现任务#3(可能在多个实例中启动),通过一个队列连接到主进程(每个进程一个队列)。
  • 当“master”进程接收到数据,找到一个没有被充分利用(或空闲)的工作进程,并把数据传递给它的消息队列。当响应准备好时主进程由该进程发起消息通知,此时它通过连接传递响应。

这里最重要的是,有效负载工作是在一个固定的(通常配置的)数量的进程中进行,这独立于连接的数量。这样的好处是,有效负载可以是任意复杂,并且也不会影响网络IO(这是很好的等待时间)。而且还可能带来更高的安全性,因为只有一个进程在做网络IO。

优点:网络IO和有效载荷的工作分离非常清晰。

缺点:为在进程之间来回传递数据利用消息队列,而这根据不同协议的性质,可能成为瓶颈。

对称多处理事件驱动(SYMPED)模型

该SYMPED网络服务模型在许多方面是网络服务模型的“圣杯”,因为它就像有独立SPED“worker”进程的多个实例。它是通过由单一进程循环接收连接,然后将它们传递到工作进程得以实现,每一个都有一个像SPED的事件循环。这有一些非常有利的后果:

  • CPU都为生成的进程的准确数量而加载,这在每个时间点要么做网络IO或有效载荷处理。没有办法进一步提升CPU利用率。
  • 如果连接是独立的(例如使用HTTP),在工作进程之间则没有间通信。

事实上,这一点,也是最新版Nginx在做的;它们生产出少量工作进程,每个运行一个事件循环。为了使事情变得更好,大多数操作系统都提供了一个可由多个进程在一个独立的TCP端口侦听传入连接的功能,省去了为某个特定进程决定与网络连接工作的需要。如果你正在使用的应用程序可以通过这种方式来实现,我建议这样做。

优点:通过像SPED那样循环可控制的数量,严格提高CPU使用率天花板。

缺点:由于每个过程有一个像SPED那样的循环,如果有效载荷工作是不均匀的,等待时间可以再次变化,就像与正常SPED模型那样。

一些低级技巧

除了为您的应用选择最佳的构架模型外,这里还有可用于进一步提高网络代码性能的一些低级招数。下面简短列出了一些更有效的技巧:

  • 1、避免动态内存分配。作为一个解释,简单地看流行的内存分配代码 - 他们使用复杂的数据结构,互斥,并其中只是简单地这么多的代码(例如,jemalloc大概是450KiB左右的C代码!)。上面大部分的模型可用完全静态的(或预先分配)网络和/或仅在需要的地方改变线程之间所有权缓冲器来实现。

  • 2、使用操作系统可以提供最大值。大多数操作系统允许多个进程监听一个单一socket,并在套接字直到接收到第一个字节(或甚至是第一个完整的请求!)时连接将不被接受时那里实现功能收到。如果可以请使用sendfile()。

  • 3、了解您正在使用的网络协议!例如,禁用Nagle算法通常是有意义的,并且如果(再)连接率高禁止持续是有意义的。学习TCP拥塞控制算法,看看它是否有意义去尝试较一个新的。

在未来的博客文章,我可以更多地谈论这些,以及其他技术和实用的技巧。但现在,这里希望能为编写高性能网络代码提供关于的架构选择一个有用的信息基础,和它们的相对优势和劣势。


------------------------

  • 知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。
  • 本文翻译作者为:dogstar,发表于艾翻译(itran.cc);欢迎转载,但请注明出处,谢谢!

转载于:https://my.oschina.net/dogstar/blog/759120

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

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

相关文章

java mvc引擎_SpringMvc+JavaConfig+Idea 搭建项目

1.介绍之前搭建SpringMvc项目要配置一系列的配置文件&#xff0c;比如web.xml,applicationContext.xml,dispatcher.xml。Spring 3.X之后推出了基于JavaConfig方式以及注解的形式的配置。在一定程度上简化了Spring项目的配置。近几年特别火的SpringBoot&#xff0c;大大的简化了…

极域电子书包课堂管理系统_【君莲微讯】君莲学校(小学部)开展电子书包第13共同体数学研讨活动...

借 助 媒 体 技 术丰 富 图 形 认 识君莲学校(小学部)开展电子书包共同体 数学研讨活动 2020年12月2日下午&#xff0c;君莲学校(小学部)开展了以“借助媒体技术 丰富图形认识”为主题的闵行区电子书包第13共同体的数学研讨活动。共同体学校教师代表、学校电子书包项目组主管朱…

python批量改动指定文件夹文件名称

这小样例仅仅要是说明用python怎么批量改动指定文件夹的文件名称&#xff1a; 记得要把脚本跟改动的文件放在同一个文件夹下 #encoding:utf-8 import os import sys files os.listdir(D:\\1) #路径能够自己for name in files:a os.path.splitext(name)if a[1] .txt: #txt能够…

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具&#xff0c;可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率&#xff0c;内存使用&#xff0c;虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令&#xff0c;一个是Linux/Unix都支持&#xff0c;二是…

java 入门 博客园_javaweb入门

复习&#xff1a;css的常用样式&#xff1a;borderbackgroundpaddingmarginfloatposition 定位top left确定div在页面中的位置&#xff0c;这两个值可以为负数。cssdiv 布局方式cssdivtable 先由div划分大块儿&#xff0c;再由table进行整齐布局。下拉列表&#xff1a;层叠的布…

以ThreadStart方式实现多线程

3.1 使用ThreadStart委托 这里先以一个例子体现一下多线程带来的好处&#xff0c;首先在Message类中建立一个方法ShowMessage()&#xff0c;里面显示了当前运行线程的Id&#xff0c;并使用Thread.Sleep&#xff08;int ) 方法模拟部分工作。在main()中通过ThreadStart委托绑定M…

我的atom插件

atom插件实在是太多了&#xff0c;下面就说说我的插件 1.minimap 右边的小地图&#xff0c;和sublime里面的差不多&#xff1b; 2.open-in-browser 右击默认浏览器打开&#xff1b; 3.emmet 这个不用多说吧&#xff0c;html快速编译 4.git-plus 直接在atom提交代码&#xff0…

MonoRail - 简介 [基础知识篇]

MonoRail - 简介 起源 MonoRail是一个.NET的MVC web开发框架, 原名Castle On Rails, 是CastleProject的一个子项目. 作者hammett在使用过Ruby On Rails后, 觉得非常棒, 他希望在享受ror的开发模式的同时能使用大量现有的资源, 于是就用.NET写出了一个Castle On Rails. 后来ror那…

结对编程(黄金点游戏)

我扮演的角色是驾驶员 一、结对伙伴 领航员&#xff1a;赵峻 作业地址见我的博客。 二、代码地址 https://coding.net/u/k2048/p/huangjindian/git/blob/master/main.c 三、总结 1、个人总结 本次作业我扮演驾驶员&#xff0c;赵峻扮演领航员&#xff0c;我负责算法实现以及代码…

qtgl 鼠标平移 c++_罗技真爱粉的MX Master 3无线鼠标体验

​这是一篇关于罗技MX Master3的晒单&#xff0c;顺带也翻出我的库存清洁整理一下吧。在决定购买一款新鼠标的时候&#xff0c;我的第一目标其实是MX Vertical垂直鼠标&#xff0c;不过MX Vertical目前优势只在外形上&#xff0c;在MX系列中明显属于低配&#xff0c;自由滚轮、…

下载网页中的图片到本地

简单的一个下载如下 &#xff1a; string url "http://avatar.csdn.net/A/2/6/2_yefengzhixia.jpg";string filepath "D:\\pic.jpg";WebClient mywebclient new WebClient();mywebclient.DownloadFile(url, filepath);MessageBox.Show("OK");…

nacos linux启动_微服务系列之Nacos配置中心之一:Nacos介绍与安装

一、Nacos 介绍Nacos 是 Alibaba 公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置管理。英文全称 Dynamic Naming and Configuration Service&#xff0c;Na 为 Naming/NameServer 即注册中心&#xff0c;co 为 Configuration 即配置中心&#xff0c;Servic…

演练:在组件设计器中创建 Windows 服务应用程序

http://msdn.microsoft.com/zh-cn/library/zt39148a(vvs.80).aspx 演练&#xff1a;在组件设计器中创建 Windows 服务应用程序 .NET Framework 2.0其他版本5&#xff08;共 5&#xff09;对本文的评价是有帮助 - 评价此主题注意 Visual Studio 标准版中不提供“Windows 服务”模…

绝对震撼 7款HTML5动画应用及源码

除非特别声明&#xff0c;PHP100新闻均为原创或投稿报道&#xff0c;转载请注明作者及原文链接 原文地址&#xff1a; http://www.php100.com/html/it/mobile/2014/0702/7030.html [导读] 关于HTML5动画&#xff0c;我们已经分享太多了&#xff0c;当然也有很多利用纯CSS3实现的…

maven打包指定main函数

2019独角兽企业重金招聘Python工程师标准>>> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> …

简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

本文实例为大家分享了java版贪吃蛇小游戏的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下项目结构新建一个JFrame窗口,作为程序入口public class GameStart{public static void main(String[] args) {JFrame jFrame new JFrame();jFrame.setBounds(100,100,900,720…

java切入式编程显示屏_C语言嵌入式系统编程修炼之四:屏幕操作

C语言嵌入式系统编程修炼之四:屏幕操作作者:宋宝华 更新日期:2005-07-22汉字处理现在要解决的问题是&#xff0c;嵌入式系统中经常要使用的并非是完整的汉字库&#xff0c;往往只是需要提供数量有限的汉字供必要的显示功能。例如&#xff0c;一个微波炉的LCD上没有必要提供显…

算法之矩阵计算斐波那契数列

算法之矩阵计算斐波那契数列 本节内容 斐波那契介绍普通方式求解斐波那契矩阵概念矩阵求幂矩阵求解斐波那契1.斐波那契介绍 斐波那契数列有关十分明显的特点&#xff0c;那是&#xff1a;前面相邻两项之和&#xff0c;构成了后一项。即f(n)f(n-1)f(n-2),f(0)0,f(1)f(2)1,推导下…

SeekBar和RatingBar

1. SeekBar的主要属性 2. OnSeekBarChangeListener 3. RatingBar的主要属性 4. OnRatingBarChangeListener 1. SeekBar的主要属性 2. OnSeekBarChangeListener 1 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"2 xmlns:tools&qu…

用“Web的思想”做PC客户端

一直在想&#xff0c;用HTML搭建前端页面这么方便&#xff0c;而且效果这么炫&#xff0c;为什么在PC端的软件要如此麻烦呢&#xff1f;就连C#也是&#xff0c;更何况C了。 尽管C有DirectUI这样优秀的图形库&#xff0c;但是开发起来仍然非常吃力。C#的WPF虽然工具链完善&#…