阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

高并发Web服务的演变——节约系统内存和CPU

478次阅读
没有评论

共计 9835 个字符,预计需要花费 25 分钟才能阅读完成。

一、越来越多的并发连接数

现在的 Web 系统面对的并发连接数在近几年呈现指数增长,高并发成为了一种常态,给 Web 系统带来不小的挑战。以最简单粗暴的方式解决,就是增加 Web 系统的机器和升级硬件配置。虽然现在的硬件越来越便宜,但是一味地通过增加机器来解决并发量的增长,成本是非常高昂的。结合技术优化方案,才是更有效的解决方法。

并发连接数为什么呈指数增长?实际上,从这几年的用户基数上看,这个数量并没有出现指数增长,因此它并非主要原因。主要原因,还是 web 变得更复杂,交互更丰富所导致的。

高并发 Web 服务的演变——节约系统内存和 CPU

1. 页面元素增多,交互复杂

Web 页面元素越来越多,更为丰富。更多的资源元素,意味着更多的下载请求。Web 系统的交互越来越复杂,交互场景和次数也大幅增加。以“www.qq.com”的首页为例子,刷新一次,大概会有 244 个请求。并且,在页面打开完成之后,还会有一些定时的查询或者上报请求持续运作。

高并发 Web 服务的演变——节约系统内存和 CPU 

目前的 Http 请求,为了减少反复的创建和销毁连接行为,通常都建立长连接(Connection keep-alive)。一经建立,这个连接会被保持住一段时间,被后续请求复用。然而,它也带来了另一个新的问题,连接的保持是会占用 Web 系统服务端资源的,如果不充分使用这个连接,会导致资源浪费。长连接被创建后,首批资源传输完毕,之后几乎没有数据交互,一直到超时时间,才会自动释放长连接占据的系统资源。

高并发 Web 服务的演变——节约系统内存和 CPU 

除此之外,还有一些 Web 需求本身就需要长期保持连接的,例如 Web socket。

2. 主流的本浏览器的连接数在增加

面对越来越丰富的 Web 资源,主流浏览器并发连接数也在增加,同一个域下,早期的浏览器一般只有 1 - 2 个下载连接,而目前的主流浏览器通常在 2 - 6 个。增加浏览器并发连接数目,在需要下载资源比较多的场景下,可以加快页面的加载速度。更多的连接对浏览器加载页面元素是有好处的,在某些连接遭遇“网络阻塞”的情况下,其他正常的下载连接可以继续工作。

这样自然无形增加了 Web 系统后端的压力,更多的下载连接意味着占据了更多的 Web 服务器的资源。而在用户访问高峰期,自热而然就形成了“高并发”场景。这些连接和请求,占据了服务器的大量 CPU 和内存等资源。尤其在资源数目超过 100+ 的网站页面中,使用更多的下载连接,非常有必要。

 

二、Web 前端优化,降低服务端压力

在缓解“高并发”的压力,需要前端和后端的共同配合优化,才能达到最大效果。在用户第一线的 Web 前端,可以起到减少或者减轻 Http 请求的效果。

1. 减少 Web 请求

常用的实现方法是通过 Http 协议头中的 expire 或 max-age 来控制,将静态内容放入浏览器的本地缓存,在之后的一段时间里,不再请求 Web 服务器,直接使用本地资源。还有 HTML5 中的本地存储技术(LocalStorage),也被作为一个强大的数据本地缓存。

高并发 Web 服务的演变——节约系统内存和 CPU 

这种方案缓存后,根本不发送请求到 Web 服务器,大幅降低服务器压力,也带来了良好的用户体验。但是,这种方案,对首次访问的用户无效,同时,也影响部分 Web 资源的实时性。

2. 减轻 Web 请求

浏览器的本地缓存是存在过期时间的,一旦过期,就必须重新向服务器请求。这个时候,会有两种情形:

(1)服务器的资源内容没有更新,浏览器请求 Web 资源,服务器回复“可以继续使用本地缓存”。(发生通信,但是 Web 服务器只需要做简单“回复”)

(2)服务器的文件或者内容已经更新,浏览器请求 Web 资源,Web 服务器通过网络传输新的资源内容。(发生通信,Web 服务器需要完成复杂的传输工作)

这里的协商方式是通过 Http 协议的 Last-Modified 或 Etag 来控制,这个时候请求服务器,如果是内容没有发生变更的情况,服务器会返回 304 Not Modified。这样的话,就不需要每次请求 Web 服务器都做复杂的传输完整数据文件的工作,只要简单的 http 应答就可以达到相同的效果。

高并发 Web 服务的演变——节约系统内存和 CPU 

虽然上述请求,起到“减轻”Web 服务器的压力,但是连接仍然被建立,请求也发生了。

3. 合并页面请求

如果是比较老一些的 Web 开发者,应该会更有印象,在 ajax 盛行之前。页面大部分都是直接输出的,并没有这么多的 ajax 请求,Web 后端将页面内容完全拼凑好了,再返回给前端。那个时候,页面静态化,是一个挺广泛的优化方式。后来,被交互更友好的 ajax 渐渐替代了,一个页面的请求也变得越来越多。

由于移动端的网络(2G/3G)比起 PC 宽带差很多,并且部分手机配置比较低,面对一个超过 100 个请求的网页,加载的速度会缓慢很多。于是,优化的方向又重新回到合并页面元素,减少请求数量:

(1)合并 HTML 展示内容。将 CSS 和 JS 直接嵌入到 HTML 页面内,不通过连接的方式引入。

(2)Ajax 动态内容合并请求。对于动态内容,将 10 次 Ajax 请求合并为 1 次的批量信息查询。

(3)小图片合并,通过 CSS 的偏移量技术 Sprites,将很多小图片合并为一张。这个优化方式,在 PC 端的 Web 优化中,也非常常见。

高并发 Web 服务的演变——节约系统内存和 CPU 

合并请求,减少了传输数据的次数,也就是相当于将它们从一个一个地请求,变为一次的“批量”请求。上述优化方法,到达“减轻”Web 服务器压力的目的,减少了需要建立的连接。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2015-04/116369p2.htm

三、节约 Web 服务端的内存

前端的优化完成,我们就需要着眼于 Web 服务端本身。内存是 Web 服务器非常重要的资源,更多的内存通常意味着可以同时放入更多的工作任务。就 Web 服务占用内存而言,可以粗略划分:

(1)用来维持连接的基本内存,进程初始化时,会载入一些基础模块到内存。

(2)被传输的数据内容载入到各个缓冲区,占据的内存。

(3)程序执行过程中,申请和使用的内存。

如果维持一个连接,能够尽可能少占用内存,那么我们就可以维持更多的并发连接,从而让 Web 服务器支持更多的并发连接数。

Apache(httpd)是一个成熟并且古老的 Web 服务,而 Apache 的发展和演变,一直在追求做到这一点,它试图不断减少服务占据的内存,以支持更大的并发量。以 Apache 的工作模式的演变为视角,我们一起来看看,它们是如何优化内存的问题的。

1. prefork MPM,多进程工作模式

prefork 是 Apache 最成熟和稳定的工作模式,即使是现在,仍然被广泛使用。主进程生成后,它先完成基础的初始化工作,然后,通过 fork 预先产生一批的子进程(子进程会复制父进程的内存空间,不需要再做基础的初始化工作)。然后等待服务,之所以预先生成,是为了减少频繁创建和销毁进程的开销。多进程的好处,是进程之间的内存数据不会相互干扰,同时,某个进程异常终止也不会影响其他进程。但是,就内存而言,每个 httpd 子进程占用了很多的内存,因为子进程的内存数据是复制父进程的。我们可以粗略认为,这里存在大量的“重复数据”被放在内存中。最终,导致我们能够生成的子进程最大数量是很有限。在面对高并发时,因为有不少 Keep-alive 的长连接,将这些子进程“霸占”住,很可能导致可用子进程耗尽。因此,prefork 并不太适合高并发场景。

高并发 Web 服务的演变——节约系统内存和 CPU 

  • 优点:成熟稳定,兼容所有新老模块。同时,不需要担心线程安全的问题。(例如,我们常用的 mod_php,将 PHP 编译为 Apache 的子模块,就不需要支持线程安全)
  • 缺点:一个服务进程占用很多内存。

2. worker MPM,多进程和多线程的混合模式

worker 模式比起 prefork,是使用了多进程和多线程的混合模式。它也预先 fork 了几个子进程(数量很少),然后每个子进程创建一些线程(其中包括一个监听线程)。每个请求过来,会被分配到 1 个线程来服务。线程比起进程会更轻量,因为线程通常会共享父进程的内存空间,因此,内存的占用会减少一些。在高并发的场景下,因为比起 prefork 更省内存,因此会有更多的可用线程。

高并发 Web 服务的演变——节约系统内存和 CPU 

但是,它并没有解决 Keep-alive 的长连接“霸占”线程的问题,只是对象变成了比较轻量的线程。

有些人会觉得奇怪,那么这里为什么不完全使用多线程呢,还要引入多进程?因为还需要考虑稳定性,如果一个线程挂了,会导致同一个进程下其他正常的子线程都挂了。如果全部采用多线程,某个线程挂掉,就导致整个 Apache 服务“全军覆没”。而目前的工作模式,受影响的只是 Apache 的一部分服务,而不是整个服务。

线程共享父进程的内存空间,减少了内存的占用,却又引起了新的问题。就是“线程安全”,多个线程修改共享资源导致的“竞争行为”,又强迫我们所使用的模块必须支持“线程安全”。因此,它有一定程度上增加 Web 服务的不稳定性。例如,mod_php 所使用的 PHP 拓展,也同样需要支持“线程安全”,否则,不能在该模式下使用。

  • 优点:占据更少的内存,高并发下表现更优秀。
  • 缺点:必须考虑线程安全的问题,同时锁的引入又增加了 CPU 的开销。

3. event MPM,多进程和多线程的混合模式,引入 Epoll

这个是 Apache 中比较新的模式,在现在的版本(Apache 2.4.10)已经是稳定可用的模式。它和 worker 模式很像,最大的区别在于,它解决了 keep-alive 场景下,长期被占用的线程的资源浪费问题。event MPM 中,会有一个专门的线程来管理这些 keep-alive 类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。它减少了“占据”连接而又不使用的资源浪费,增强了高并发场景下的请求处理能力。因为减少了“闲等”的线程,线程的数量减少,同等场景下,内存占用会下降一些。

高并发 Web 服务的演变——节约系统内存和 CPU 

event MPM 在遇到某些不兼容的模块时,会失效,将会回退到 worker 模式,一个工作线程处理一个请求。新版 Apache 官方自带的模块,全部是支持 event MPM 的。注意一点,event MPM 需要 Linux 系统(Linux 2.6+)对 EPoll 的支持,才能启用。Apache 的三种模式中在真实应用场景中,event MPM 是最节约内存的。

4. 使用比较轻量的 Nginx 作为 Web 服务器

虽然 Apache 的不断优化,减少了内存占用,从而增加了处理高并发的能力。但是,正如前面所说,Apache 是一个古老而成熟的 Web 服务,同时,集成很多稳定的模块,是一个比较重的 Web 服务。Nginx 是个比较轻量的 Web 服务,占据的内存天然就少于 Apache。而且,Nginx 通过一个进程来服务于 N 个连接。所使用的方式,并不是 Apache 的增加进程 / 线程来支持更多的连接。对于 Nginx 来说,它少创建了大量的进程 / 线程,减少了很多内存的开销。

高并发 Web 服务的演变——节约系统内存和 CPU 

静态文件的 QPS 性能压测结果,Nginx 性能大概 3 倍于 Apache 对静态文件的处理。PHP 等动态文件的 QPS,Nginx 的做法通常是通过 FastCGI 的方式和 PHP-FPM 通信的方式完成,PHP 作为一个与之无关的外部服务存在。而 Apache 通常将 PHP 编译为自己的子模块(新版的 Apache 也支持 FastCGI)。PHP 动态文件,Nginx 的表现略逊于 Apache。

5. sendfile 节约内存

Apache、Nginx 等不少 Web 服务,都带有 sendfile 支持的。sendfile 可以减少数据到“用户态内存空间”(用户缓冲区)的拷贝,进而减少内存的占用。当然,很多同学第一个反应当然是问 Why?为了尽可能清楚讲述这个原理,我们就先回 Linux 内核态和用户态的存储空间的交互。

一般情况下,用户态(也就是我们的程序所在的内存空间)是不会直接读写或者操作各种设备(磁盘、网络、终端等),中间通常用内核作为“中间人”,来完成对设备的操作或者读写。

以最简单的磁盘读写例子,从磁盘中读取 A 文件,写入到 B 文件。A 文件数据是从磁盘开始,然后载入到“内核缓冲区”,然后再拷贝到“用户缓冲区”,我们才可以对数据进行处理。写入的时候,也同理,从“用户态缓冲区”载入到“内核缓冲区”,最后写入到磁盘 B 文件。

高并发 Web 服务的演变——节约系统内存和 CPU 

这样写文件很累吧,于是有人觉得这里可以跳过“用户缓冲区”的拷贝。其实,这就是 MMP(Memory-Mapping,内存映射)的实现,建立一个磁盘空间和内存的直接映射,数据不再复制到“用户态缓冲区”,而是返回一个指向内存空间的指针。于是,我们之前的读写文件例子,就会变成,A 文件数据从磁盘载入到“内核缓冲区”,然后从“内核缓冲区”复制到 B 文件的“内核缓冲区”,B 文件再从”内核缓冲区“写回到磁盘中。这个过程,减少了一次内存拷贝,同时也少内存占用。

高并发 Web 服务的演变——节约系统内存和 CPU 

好了,回到 sendfile 的话题上来,简单的说,sendfile 的做法和 MMP 类似,就是减少数据从”内核态缓冲区“到”用户态缓冲区“的内存拷贝。

默认的磁盘文件读取,到传输给 socket,流程(不使用 sendfile)是:

高并发 Web 服务的演变——节约系统内存和 CPU 

使用 sendfile 之后:

高并发 Web 服务的演变——节约系统内存和 CPU 

这种方式,不仅节省了内存,而且还有 CPU 的开销。

一、越来越多的并发连接数

现在的 Web 系统面对的并发连接数在近几年呈现指数增长,高并发成为了一种常态,给 Web 系统带来不小的挑战。以最简单粗暴的方式解决,就是增加 Web 系统的机器和升级硬件配置。虽然现在的硬件越来越便宜,但是一味地通过增加机器来解决并发量的增长,成本是非常高昂的。结合技术优化方案,才是更有效的解决方法。

并发连接数为什么呈指数增长?实际上,从这几年的用户基数上看,这个数量并没有出现指数增长,因此它并非主要原因。主要原因,还是 web 变得更复杂,交互更丰富所导致的。

高并发 Web 服务的演变——节约系统内存和 CPU

1. 页面元素增多,交互复杂

Web 页面元素越来越多,更为丰富。更多的资源元素,意味着更多的下载请求。Web 系统的交互越来越复杂,交互场景和次数也大幅增加。以“www.qq.com”的首页为例子,刷新一次,大概会有 244 个请求。并且,在页面打开完成之后,还会有一些定时的查询或者上报请求持续运作。

高并发 Web 服务的演变——节约系统内存和 CPU 

目前的 Http 请求,为了减少反复的创建和销毁连接行为,通常都建立长连接(Connection keep-alive)。一经建立,这个连接会被保持住一段时间,被后续请求复用。然而,它也带来了另一个新的问题,连接的保持是会占用 Web 系统服务端资源的,如果不充分使用这个连接,会导致资源浪费。长连接被创建后,首批资源传输完毕,之后几乎没有数据交互,一直到超时时间,才会自动释放长连接占据的系统资源。

高并发 Web 服务的演变——节约系统内存和 CPU 

除此之外,还有一些 Web 需求本身就需要长期保持连接的,例如 Web socket。

2. 主流的本浏览器的连接数在增加

面对越来越丰富的 Web 资源,主流浏览器并发连接数也在增加,同一个域下,早期的浏览器一般只有 1 - 2 个下载连接,而目前的主流浏览器通常在 2 - 6 个。增加浏览器并发连接数目,在需要下载资源比较多的场景下,可以加快页面的加载速度。更多的连接对浏览器加载页面元素是有好处的,在某些连接遭遇“网络阻塞”的情况下,其他正常的下载连接可以继续工作。

这样自然无形增加了 Web 系统后端的压力,更多的下载连接意味着占据了更多的 Web 服务器的资源。而在用户访问高峰期,自热而然就形成了“高并发”场景。这些连接和请求,占据了服务器的大量 CPU 和内存等资源。尤其在资源数目超过 100+ 的网站页面中,使用更多的下载连接,非常有必要。

 

二、Web 前端优化,降低服务端压力

在缓解“高并发”的压力,需要前端和后端的共同配合优化,才能达到最大效果。在用户第一线的 Web 前端,可以起到减少或者减轻 Http 请求的效果。

1. 减少 Web 请求

常用的实现方法是通过 Http 协议头中的 expire 或 max-age 来控制,将静态内容放入浏览器的本地缓存,在之后的一段时间里,不再请求 Web 服务器,直接使用本地资源。还有 HTML5 中的本地存储技术(LocalStorage),也被作为一个强大的数据本地缓存。

高并发 Web 服务的演变——节约系统内存和 CPU 

这种方案缓存后,根本不发送请求到 Web 服务器,大幅降低服务器压力,也带来了良好的用户体验。但是,这种方案,对首次访问的用户无效,同时,也影响部分 Web 资源的实时性。

2. 减轻 Web 请求

浏览器的本地缓存是存在过期时间的,一旦过期,就必须重新向服务器请求。这个时候,会有两种情形:

(1)服务器的资源内容没有更新,浏览器请求 Web 资源,服务器回复“可以继续使用本地缓存”。(发生通信,但是 Web 服务器只需要做简单“回复”)

(2)服务器的文件或者内容已经更新,浏览器请求 Web 资源,Web 服务器通过网络传输新的资源内容。(发生通信,Web 服务器需要完成复杂的传输工作)

这里的协商方式是通过 Http 协议的 Last-Modified 或 Etag 来控制,这个时候请求服务器,如果是内容没有发生变更的情况,服务器会返回 304 Not Modified。这样的话,就不需要每次请求 Web 服务器都做复杂的传输完整数据文件的工作,只要简单的 http 应答就可以达到相同的效果。

高并发 Web 服务的演变——节约系统内存和 CPU 

虽然上述请求,起到“减轻”Web 服务器的压力,但是连接仍然被建立,请求也发生了。

3. 合并页面请求

如果是比较老一些的 Web 开发者,应该会更有印象,在 ajax 盛行之前。页面大部分都是直接输出的,并没有这么多的 ajax 请求,Web 后端将页面内容完全拼凑好了,再返回给前端。那个时候,页面静态化,是一个挺广泛的优化方式。后来,被交互更友好的 ajax 渐渐替代了,一个页面的请求也变得越来越多。

由于移动端的网络(2G/3G)比起 PC 宽带差很多,并且部分手机配置比较低,面对一个超过 100 个请求的网页,加载的速度会缓慢很多。于是,优化的方向又重新回到合并页面元素,减少请求数量:

(1)合并 HTML 展示内容。将 CSS 和 JS 直接嵌入到 HTML 页面内,不通过连接的方式引入。

(2)Ajax 动态内容合并请求。对于动态内容,将 10 次 Ajax 请求合并为 1 次的批量信息查询。

(3)小图片合并,通过 CSS 的偏移量技术 Sprites,将很多小图片合并为一张。这个优化方式,在 PC 端的 Web 优化中,也非常常见。

高并发 Web 服务的演变——节约系统内存和 CPU 

合并请求,减少了传输数据的次数,也就是相当于将它们从一个一个地请求,变为一次的“批量”请求。上述优化方法,到达“减轻”Web 服务器压力的目的,减少了需要建立的连接。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2015-04/116369p2.htm

四、节约 Web 服务器的 CPU

对 Web 服务器而言,CPU 是另一个非常核心的系统资源。虽然一般情况下,我们认为业务程序的执行消耗了我们主要 CPU。但是,就 Web 服务程序而言,多线程 / 多进程的上下文切换,也是比较消耗 CPU 资源的。一个进程 / 线程通常不能长期占有 CPU,当发生阻塞或者时间片用完,就无法继续占用 CPU,这个时候,就会发生上下文切换,CPU 时间片从老进程 / 线程切换到新的。除此之外,在并发连接数目很高的场景下,对这些用户建立的连接(socket 文件描述符)状态的轮询和检测,也是比较消耗 CPU 的。

而 Apache 和 Nginx 的发展和演变,也在努力减少 CPU 开销。

1. Select/Poll(Apache 早期版本的 I / O 多路复用)

通常,Web 服务都要维护很多个和用户通信的 socket 文件描述符,I/ O 多路复用,其实就是为了方便对这些文件描述符的管理和检测。Apache 早期版本,是使用 select 的模式,简单的说,就是将这些我们关注的 socket 文件描述符交给内核,让内核告诉我们,那些描述符可操作。Poll 与 select 原理基本相同,因此放在一起,它们之间的区别,就不赘叙了哈。

select/poll 返回的是一个我们之前提交的文件描述符集合(内核将其中可读、可写或者异常状态的 socket 文件描述符的标识位修改了),我们需要通过轮询检查才能获得我们可以操作的文件描述符。在这个过程中,不断重复执行。在实际应用场景中,大部分被我们监控的 socket 文件描述符,都是”空闲的“,也就是说,不能操作。我们对整个集合轮询,就是为了找了少部分我们可以操作的 socket 文件描述符。于是,当我们监控的 socket 文件描述符越多(用户并发连接数越来越多),这个轮询工作,也就越来越沉重,进而导致增大了 CPU 的开销。

高并发 Web 服务的演变——节约系统内存和 CPU 

如果我们监控的 socket 文件描述符,几乎都是”活跃的“,反而使用这种模式更合适一点。

2. Epoll(新版的 Apache 的 event MPM,Nginx 等支持)

Epoll 是 Linux2.6 开始正式支持的 I / O 多路复用,我们可以理解为它是对 select/poll 的改进。首先,我们同样将我们关注的 socket 文件描述符集合告诉给内核,同时,给它们注册”回调函数“,如果某个 socket 文件准备好了,就通过回调函数通知我们。于是,我们就不需要专门去轮询整个全量的 socket 文件描述符集合,直接可以得到已经可操作的 socket 文件描述符。那么,那些大部分”空闲“的描述符,我们就不遍历了。即使我们监控的 socket 文件描述越来越多,我们轮询的也只是”活跃可操作“的 socket 文件描述符。

高并发 Web 服务的演变——节约系统内存和 CPU 

其实,有一种极端点的场景,就是我们全部文件描述符几乎都是”活跃“的,这样反而导致了大量回调函数的执行,又增加了 CPU 的开销。但是,就 Web 服务的真实场景,绝大部分时候,都是连接集合中都存在很多”空闲“连接。

3. 线程 / 进程的创建销毁和上下文切换

通常,Apache 某一个时间内,是一个进程 / 线程服务于一个连接。于是,Apache 就有很多的进程 / 线程,服务于很多的连接。Web 服务在高峰期,会建立很多的进程 / 线程,也就带来很多的上下文切换开销。而 Nginx,它通常只有 1 个 master 主进程和几个 worker 子进程,然后,1 个 worker 进程服务很多个连接,进而节省了 CPU 的上下文切换开销。

高并发 Web 服务的演变——节约系统内存和 CPU 

两种模式虽然不同,但实际上不能直接出分好坏,综合来说,各有各自的优势,就不妄议了哈。

4. 多线程下的锁对 CPU 的开销

Apache 中的 worker 和 event 模式,都有采用多线程。多线程因为共享父进程的内存空间,在访问共享数据的时候,就会产生竞争,也就是线程安全问题。因此通常会引入锁(Linux 下比较常用的线程相关的锁有互斥量 metux,读写锁 rwlock 等),成功获取锁的线程可以继续执行,获取失败的通常选择阻塞等待。引入锁的机制,程序的复杂度往往增加不少,同时还有线程“死锁”或者“饿死”的风险(多进程在访问进程间共享资源的时候,也有同样的问题)。

死锁现象(两个线程彼此锁住对方想要获取的资源,相互阻塞等待,永远无法达不到满足条件):

高并发 Web 服务的演变——节约系统内存和 CPU 

饿死现象(某个线程,一直获取不到它想要锁资源,永远无法执行下一步):

高并发 Web 服务的演变——节约系统内存和 CPU 

为了避免这些锁导致的问题,就不得不加大程序的复杂度,解决方案一般有:

(1)对资源的加锁,根据约定好的顺序,大家都先对共享资源 X 加锁,加锁成功之后才能加锁共享资源 Y。

(2)如果线程占有资源 X,却加锁资源 Y 失败,则放弃加锁,同时也释放掉之前占有的资源 X。

在使用 PHP 的时候,在 Apache 的 worker 和 event 模式下,也必须兼容线程安全。通常,新版本的 PHP 官方库是没有线程安全方面的问题,需要关注的是第三方扩展。PHP 实现线程安全,不是通过锁的方式实现的。而是为每个线程独立申请一份全局变量的副本,相当于线程的私人内存空间,但是这样做相对消耗多一些内存。不过,这样的好处,是不需要引入复杂的锁机制实现,也避免了锁机制对 CPU 的开销。

这里顺便提到一下,经常和 Nginx 搭配工作的 PHP-FPM(FastCGI)使用的是多进程,因此不会有线程安全的问题。

高并发 Web 服务的演变——节约系统内存和 CPU 

五、小结

可能有些同学看完之后,会得出结论,Nginx+PHP-FPM 的工作方式,似乎是最节省系统资源的 Web 系统工作方式。某种程度上说,的确是可以这么说的,但是 Web 系统的搭建,需要从实际业务应用的角度出发,具体问题需要具体分析,寻求最合适的技术方案。

Web 服务的不断演变和发展,努力地追求用尽可能少的系统资源,来支撑更多的用户请求,这是一条波澜壮阔的前进之路。这些技术方案,汇聚了很多值得学习和借鉴的解决问题的思路。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2015-04/116369.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-20发表,共计9835字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7987890
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
150元打造低成本NAS小钢炮,捡一块3865U工控板

150元打造低成本NAS小钢炮,捡一块3865U工控板

150 元打造低成本 NAS 小钢炮,捡一块 3865U 工控板 一块二手的熊猫 B3 工控板 3865U,搭...
2025年11月28日-Cloudflare史诗级事故:一次配置失误,引爆全球宕机

2025年11月28日-Cloudflare史诗级事故:一次配置失误,引爆全球宕机

2025 年 11 月 28 日 -Cloudflare 史诗级事故: 一次配置失误,引爆全球宕机 前言 继今...
你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

  三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Andr...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

仅2MB大小!开源硬件监控工具:Win11 无缝适配,CPU、GPU、网速全维度掌控

还在忍受动辄数百兆的“全家桶”监控软件?后台偷占资源、界面杂乱冗余,想查个 CPU 温度都要层层点选? 今天给...
Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集 在云原生体系中,Prometheus 已成为最主流的监控与报警...
开发者福利:免费 .frii.site 子域名,一分钟申请即用

开发者福利:免费 .frii.site 子域名,一分钟申请即用

  开发者福利:免费 .frii.site 子域名,一分钟申请即用 前言 在学习 Web 开发、部署...
星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

  星哥带你玩飞牛 NAS-16:不再错过公众号更新,飞牛 NAS 搭建 RSS 对于经常关注多个微...
自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个AI智能体—跟创业大佬对话

自己手撸一个 AI 智能体 — 跟创业大佬对话 前言 智能体(Agent)已经成为创业者和技术人绕...