The Future of Monitoring
Apache HTTP Server监控
Apache性能与了解/server状态指标
作者:Andris Zeila, Zabbix开发工程师
译者: 张歆,宏时数据Zabbix工程师
一 Apache统计模块:mod_status
了解网站性能和Apache运行时间可以通过外部监控工具实现,例如:Zabbix,可以从用户的视角来发现问题,包括:
所有这些问题都应该通过多个区域的监控来确认,以排除网络问题的相关因素。只有在同时从多个区域发现到相同的问题时,我们才能断定是服务器端出了问题。
下一步是检查服务器本身是否一切正常。这就是CPU、内存、磁盘和交换空间等基本指标发挥作用的上地方,它们为您提供了进一步关注哪些方面的指导。
导致网站性能问题的最常见原因是故障、bug或未优化的应用程序(例如PHP脚本)和数据库查询速度慢。然而,在深入分析应用程序及其查询之前,检查Apache配置和统计数据是很有必要的——这就是本文要阐述内容。
Apache web服务器通过其状态模块mod_status公开指标。如果您的服务器正在运行并且启用了mod_status,那么您的服务器的状态页面应该是http://<YOUR_DOMAIN>/server-status。如果该链接不起作用,则意味着需要在配置文件中启用mod_status。
配置文件中指定的位置也可能不是/server-status,不管有意还是无意。按照下面的指示查找mod_status配置文件,并寻找包含SetHandler server-status的指令。如果您看到它指定了一个位置而不是/server-status,那么您可以相应地更新它(并重新启动Apache),或者尝试访问该端点,看看是否在该位置启用了mod_status。启用mod_status并重启Apache之后,您将能够在http://<YOUR_DOMAIN>/server-status看到您的状态页面。
一 Apache进程和线程架构
最新的Apache版本实现了对服务器请求的混合多线程和多进程模型。这意味着您将看到多个Apache进程运行,每个进程包含多个线程。这允许在效率和稳定性之间进行很大的权衡。
Apache总是在所有进程之间维护大量空闲(备用)的workers,即处理请求的单个服务器线程,因为这允许它立即将请求分配给一个线程进行处理,而不需要生成一个线程,这将大大增加处理延迟。已经处理请求的workers称为繁忙workers。根据于空闲workers的数量,Apache能够分支或者结束进程。在正常情况下,由于Apache的自我调节,空闲workers的数量应该或多或少是稳定的。
Apache分支处理进程和线程的方式由特定的多处理模块(MPM)决定。此模块还负责绑定端口、接收连接并将其分派给workers。根据在Unix OS家族中最使用最广泛的prefork和worker两种模式。区别在于prefork不使用线程,而prefork使用所有必要的进程,而worker同时使用进程和线程。因此,prefork的内存消耗较低,但在非线程安全的应用程序中,它提供了更高的稳定性。
一 Workers模式配置
一个典型的多处理模块(MPM)配置如下(参考apache.org):
ServerLimit 16
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 10000
以下是这些配置指令的简要说明:
Ø ServerLimit是对活动Apache子进程数量的硬限制。它应该遵循以下规则ServerLimit >= MaxClients / ThreadsPerChild。
Ø StartServers是初始启动的子进程数。
Ø MaxClients是一个非常重要的参数,它设置了workers的最大数量(所有进程中的所有线程),还设置了可以同时处理的客户机请求的最大数量的限制。任何超过MaxClients限制的连接尝试通常都会被排队,直到按照ListenBacklog指令引导的特定数字为止。注意,在Apache 2.4版本中,这个参数被重命名为MaxRequestWorkers。
Ø MinSpareThreads和MaxSpareThreads是空闲workers数量的边界。
Ø ThreadsPerChild指定每个子进程创建的固定线程数。
Ø MaxRequestsPerChild是服务请求的数量(或连接,取决于使用的MPM的特定类型),之后子进程将终止。该指令的目的是防止内存泄漏。
一 了解Workers是如何工作的
Mod_status以记分牌的形式提供了关于每个worker正在做什么,记分牌看起来是这样的:
每个字符的含义如下:
空闲的workers:
"_" 等待连接
繁忙的workers:
"S" 正在启动
"R" 读请求
"W" 发送回复
"K" 保持连接(只读)
"D" DNS解析
"C" 正在关闭连接
"L" 正在登录
"G" 正常停止
"I" 清理空闲的workers
没有worker运行(但如果需要,配置允许它启动):
"." 打开没有当前进程的slot
一般情况下,大多数workers应处于R/W或空闲状态(“_”)。如果看到大量workers处于比如“K”、“D”或“L”状态,那么在活动设置、DNS解析或日志记录方面可能出现了相应的问题。
一 根据server调整Apache参数
与web服务器相关的最重要的服务器特性是RAM的数量。一般情况下我们会严禁切换web服务器,因为这会使请求处理延迟变得不可接受。重要的是要了解适合服务器RAM的最大worker的数量,并相应地调整MaxClients(或MaxRequestWorkers)参数。为了做到这一点,应该观察在正常情况下有多少Apache进程消耗了多少RAM。将第一个除以第二个,并将其与总可用物理内存进行比较,以了解在此服务器上可以启用多少Apache进程。
了解每台服务器上Apache worker的最大数量,将使您对服务器可以提供的流量有一定的了解。您可以使用这些信息来预测未来基础组件的升级。
一 查看繁忙和空闲的workers
观察繁忙和空闲workers的数量是及早发现Apache配置问题的一种很好的、主动的方法。
如果在高峰流量情况下,空闲workers的数量接近或达到零,这可能导致一些请求排队;等待有空的workers。这种排队的请求必须等待较早的请求被处理,这将导网站响应时间较长。为了改善这种情况,您应该考虑增加MaxClients (或MaxRequestWorkers)参数的值,这些值决定对连接数的限制。请注意,使用更多的workers将需要更多的服务器资源,因此如果您缺少这些资源(主要是RAM),那么更改MaxClients/MaxRequestWorkers将适得其反。在这种情况下,解决资源瓶颈的唯一方法是升级服务器或购买另一个服务器并进行负载平衡,将静态数据移出服务器。
一 小技巧
一 系统管理员最关注的监控指标
一 通过Zabbix监控
现在让我们看看如何使用Zabbix获得和解析这些数据。方便重复使用这些配置数据,最好创建Apache监控模板。使用HTTP agent监控项类型很容易获得状态数据。将其添加到模板中,将URL设置为用户宏{$APACHE.STATUS}。它的内容可以在主机上被覆盖,并添加' auto '到查询字段。数据将由依赖的监控项解析,因此历史记录可以设置为0,除非您希望保留原始数据的历史记录。
现在是有点复杂的部分——数据解析。可以使用正则表达式解析大部分数据,但是,解析workers状态(记分牌)会存在问题。这就是为什么我们将使用JavaScript预处理将Apache状态数据转换为JSON格式,依赖监控项可以轻松解析JSON格式以提取特定的参数。
数据将根据以下规则进行转换:
转换脚本如下:
// Convert Apache status to JSON. var lines = value.split("\n"); var fields = {}, workers = {}, output = {}; // Get all "Key: Value" pairs as an object. for (var i = 0; i < lines.length; i++) { var line = lines[i].match(/([A-z0-9 ]+): (.*)/); if (line !== null) { output[line[1]] = isNaN(line[2]) ? line[2] : Number(line[2]); } } // Parse "Scoreboard" to get worker count. if (typeof output.Scoreboard === 'string') { for (var i = 0; i < output.Scoreboard.length; i++) { var char = output.Scoreboard[i]; workers[char] = workers[char] ? (workers[char] + 1) : 1; } } // Add worker data to the output. output.Workers = { waiting: workers["_"], starting: workers["S"], reading: workers["R"], sending: workers["W"], keepalive: workers["K"], dnslookup: workers["D"], closing: workers["C"], logging: workers["L"], finishing: workers["G"], cleanup: workers["I"], slot: workers["."] }; // Return JSON string. return JSON.stringify(output);
现在创建依赖监控项来从转换后的JSON中提取指标。监控项是类似的,具有相应的值类型和单位。这些监控项将至少有一个JSONPath预处理步骤,对于可选指标,“Custom on fail”设置为“丢弃值”。具体详见下表:
测试时先创建主机,关联模板并添加{$APACHE.STATUS},指向apache mod状态URL的主机宏。一段时间后,Zabbix应该能收集Apache状态数据: