是啥限制一个web服务器的并发访问量

谢邀,首先并发度跟性能有联系但不完全一样,性能一般使用qps进行衡量,即每秒处理的请求次数。很容易想象如果程序性能很好,即使同时只能处理一个请求也可以有很高的qps。但一般来说每个请求总会因为资源固有的延迟而耽误一定时间,这个时候提高并发度就会提高一定的性能,但并发度高到一定程度之后再提升并发度并不会增加性能,反而会导致每个请求的延迟都变长,qps不再提升,这时候瓶颈往往出现在其他部分,因此许多Web框架使用线程池的模型,并不能支持非常多的并发数,但性能也不差。如果是有许多长连接的comet服务的话,并发度要求会比较高。否则的话盲目追求并发度并不是一个好的web服务器的优化方法。很多人觉得自己的Web服务器并发度不够,其实性能低下并不是并发度不够的问题。单纯说并发量的话,并发访问量主要受到以下因素的限制:1. 物理资源。主要是内存,每个同时进行的请求都要占用一部分内存,内存超过限度程序就会崩溃,除了扩展物理内存以外,优化每个请求占用的内存资源也很重要。但一般情况下总内存都不会是瓶颈。除了内存以外,CPU、网络带宽、磁盘IO等都会有影响,但主要影响总qps而不是最大并发量。2. 系统资源。主要是内核内存,文件号限制,conntrack表等。应用程序除了占用应用程序空间中的资源以外,一般还需要占用一些系统的资源,在Linux下主要表现为线程、文件号、conntrack表容量,在Windows下主要表现为句柄数量等,大部分最后都对应到操作系统内核使用的内存上。与用户空间不同,操作系统在内核态中往往受到更严格的内存空间限制,因此内核内存会比用户态的内存更宝贵。Linux操作系统对这些系统资源往往有一些限制,主要可以通过ulimit和系统参数进行配置,例如ulimit -n默认配置为1024,这个就会严重影响网络服务的并发量。线程也会占用比较多的内核态资源,因此高并发的系统往往不采用多线程(或者不采用单个线程处理单个请求的模型),而是使用多路转接(如select, epoll)的单线程或者有限数量的多线程的模型。3. 程序结构一般来说socket程序都会有一段是类似这样的:s = create_socket(...)s.bind(...)s.listen(256) # backlogwhile True: s1, addr = s.accept() handleRequest(s1)这段handleRequest如果发生阻塞,比如线程池或者队列已满,就会使整个服务的并发量受到限制。一般这个限制都是故意设计的,这样在服务器压力很大的时候不会发生并发量太大导致内存溢出、资源不足或者用户端IO超时等问题。一般会有相应的参数比如线程池大小、队列长度之类来控制。反过来如果完全不控制的,一般并发能力会很强,但也容易出现单个请求速度过慢之类的问题。有人以为listen的backlog参数会对并发度有影响,其实并没有特别大的影响。总结来说,要提高最大并发量:1. 确保足够大的内存2. 调整相应系统参数如ulimit, nf_conntrack, max.files等3. 调整线程池、队列长度等参数(如果有的话),或者使用没有相应限制的IO框架最后还是强调,最大并发量跟服务器性能其实是不同的,在优化服务器性能的过程中,这是一个比较次要的指标,要承受大量访问最主要还是提高qps。


    推荐阅读