• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • mpm_event

    描述:workerMPM的一种变体,其目标是仅消耗具有活动处理能力的连接的线程
    状态:MPM
    模块标识符:mpm_event_module
    源文件:event.c

    摘要

    event多处理模块(MPM)被设计以允许通过使关闭一些处理工作,以听众的线程,释放工作线程服务新的请求同时服务更多的请求。

    要使用eventMPM,请在构建时将其添加--with-mpm=eventconfigure脚本的参数中httpd

    与工人MPM的关系

    event基于workerMPM,该MPM实现了混合多进程多线程服务器。单个控制进程(父进程)负责启动子进程。每个子进程都会按照指令中的指定创建固定数量的服务器线程ThreadsPerChild,以及一个侦听器线程,该线程侦听连接并将连接到达时将其传递给工作线程进行处理。

    运行时配置指令与所提供的配置指令相同worker,只是增加了AsyncRequestWorkerFactor

    怎么运行的

    该MPM尝试修复HTTP中的“保持活动状态”。客户端完成第一个请求后,它可以保持连接打开,使用同一套接字发送其他请求,并节省创建TCP连接的大量开销。但是,Apache HTTP Server传统上会保留整个子进程/线程来等待来自客户端的数据,这有其自身的缺点。为了解决此问题,该MPM为每个进程使用专用的侦听器线程来处理侦听套接字,处于保持活动状态的所有套接字,处理程序和协议过滤器已完成工作的套接字以及仅剩余的套接字要做的就是将数据发送到客户端。

    这种新的架构利用了APR公开的无阻塞套接字和现代内核功能(例如Linux的epoll),不再需要进行mpm-acceptMutex配置来避免雷电群问题。

    单个进程/线程块可以处理的连接总数由AsyncRequestWorkerFactor指令控制。

    异步连接

    异步连接将需要使用固定的专用工作线程与先前的MPM,而不需要事件。的状态页面mod_status在“异步连接”部分下显示新列:

    写作
    在将响应发送到客户端时,由于连接速度太慢,TCP写缓冲区可能已满。通常在这种情况下,在空闲时间之后write(),套接字的a返回EWOULDBLOCKEAGAIN再次变为可写状态。持有套接字的工作程序可能能够将等待的任务卸载到侦听器线程,从而一旦套接字发生事件(例如,“套接字已现在可写”)。请检查“限制”部分以获取更多信息。
    活着
    “保持活动”处理是工作人员MPM的最基本改进。一旦工作线程完成将响应刷新到客户端的操作,它就可以将套接字处理工作转移到侦听器线程,从而依次等待来自OS的任何事件,例如“套接字可读”。如果客户端发出任何新请求,则侦听器会将其转发到可用的第一个工作线程。相反,如果KeepAliveTimeout发生这种情况,则监听器将关闭套接字。这样,工作线程不负责空闲套接字,并且可以将它们重新用于服务其他请求。
    闭幕
    有时,MPM需要执行持久的关闭,即在仍将数据传输到httpd的同时,将早期错误发送回客户端。发送响应然后立即关闭连接不是正确的操作,因为客户端(仍在尝试发送其余请求)将重置连接并且无法读取httpd的响应。延迟关闭是有时间限制的,但是可能会花费相对较长的时间,因此将其卸载到工作线程(包括关闭挂钩和实际套接字关闭)。从2.4.28开始,连接最终超时时也是如此(侦听器线程除了等待和调度其事件外,从不处理连接)。

    这些改进对HTTP / HTTPS连接均有效。

    流畅地终止流程和使用记分板

    此MPM过去显示了一些可伸缩性瓶颈,导致出现以下错误:“记分板已满,而不是在MaxRequestWorkers处”。MaxRequestWorkers限制在任何给定时间将服务的并发请求数,以及允许的进程数(MaxRequestWorkers/ThreadsPerChild);同时,记分板表示所有正在运行的进程及其工作线程的状态。如果记分板已满(因此所有线程的状态都为非空闲),但服务的活动请求数不是MaxRequestWorkers,则意味着其中一些正在阻止可服务但正在排队的新请求(最多限制ListenBacklog)。在大多数情况下,线程都处于Graceful状态,即它们正在等待通过TCP连接完成其工作,以安全地终止并释放记分板插槽(例如,处理长时间运行的请求,慢速客户端或与保持活动状态)。两种情况很常见:

    • 在正常重启期间,父进程会发信号通知其所有子进程完成其工作并终止,同时重新加载配置并派生新进程。如果大一点的孩子在停下来之前继续跑步一段时间,记分板将被部分占用,直到他们的插槽被释放。
    • 服务器负载的下降会导致httpd停止某些进程(例如由于MaxSpareThreads)。这特别有问题,因为当负载再次增加时,httpd将尝试启动新进程。如果重复这种模式,则进程的数量可能会增加很多,最终导致尝试停止的旧进程和尝试执行某些工作的新进程混合在一起。

    从2.4.24开始,mpm-event变得更智能,并且能够以更好的方式处理正常终止。一些改进是:

    • 允许使用所有记分牌插槽(最多)ServerLimitMaxRequestWorkersThreadsPerChild用于限制活动进程的数量;同时,ServerLimit还应考虑进行适当的关闭以在需要时允许额外的插槽。这个想法是用来ServerLimit指导httpd在影响系统资源之前允许多少个总体过程。
    • 强制优雅地完成进程以使其保持活动状态以关闭其连接。
    • 在正常关闭期间,如果给定进程的运行中的工作线程多于打开的连接,请终止这些线程以更快地释放资源(新进程可能需要)。
    • 如果记分板已满,请防止由于负载减少而导致更多进程正常完成,直到旧进程终止为止(否则,一旦负载再次增加,情况将变得更糟)。

    最后一点中描述的行为可以通过mod_status连接摘要表中的两个新列完全看到:“插槽”和“停止”。前者指示PID,后者指示过程是否停止。多余的状态“是(旧生成)”表示正常重启后进程仍在运行。

    局限性

    改进的连接处理对于某些声明为与事件不兼容的连接过滤器可能不起作用。在这些情况下,该MPM将退回到MPM的行为worker并为每个连接保留一个工作线程。服务器随附的所有模块均与事件MPM兼容。

    当前对于涉及需要读取和/或修改整个响应主体的输出过滤器的请求存在类似的限制。如果在过滤器处理数据时阻塞了与客户端的连接,并且过滤器产生的数据量太大而无法在内存中进行缓冲,则在httpd等待挂起的数据被释放时,不会释放用于请求的线程。发送给客户。
    为了说明这一点,我们可以考虑以下两种情况:提供静态资产(如CSS文件)与提供从FCGI / CGI或代理服务器检索的内容的服务。前者是可以预见的,即事件MPM在内容末尾具有完全可见性,并且可以使用事件:提供响应内容的辅助线程可以刷新第一个字节,直到EWOULDBLOCKEAGAIN返回,将其余的委托给侦听器。这依次等待套接字上的一个事件,并委派工作将其余的内容刷新到第一个空闲的工作线程。同时,在后一个示例(FCGI / CGI /代理内容)中,MPM无法预测响应的结束,并且辅助线程必须先完成其工作,然后才能将控件返回给侦听器。唯一的选择是将响应缓冲在内存中,但是出于服务器稳定性和内存占用的考虑,这不是最安全的选择。

    背景材料

    通过在支持的操作系统中引入新的API,使事件模型成为可能:

    • epoll(Linux)
    • kqueue(BSD)
    • 事件端口(Solaris)

    在提供这些新API之前,必须使用传统API selectpollAPI。如果用于处理许多连接或连接变化率很高,则这些API会变慢。新的API允许监视更多的连接,并且在一组监视频繁变化的连接时,它们的性能更好。因此,这些API使得编写事件MPM成为可能,该事件可通过许多空闲连接的典型HTTP模式进行更好地扩展。

    MPM假定基础apr_pollset实现是合理的线程安全的。这使MPM可以避免过多的高级锁定,也不必唤醒侦听器线程才能向其发送保持活动套接字。当前仅与KQueue和EPoll兼容。

    要求

    该MPM依赖于APR的原子比较和交换操作来进行线程同步。如果要编译支持x86的目标,你不需要支持386,或者你正在编译为SPARC,你不需要在UltraSPARC之前芯片上运行,添加--enable-nonportable-atomics=yesconfigure脚本的参数。这将导致APR使用旧式CPU中不可用的有效操作码来实现原子操作。

    该MPM在缺少良好线程的较旧平台上的性能不佳,但是对于EPoll或KQueue的要求却引起了争议。

    • 要在FreeBSD上使用此MPM,建议使用FreeBSD 5.3或更高版本。但是,如果您使用的话,可以在FreeBSD 5.2.1上运行该MPM libkse(参见参考资料man libmap.conf)。
    • 对于NetBSD,建议至少使用2.0版。
    • 对于Linux,建议使用2.6内核。还需要确保您的的版本glibc已编译为支持EPoll。

    AsyncRequestWorkerFactor 指令

    描述:限制每个进程的并发连接
    句法:AsyncRequestWorkerFactor factor
    默认:2
    内容:服务器配置
    状态:MPM
    模组:事件
    兼容性:在2.3.13版和更高版本中可用

    事件MPM以异步方式处理某些连接,其中请求工作线程仅根据需要分配很短的时间,而其他连接每个连接保留一个请求工作线程。这可能导致所有工作人员都被束缚,并且没有工作线程可用于处理已建立的异步连接上的新工作的情况。

    为了缓解此问题,事件MPM做两件事:

    • 它限制了每个进程接受的连接数,具体取决于空闲请求工作程序的数量。
    • 如果所有工作人员都忙,即使保持活动超时没有到期,它也会以保持活动状态关闭连接。这允许各个客户端重新连接到可能仍具有工作线程的其他进程。

    此伪指令可用于微调每个进程的连接限制。甲过程将只接受新的连接,如果连接(未计数的“闭合”状态的连接)的当前数目低于:

    ThreadsPerChild+(AsyncRequestWorkerFactor*闲置工人数

    给定空闲工作线程的平均值,可以估算所有进程之间的最大并发连接数,其估算公式如下:

    ThreadsPerChild+(AsyncRequestWorkerFactor*闲置工人数))*ServerLimit

    ThreadsPerChild = 10 ServerLimit = 4 AsyncRequestWorkerFactor = 2 MaxRequestWorkers = 40  
      
      
      
    
    idle_workers = 4 (所有进程的平均值,以使其保持简单)  
    
    max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers ))* ServerLimit = (10 + (2 * 4 ))* 4 = 72      
                             
    

    当所有工作线程都处于空闲状态时,可以通过一种更简单的方式计算并发连接的绝对最大数量:

    AsyncRequestWorkerFactor+ 1)*MaxRequestWorkers

    ThreadsPerChild = 10 ServerLimit = 4 MaxRequestWorkers = 40 AsyncRequestWorkerFactor = 2  
      
      
      
    

    如果所有进程的所有线程都空闲,则:

    idle_workers = 10 
    

    我们可以通过两种方式计算并发连接的绝对最大数量:

    max_connections = (ThreadsPerChild + (AsyncRequestWorkerFactor * idle_workers ))* ServerLimit = (10 + (2 * 10 ))* 4 = 120      
                             
    
    MAX_CONNECTIONS = (AsyncRequestWorkerFactor + 1 )* MaxRequestWorkers = (2 + 1 )* 40 = 120     
                           
    

    调优AsyncRequestWorkerFactor需要有关每种特定用例中httpd处理的流量的知识,因此更改默认值需要进行广泛的测试和从收集数据mod_status

    MaxRequestWorkersMaxClients2.3.13版之前被调用。上面的值表明,旧名称不能准确描述事件MPM的含义。

    AsyncRequestWorkerFactor可以接受非整数参数,例如“ 1.5”。

    上篇:mpm_common

    下篇:mpm_netware