这个问题太复杂,我2天时间也没想明白,这是我大体思路

  • 第一步知道并发(concurrency) vs 并行(parallelism)区别
  • 第2️⃣ 步 同步IO和异步IO的区别
  • 第3️⃣步 需要了解的是 进程 线程
  • 第四知道的 什么协程序
  • 第四liunx 如何调度的
  • 第五golang 调度实现
  • 第六FQA

系统最大支持多少进程,线程,协程

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

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


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

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

先来看一个例子:

一个蓄水池,是1m*1m*1m=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/100ms*8=80个/秒

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

qps=1000ms/10ms*8=800个/秒

如果可以继续优化,将单个请求耗时降低到1ms,那么

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

上面的情况和优化的效果理解起来应该很容易,因为对服务器资源的依赖更多是CPU的运算能力和数量。

【进程介绍】

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

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

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

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

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

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

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

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

【线程介绍】

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

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

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

而线程的栈空间是固定大小的,如果程序比较复杂,或者里面的数据量大,为了不出现“栈空间不足”的错误,就必须把栈空间设置的足够大才行。

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

这个资源占用量相对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利用协程把各个请求动态执行,也就可以高效的达到一个应用服务器的效果了,而且并发、性能也非常好。

【总结】

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

5000并发的qps是多少_高并发和高性能系统中进程、线程、协程、队列(如何调度的)...相关推荐

  1. 5000并发的qps是多少_高并发初体验记录-02

    前言 这半个多月完成了这次活动的业务代码开发和测试,至于性能调优对我而言近乎玄学.总结记录,以备参考.如有错误,欢迎指正.不过其实大佬不用浪费时间看这篇低质量的流水账了. 实测过后,一个月前老板给我说 ...

  2. 5000并发的qps是多少_高并发架构设计

    点击蓝字,关注我们 01 概述 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求. 高并发一方面可以提高资 ...

  3. 高并发内存占用持续下降_高并发性能调试经验分享

    引文 4月份的时候看到一道面试题,据说是腾讯校招面试官提的:在多线程和高并发环境下,如果有一个平均运行一百万次才出现一次的bug,你如何调试这个bug?知乎原贴地址如下:腾讯实习生面试,这两道题目该怎 ...

  4. 并发编程:进程,线程,协程,异步

    并发编程(不是并行)目前有四种方式:多进程.多线程.协程和异步. 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库 多线程编程python中有Th ...

  5. Python之进程+线程+协程(并发与并行、GIL锁、同步锁、死锁、递归锁)

    文章目录 一.并发与并行 二.同步与异步 三.线程锁 1.GIL全局解释器锁 2.同步锁 3.死锁 4.递归锁 在Python中GIL解释器锁.同步锁.死锁.递归锁都是什么?怎么这么多锁,它们都是用来 ...

  6. 进程 线程 协程_进程 线程 协程 管程 纤程 概念对比理解

    不知道是不是我自己本身就有那么一丝丝的密集恐惧,把这么一大堆看起来很相似很相关的概念放在一起,看起来是有点麻,捋一捋感觉舒服多了. 相关概念 任务.作业(Job,Task,Schedule) 在进程的 ...

  7. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之OS_Part_1整起(进程线程协程并发并行、进程线程切换进程间通信、死锁\进程调度策略、分段分页、交换空间、OS三大调度机制)

    PART0:OS,这货到底是个啥? OS,是个啥? OS的结构们: 存储器: 存储器的层次结构: 内存:我们的程序和数据都是存储在内存,我们的程序和数据都是存储在内存,每一个字节都对应一个内存地址.内 ...

  8. 并发编程:进程+线程+协程

    现代计算机系统是由一个或者多个处理器,主存,磁盘,打印机,键盘,鼠标显示器,网络接口以及各种其他输入 输出设备组成的复杂系统,每位程序员不可能掌握所有系统实现的细节,并且管理优化这些部件是一件挑战性极 ...

  9. python进程线程协程区别_进程和线程、协程的区别

    现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中有协程库gevent,py web框架tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区 ...

  10. 进程 线程 协程_进程,线程,协程那些事

    无论我们写出怎样的程序,最后都是由操作系统来运行我们的程序,而操作系统如何管理我们的程序,我们程序的数据如何保存和计算,这些都是操作系统需要处理的事情,我们只要将写好的程序交给操作系统就好. 虽然操作 ...

最新文章

  1. mysql 忽略语法错误_MYSQL语句中易忽略的语法错误 | 学步园
  2. 数据结构Stack:关系以及方法
  3. java代码。继承。。。很戳我的心啊。。不太懂。super的真正用法
  4. 【Android 逆向】整体加固脱壳 ( DEX 优化流程分析 | dvmDexFileOpenPartial | dexFileParse | 脱壳点 | 获取 dex 文件在内存中的首地址 )
  5. 写给java开发的运维笔记
  6. Visual C++——设置光标Cursor
  7. 在Windows平台如何选择C语言编译器?
  8. Java程序编译和运行的过程
  9. HURST 1116:选美大赛(LIS+路径输出)
  10. 王道考研 计算机网络19 传输层 传输层的寻址与端口 TCP UDP
  11. 有人问我,为什么1+1等于2
  12. oracle归档日志太多(ORA-00257: archiver error. Connect internal only, until freed)错误的处理方法
  13. Golang 须知知识点
  14. AWT_Swing_JPasswordField密码框(Java)
  15. Yii Framework2.0开发教程(4)在yii中定义全局变量
  16. linux 安裝 curl的 dev 包,R包:RCurl和curl包在Linux上安装失败
  17. 造假家族覆灭记:警方联合阿里斩断涉案三千万假耐克产销链
  18. java+poi在Excel中生成二维码
  19. 【Linux】动态防火墙,实现对攻击IP的动态拦截,一定程度上解决云服务器主机经常被境外IP尝试登录,屏蔽指定地区、国家的IP连接
  20. Python图像处理库PIL中图像格式转换(二)

热门文章

  1. R实践 第二篇:创建数据集
  2. Linux 内核版本号查看
  3. Java多线程之可见性与原子性——synchronized VS volatile
  4. 微软发布TypeScript用以改进JavaScript开发
  5. centos如何使用nomachine远程连接GNOME桌面(二)
  6. vim 配置文件 (未完待续)
  7. exawear能运行java_VirSCAN.org-多引擎在线病毒扫描网 v1.02,当前支持 47 款杀毒引擎...
  8. python标准库math中用来计算平方根的函数是_Python程序设计的复习题资料合集免费下载...
  9. ARM开发7.5.2 基础实训( 6 ) 4×4 矩阵键盘和 2 路 LED 显示系统( 2 )--LPC21XX
  10. mfc窗口右下角如何显示一个三角形图案_以C4D制作金属碳笼为例:安利一个友好的三维制图软件...