服务器的并发处理能力是多少?有没有什么方法可以衡量服务器的并发处理能力1、吞吐率吞吐率是服务器在单位时间内处理***请求的数量,单位是req/s。从服务端来看,实际并发用户数可以理解为服务端当前维护的代表不同用户的文件描述符总数,即并发连接数。服务器一般会限制同时服务的最大用户数,比如apache的MaxClients参数。让我们在这里更深入。对于服务器来说,服务器希望支持高吞吐率。对于用户来说,用户只希望等待最短的时间。显然,双方无法满足,所以双方利益的平衡点就是我们希望的***并发用户数。2、有一个压力测试的原则,首先要明确。如果100个用户同时向服务器发出10次请求,1个用户连续向服务器发出1000次请求,服务器的压力是否一样?其实是不一样的,因为对于每个用户来说,连续发送请求意味着发送一个请求,在发送下一个请求之前收到响应数据。这样,对于一个用户连续向服务器发出1000次请求,服务器网卡的接收缓冲区中任何时候都只有一个请求,而对于100个用户同时向服务器发出10次请求,服务器网卡的接收缓冲区最多有100个请求。显然,此时服务器的压力更大。压测前提考虑的条件并发用户数:指某一时刻同时向服务器发送请求的用户总数(HttpWatch)请求总数请求资源描述请求等待时间(用户等待时间)平均waitingtimeofuserrequestsServeraveragerequestprocessingTime硬件环境压力测试关注的时间分为以下两种:本地PC不计入这里)和服务器平均请求处理时间平均用户请求等待时间主要用来衡量服务器在一定的并发用户数下单个用户的服务质量;服务器的平均请求处理时间是吞吐率的倒数。一般来说,用户平均请求等待时间=服务器平均请求处理时间*并发用户数如何提高服务器的并发处理能力1.提高CPU的并发计算能力服务器可以处理多个请求的原因同时是操作系统通过多执行流系统的设计,允许多个任务轮流使用系统资源。这些资源包括CPU、内存和I/O。这里的I/O主要是指磁盘I/O和网络I/O。多进程&多线程多执行流程的一般实现是一个进程。多进程的好处可以反过来利用CPU时间,重叠使用CPU计算和IO操作。这里的IO主要是指磁盘IO和网络IO,相对于CPU来说,慢得可怜。实际上,大多数进程主要将时间花在I/O操作上。现代计算机的DMA技术可以避免CPU参与整个I/O操作过程。例如,一个进程进行系统调用,导致CPU向网卡或磁盘等I/O设备发出指令,然后进程被挂起,释放CPU资源,等待I/O设备执行完它之后工作,它通过中断通知进程它再次准备就绪。对于单个任务来说,大部分时间CPU是空闲的,此时多进程的作用就显得尤为重要。多进程不仅可以提高CPU的并发性。其优越性还体现在独立的内存地址空间和生命周期带来的稳定性和健壮性,一个进程的崩溃不会影响到另一个进程。但该进程也有以下缺点:fork()系统调用开销大??:prefork进程间调度和上下文切换开销:减少大量进程的内存重复:共享内存IPC编程相对麻烦减少进程切换当硬件上下文在频繁加载和移除时,消耗的时间是非常可观的。Nmon工具可以用来监控服务器每秒的上下文切换次数。为了尽量减少上下文切换次数,最简单的方法就是减少进程数,尽可能使用线程,并结合其他I/O模型设计并发策略。也可以考虑使用进程绑定CPU技术来提高CPU缓存的效率。如果进程不停地在每个CPU上切换,旧的CPU缓存就会失效。减少不必要的锁的使用当服务器处理大量并发请求时,多个请求处理任务时存在一些资源抢占竞争。这时候一般会使用“锁”机制来控制资源的占用。当任务占用资源时,我们锁定资源,此时其他任务正在等待锁的释放。这种现象称为锁竞争。通过锁竞争的本质,我们必须认识到应该尽量减少并发请求共享资源的竞争。例如,在允许的情况下关闭服务器访问日志,可以大大减少等待锁时的延迟时间。尽量减少无辜的等待时间。这里说一下无锁编程,即内核完成锁机制,主要是使用原子操作代替锁来实现对共享资源的访问保护。当使用原子操作时,在执行实际写操作时使用锁定指令,这样可以防止其他任务写入这块内存,避免数据竞争。原子操作比锁快,一般快两倍以上。例如,fwrite()和fopen()使用append方法写入文件。原理是使用无锁编程。无锁编程复杂,但效率高,死锁概率低。考虑进程优先级进程调度器会动态调整进程在运行队列中的优先级,通过top观察进程的PR值。考虑到系统负载,可以随时查看/proc/loadavg,top中的loadaverage也可以看到。考虑CPU使用率除了用户空间和内核空间的CPU使用率外,还应该关注I/O等待,指的是CPU空闲等待I/O操作完成的时间比例(查看值wa在顶部)。2.考虑减少内存分配和释放。服务器在工作过程中,需要大量的内存,这就使得内存的分配和释放工作变得尤为重要。通过改进数据结构和算法复制,可以适当减少中间临时变量的内存分配和数据复制时间,服务器本身也使用自己的策略来提高效率。比如Apache,在开始运行的时候,申请了一大块内存作为内存池。如果后面需要,可以直接从内存池中获取,不需要重新分配,避免了频繁的内存分配和释放带来的内存整理时间。又如Nginx采用多线程处理请求,使得内存资源可以在多个线程之间共享,从而大大降低其整体内存占用。另外,nginx的staged内存分配策略,按需分配,及时释放,使得Memory的占用率保持在一个很小的范围内。另外,还可以考虑共享内存。共享内存是指在多处理器计算机系统中,可以被不同中央处理器(CPU)访问,也可以被不同进程共享的大容量内存。它是一种非常快速的进程通信方式。但是使用共享内存也有一个缺点,就是在处理多台机器的时候数据不统一。shell命令ipcs可以用来显示系统中共享内存的状态。函数shmget可以创建或打开共享内存区域。函数shmat可以将现有的共享内存段连接到进程空间。函数shmctl可以对共享内存段进行各种操作,函数shmdt函数分离共享内存。3.考虑使用持久连接。持久连接也称为长连接。是TCP通信的一种常用方式,即在一个TCP连接中连续发送多条数据而不断开连接。相反的方法称为短连接。即连接建立后发送一个数据后断开,然后再次建立连接发送下一个数据,如此周而复始。是否使用持久连接完全取决于应用程序的特性。从性能的角度来看,建立TCP连接这个操作本身就是一个不小的开销。如果允许,连接数越少,越有利于性能提升;特别是对于密集图片或网页等小数据请求的处理。有明显的加速。HTTP持久连接需要浏览器和Web服务器的配合。目前,浏览器普遍支持长连接,表现在它们发送的HTTP请求数据头中包含关于长连接的声明,如下:Connection:Keep-Alive,主流的web服务器都支持长连接。比如在apache中,可以使用KeepAliveoff来关闭长连接。长连接的有效利用,还有一个关键点就是长连接超时时间的设置,即长连接什么时候关闭?Apache的默认设置是5s。如果这个时间设置的过长,可能会导致资源无效占用,维持大量空闲进程,影响服务器性能。4、改进I/O模型I/O操作根据不同的设备分为多种类型,如内存I/O、网络I/O、磁盘I/O等。对于网络I/O和磁盘I/O,它们的速度要慢很多,虽然使用RAID磁盘阵列可以通过并行磁盘加快磁盘I/O速度,购买大连独享网络带宽和使用高带宽网络适配器可以提高速度网络I/O。但是这些I/O操作需要内核系统调用来完成,这些都需要CPU进行调度,这就使得CPU不得不浪费宝贵的时间等待慢速的I/O操作。我们希望CPU花更少的时间在I/O操作的调度上。如何让高速的CPU和慢速的I/O设备更好地协调,是现代计算机一直在讨论的话题。各种I/O模型的本质区别在于CPU的参与方式。1、DMA技术I/O设备与内存之间的数据传输方式是由DMA控制器完成的。在DMA模式下,CPU只需要向DMA下发命令,让DMA控制器处理数据传输,可以大大节省系统资源。2.异步I/O异步I/O是指在主动请求数据后,可以继续处理其他任务,然后等待I/O操作的通知,这样进程在读写数据时不会阻塞.异步I/O是非阻塞的。当函数返回时,真正的I/O传输已经完成,这让CPU处理和I/O操作实现了很好的重叠。3.I/O多路复用服务器必须同时处理大量的文件描述符。如果采用同步非阻塞I/O模型,如果同时接收到TCP连接的数据,则必须依次调用和接收各个socket。data的方法,不管这些socket有没有数据可以接收,都要查询一次。如果大部分套接字都没有数据可接收,进程将浪费大量CPU时间来检查这些套接字是否有数据可接收。多路I/O就绪通知的出现,为大量的文件描述符就绪检查提供了一种高性能的解决方案,可以让一个进程通过一个方法同时监听所有的文件描述符,可以快速获取所有就绪文件描述符,然后仅针对这些文件描述符执行数据访问。epoll可以同时支持水平触发和边沿触发。理论上边沿触发性能更高,但代码实现复杂,因为任何意外丢失事件都会导致请求处理错误。epoll有两大改进:epoll只告诉就绪的文件描述符,调用epoll_wait()获取文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符个数的值,然后直接转到epoll指定的一个数组,依次获取相应数量的文件描述符。这里使用了内存映射(mmap)技术,完全省去了系统调用时拷贝这些文件描述符的开销。epoll采用了基于事件的就绪通知方式。它预先通过epoll_ctrl()注册每个文件描述符。一旦文件描述符就绪,内核将使用类似于回调的回调机制在进程调用epoll_wait()时得到通知。4、sendfile大多数时候,我们向服务器请求静态文件,比如图片、样式表等,在处理这些请求时,磁盘文件的数据首先经过内核缓冲区,然后到用户内存未经任何处理的空间。发送到网卡对应的内核缓冲区,然后发送到网卡进行发送。Linux提供了sendfile()系统调用,可以直接将磁盘文件的特定部分传输到代表客户端的socket描述符,加快静态文件的请求速度,减少CPU和内存开销。适用场景:对于小请求的静态文件,sendfile的作用不是那么明显,因为在发送数据的整个过程中所占的时间比大文件请求要小很多。5.内存映射Linux内核提供了一种特殊的方式来访问磁盘文件。它可以将内存中的某个地址空间与我们指定的磁盘文件关联起来,从而将对这块内存的访问转换为对磁盘文件的访问。这种技术称为内存映射。在大多数情况下,内存映射可以提高磁盘I/O的性能。而不是使用read()或write()等系统调用来访问文件,而是使用mmap()系统调用来建立内存和磁盘文件之间的关联,然后像访问内存一样自由地访问文件。缺点:在处理大文件时,内存映射会造成较大的内存开销,得不偿失。6、直接I/O在Linux2.6中,内存映射和直接访问文件没有本质区别,因为数据需要复制两次,即磁盘和内核缓冲区之间以及内核缓冲区和内核缓冲区之间。用户态内存空间。引入内核缓冲区的目的是为了提高磁盘文件的访问性能。但是,对于一些复杂的应用,比如数据库服务器,为了进一步提高性能,他们希望绕过内核缓冲区,自己在用户态空间实现和管理I/O。缓冲区,例如数据库,可以基于更合理的策略来提高查询缓存效率。另一方面,绕过内核缓冲区也可以减少系统内存的开销,因为内核缓冲区本身就是在使用系统内存。Linux在open()系统调用中加入参数选项O_DIRECT,可以绕过内核缓冲区,直接访问文件,实现直接I/O。在Mysql中,对于Innodb存储引擎,可以自行进行数据和索引的缓存管理,在my.cnf配置中分配原始分区,跳过内核缓冲区,实现直接I/O。改进服务器并发策略服务器并发策略的目的是尽可能地重叠I/O操作和CPU计算。一方面,I/O等待时CPU不应该空闲,另一方面,CPU应该尽可能少地花费在I/O调度上。时间。一个进程处理一个连接,当多个并发请求在非阻塞I/O中同时到达时,服务器必须准备多个进程来处理这些请求。其进程的开销限制了它的并发连接数。但从稳定性和兼容性来看,还是比较安全的。任何子进程的崩溃都不会影响服务器本身,父进程可以创建新的子进程;这种策略的典型例子是Apache的fork和prefork模式。对于并发数不高(比如小于150),同时依赖Apache其他功能的应用,还是可以选择Apache。一个线程处理一个连接,非阻塞IO方式允许多个线程在一个进程中处理多个连接,一个线程处理一个连接。Apache的worker模式就是这方面的一个典型例子,使其能够支持更多的并发连接。但是这种模式的整体性能不如prefork,所以一般不会使用worker模式。一个进程处理多个连接,异步I/O线程同时处理多个连接。潜在的先决条件是使用IO多路复用就绪通知。在这种情况下,将处理多个连接的进程称为工作进程或服务进程。worker的数量可以配置,比如Nginx中的worker_processes4。一个线程处理多个连接,即使有异步IO的高性能IO多路复用就绪通知,等待磁盘IO还是不可避免的。更高效的方法是对磁盘文件使用异步IO。目前很少有web服务器真正支持这种异步IO。6、改善硬件环境还有一个值得一提的就是硬件环境。服务器的硬件配置往往是提高应用程序性能最直接、最简单的方法。这就是所谓的放大。这里不讨论。
