首页 » PHP教程 » php线性并发技巧_高并发和高机能系统中进程线程协程队列若何调解的

php线性并发技巧_高并发和高机能系统中进程线程协程队列若何调解的

访客 2024-12-04 0

扫一扫用手机浏览

文章目录 [+]

end 结束 ,我理解正在码字中

下面别人总结,基本的解释,但是没说点子上。

php线性并发技巧_高并发和高机能系统中进程线程协程队列若何调解的

互联网运用系统开拓肯定常常会看到高并发和高性能这两个词,可谓是耳熟能详,而详细的含义和关系真的如你所想的,真正的理解了吗?

php线性并发技巧_高并发和高机能系统中进程线程协程队列若何调解的
(图片来自网络侵删)

这次,我也结合自己的理解,来跟大家分享一下。

先来看一个例子:

一个蓄池塘,是1m1m1m=1立方米大小,有一个出水口,出水口每秒钟流出0.1立方米,那么这个蓄池塘的并发量是1立方米,出水速率是0.1立方米/秒。

如果增加一个出水口,都是每秒钟流出0.1立方米,那么这个蓄池塘的并发量没变,但是出水速率变成了0.2立方米/秒。

同理,增大了出水口,蓄池塘的出水速率也变快了。

上面我们很随意马虎知道,并发量是一个容量的观点,性能便是出水速率,而且有下面这些结果。

1 增大蓄池塘的长宽高,可以增加并发能力。

2 出水口如果扩大了出口大小,则可以提高出水的速率,也便是性能提高了。

3 增加出水口的数量,则是增加了并行处理的能力,同样可以提高性能。

那么对照我们打算机中,我们的系统中,是怎么样的结果呢?

1 增加做事器的内存大小,可以增加并发量。
由于内存增加了,就可以开更多的进程,更多的线程,也可以扩大任务行列步队的大小。

2 提高cpu的主频速率,优化程序,可以提高性能。
cpu更快了,程序优化的更好了,处理单个任务的韶光也就更短了。

3 增加多核乃至分布式做事器数量,也可以提高性能,同时提高并发量。

如果只是性能提高了,并发量是否也能提高呢?

如果我们静态的理解并发量,那它是不会提高的。

而我更乐意动态的来理解并发量,即:单位韶光内可以进来的最大数量。

那么提高性能,是可以线性提高并发量的,由于单位韶光内,进来的同时也有出去。

接下来,再来详细的剖析下,上面的几种结果,是不是真的可以实现呢?是不是完备精确呢?

我们先来做一个假设,单个进程内存占用10M,单个线程内存占用2M,单个协程内存占用20K,行列步队任务内存占用2K,我们下面来看看内存与并发量的关系。

(详细的内存占用大小在不同的运用处景中会有很大的不同,以是这里只是为了方便打算而做的一个假设)

内存量 进程数 线程数 协程 行列步队任务

1G 100 500 50K 500K

2G 200 1000 100K 1000K

4G 400 2000 200K 2000K

8G 800 4000 400K 4000K

对应的几种运行模式

多进程: php fast-cgi

多线程: java web

协程: go

行列步队: nginx

从上面的结果中,我们可以很直不雅观的看出来,并发能力在不同的运行模式中的巨大差异。

多进程和多线程的模式,不仅是内存开销巨大,而且在数量不断增加的情形下,对CPU的压力也是非常巨大,这也是为什么这类系统在并发量大的情形下会很不稳定,乃至宕机。

上面假设中计算出来的数据,都是静态的容量,如果所有任务都不处理,那么肯定都是会很快就被撑爆。

以是要达到更高的并发量,就须要有更快的处理速率,即做好性能优化。

下面,再来做一个假设。

我们现在有一台做事器,配置是8核16G内存。

如果我们的运用是打算密集型,纯运算的系统,如:数据索引查询、排序等操作。

而且还要假设,这个运用在多核并走运算时不存在锁竞争的情形(只读)。

qps=1000ms/单个要求耗时8

如果单个要求(任务)耗时100ms,那么我们可以打算出来

qps=1000ms/100ms8=80个/秒

如果我们优化处理的算法,单个要求耗时降落到10ms,那么

qps=1000ms/10ms8=800个/秒

如果可以连续优化,将单个要求耗时降落到1ms,那么

qps就可以达到更高的8k。

上面的情形和优化的效果理解起来该当很随意马虎,由于对做事器资源的依赖更多是CPU的运算能力和数量。

【进程先容】

每一个运用运行起来都会有自己的进程,由于进程是系统资源分配的基本单位。

在线程涌现之前,进程也是CPU调度的基本单位。

每一个进程创建出来,都会分配三种基本的内存资源,分别是代码段、数据段和堆栈段。

代码段和数据段分别保存着运用的实行代码和全局变量、常量、静态变量,这些便是不会变革或者很少变革的内容,当然内存占用相对也会比较少。

而运用运行起来,须要的更多资源就会在堆栈中用到。

个中堆空间是存放各种变量数据的地方,内存大小也是可以动态调度的。

而栈空间是子任务(线程、协程)独立存放自己的数据地方,比如:函数调用、参数、返回值和局部变量。

这样一来,子任务(线程、协程)之间就可以独立运行,而且还可以共享堆空间中的变量数据。

【线程先容】

线程在新的操作系统中,也称为轻量级进程,由于现在的线程已经是CPU调度的基本单位了。

操作系统不仅仅坚持一个进程表,而且还会坚持一个线程表,这样操作系统就可以把线程作为调度单位。

线程是进程内创建,可以共享进程的资源,以是,线程自身独立的资源依赖就会少很多,由于只须要为每个线程分配独立的栈空间。

而线程的栈空间是固定大小的,如果程序比较繁芜,或者里面的数据量大,为了不涌现“栈空间不敷”的缺点,就必须把栈空间设置的足够大才行。

于是,线程是固定的栈空间S(足够大),统共运行多少线程T,占用总的栈空间就可以大略打算出来=TS。

这个资源占用量相对T个进程来说,还是少了很多的,毕竟线程是共享了进程的代码段、数据段和堆空间。

【协程先容】

协程是可以在运用态协作的程序,它的调度不是操作系统处理,而是运用系统自己来调度处理,也称为轻量级线程。

在操作系统可以独立调度线程之前,在线程还是作为运用的程序包,有运用程序自己调度和管理的时候,实在那种线程也就跟现在的协程是一个观点了。

以是,这里我们就不再讲以前的那种运用内的线程,只讲新的协程。

如果说到线程,便是新的可以被操作系统独立调度的线程。

协程作为运用系统内调度的子任务单元,当然也是会共享进程的各种资源,除了自己的栈空间(函数调用、参数、返回值、局部变量)。

而协程与线程紧张的差异有两个,最大的便是调度办法,线程是操作系统调度,协程是运用系统自己调度。

其余一个差异,协程的栈空间是可以动态调度的,这样空间利用率就可以更高,一个任务须要2K空间就分配2K内存,一个任务须要20M空间就分配20M,而不用担心栈空间不足或者空间摧残浪费蹂躏。

由于上面的两个缘故原由,协程的上风也就凸显出来。

1 协程可以更好的利用CPU,不用把CPU摧残浪费蹂躏在线程调度和高下文切换上。

2 协程可以更好的利用内存,不用全都分配一个偏大的空间,只须要分配须要的对应空间即可。

libco的特性

无需侵入业务逻辑,把多进程、多线程做事改造成协程做事,并发能力得到百倍提升;支持CGI框架,轻松构建web做事(New);支持gethostbyname、mysqlclient、ssl等常用第三库(New);可选的共享栈模式,单机轻松接入千万连接(New);完善简洁的协程编程接口类pthread接口设计,通过co_create、co_resume等大略清晰接口即可完成协程的创建与规复;__thread的协程私有变量、协程间通信的协程旗子暗记量co_signal (New);措辞级别的lambda实现,结合协程原地编写并实行后台异步任务 (New);基于epoll/kqueue实现的小而轻的网络框架,基于韶光轮盘实现的高性能定时器;

【行列步队先容】

这里的行列步队不是独立的行列步队做事,而只是运用中坚持数据的一个行列步队,很多时候会是一个数组或者链表。

行列步队里面保存的也不是一个子任务,而只是一个数据,详细这个数据拿出来之后要启动什么子任务,这个行列步队是不关心的。

行列步队只是一个缓冲带,把更多的独立数据先临时保持住,运用系统有多大的能力消化接管就从里面用多快的速率进行处理。

从上面可以看出,行列步队比协程还要大略,都没有所谓各自独立的子任务,也就没有了独立的栈空间。

以是,这样的简化,也就带来了更少的资源开销,更少的任务调度。

接下来,我们结合实际中的几种运行模式来先容下现状和发展。

【多进程:php fast-cgi】

php在利用fast-cgi之前,更多是多线程模式,为什么转而回到多进程模式呢?

多线程模式是为每个网络要求创建一个线程来处理这个要求,当要求实行结束,再销毁这个线程。

于是,当网站的要求量高的时候,意味侧重复的为这些要求创建和销毁线程,这个开销就变得比较大,效率也就低落了。

在多进程模式下,进程是复用的,不会反复的创建和销毁,以是就没有之前多线程模式那样大的资源摧残浪费蹂躏了。

当然,多进程的问题就像上面说到的,内存开销大,系统调度开销大,以是也就意味着并发量相对就会比较小。

以是,新的php swoole框架也把协程引入进来,同时把多路复用的epoll网络模型引入进来,这样就带来了很明显的好处。

1 协程占用内存小,可以同时坚持更多的并发要求。

2 epoll网络模型非壅塞而且系统开销少,可以更好的利用CPU资源,同时避免了网络IO壅塞影响整体的任务实行。

【多线程:java web】

java多线程的运行模式用到线程池的技能,并不是每个要求都会启动一个线程来处理,而是复用线程池中的线程,这样也就类似上面php fast-cgi模式,很好的避免了线程频繁创建和销毁所带来的损耗。

线程比进程更轻量,以是单个线程的内存占用会比单个进程少,但是由于线程栈空间固定,在一些个别要求中,数据量很大,也可能会不得已要设置较大的栈空间,这样一来,内存摧残浪费蹂躏也是会比较严重了。

在之前的文章《认识IO的问题才能更好的设计和开拓出高并发和高性能的系统》,也有提到,java中更好支持IO密集型的框架,可以用netty,同样是支持多路复用的epoll模型,也简化了自己去实现NIO的过程。

kotlin.corouties 理解一下,简化的JAVA,1.3版本会发布协程的正式线上支持。

【协程:go】

go原生的支持协程,并且有完善的协程调度器,让协程在开拓和运行时变得更加大略和高效。

作为新的开拓措辞,遍及还须要韶光,在网络编程的系统中,还是非常有竞争力的。

一步到位的支持高并发和高性能,说的太多就怕它骄傲了(站在巨人肩膀上,新思维、新技能)。

【行列步队:nginx】

nginx实际是一个master+多个worker,也算是多进程模式。
但是work是单线程的,却可以支持超高的网络并发量,这便是nginx内部实际便是一个网络事宜行列步队。

每个要求进来都是一个connection,然后这个connection就通过epoll_ctl注册到系统的网络IO事宜中,当connection的网络事宜准备好了才通过回调函数放到已就绪行列步队中。

而nginx便是epoll_wait不断的轮询这个就绪行列步队,然后再处理这里的事宜。

网络要求的处理又有很多的阶段,每个阶段又可以有多个nginx模块来处理,这些nginx模块便是各个真正的任务处理系统。

nginx除了反向代理以及作为静态WEB做事器,也可以作为运用做事器,比如利用ngx_lua模块,就可以对WEB要求做实时动态的处理,来完成一个动态做事。

这样一来,nginx把网络要求放到事宜行列步队中,ngx_lua利用协程把各个要求动态实行,也就可以高效的达到一个运用做事器的效果了,而且并发、性能也非常好。

【总结】

从上面几种模式中,我们都看到协程在新的框架、模块中用的越来越多,而且也确实能非常明显的提高系统的并发量。

标签:

相关文章

介绍白点控制之路,从原理到方法

白点,作为生活中常见的现象,无处不在。对于如何控制白点,许多人却感到困惑。本文将从原理出发,探讨白点的控制方法,并结合实际案例,为...

PHP教程 2025-01-03 阅读1 评论0

介绍直播王者,如何开启你的电竞直播之旅

随着电竞产业的蓬勃发展,越来越多的年轻人投身于电竞直播行业。王者荣耀作为一款备受欢迎的MOBA手游,吸引了大量玩家和观众。如何开启...

PHP教程 2025-01-03 阅读1 评论0