ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Nginx连接数监控:从基础原理到实战排查的完整指南

Nginx连接数监控:从基础原理到实战排查的完整指南

1. 项目概述:为什么我们需要关注Nginx连接数?

在运维和开发的实际工作中,Nginx的状态监控就像汽车的仪表盘,而连接数则是其中最关键的几个仪表之一。想象一下,你负责的电商网站在大促期间突然响应变慢,页面加载时间从几百毫秒飙升到几秒,用户开始抱怨。这时候,你的第一反应是什么?是代码有Bug,还是数据库慢了?很多时候,问题的根源可能在于流量洪峰压垮了你的Web服务器,而连接数就是最直观的“压力表”。它直接反映了Nginx当前正在处理的客户端请求数量,包括正在等待的和正在响应的。一个异常飙升的活跃连接数,往往意味着服务器正在过载,或者后端应用出现了阻塞。

我遇到过不少案例,团队花了大量时间排查应用日志和数据库性能,最后才发现是Nginx的worker_connections参数配置过低,导致连接池迅速耗尽,新的请求被直接丢弃。因此,掌握查看Nginx连接数的方法,不仅仅是执行几条命令,更是构建系统可观测性、进行容量规划和故障快速定位的基础技能。无论是日常巡检、性能调优,还是突发的线上故障应急,它都是你工具箱里必备的“听诊器”。接下来,我会结合多年实战经验,为你拆解几种核心方法,从内置状态模块到系统级命令,让你不仅能看懂数字,更能理解数字背后的故事。

2. 核心方法一:使用Nginx内置的ngx_http_stub_status_module模块

这是Nginx官方提供的、最标准也是最常用的连接数查看方法。它通过一个简单的HTTP接口,暴露了Nginx进程的关键状态信息。但首先,你需要确认你的Nginx编译安装时包含了这个模块。

2.1 模块检查与启用

对于大多数通过包管理器(如yumapt)安装的Nginx,该模块通常是默认包含的。你可以通过以下命令快速验证:

nginx -V 2>&1 | grep -o with-http_stub_status_module

如果输出with-http_stub_status_module,则说明模块已存在。如果没有输出,你可能需要重新编译Nginx并加入--with-http_stub_status_module参数,或者寻找包含此模块的发行版。

启用该模块需要在Nginx的配置文件中(通常是nginx.conf/etc/nginx/conf.d/下的某个文件)添加一个location块。我个人的习惯是单独创建一个配置文件,比如/etc/nginx/conf.d/status.conf,这样管理起来更清晰,也避免污染主业务配置。

server { listen 8080; # 建议使用一个内部端口,不要暴露在公网 server_name localhost; # 或你的内网IP location /nginx_status { stub_status on; access_log off; # 状态页面访问通常不需要记录日志 allow 192.168.1.0/24; # 只允许特定内网IP段访问,这是安全关键! allow 127.0.0.1; deny all; # 拒绝其他所有访问 # 如果需要有基础认证,可以加上: # auth_basic "Nginx Status"; # auth_basic_user_file /etc/nginx/.htpasswd; } }

注意:安全是重中之重!绝对不要将stub_status页面暴露在公网。它虽然不包含敏感业务数据,但攻击者可以通过它了解你服务器的负载状况,为后续攻击做准备。务必使用allow/deny指令进行IP限制,或结合防火墙规则。

配置完成后,执行nginx -t测试配置语法,无误后通过nginx -s reload重载配置。

2.2 状态页面解读与深度分析

现在,访问http://your-server-internal-ip:8080/nginx_status,你会看到类似下面的信息:

Active connections: 291 server accepts handled requests 16630948 16630948 31070465 Reading: 6 Writing: 179 Waiting: 106

这几行数字就是宝藏,我们来逐一解码:

  • Active connections:当前活跃的客户端连接数。这是最需要关注的指标,它直接反映了Nginx的实时负载压力。这个数字应该与你配置的worker_connections(在events块中)进行比较。如果Active connections长期接近worker_connections的上限,就意味着连接池即将耗尽,新请求会被拒绝,必须立即扩容或调优。

  • accepts, handled, requests

    • accepts:自Nginx启动以来,已经接受的客户端连接总数。
    • handled:成功处理的连接总数。通常,acceptshandled是相等的,如果两者出现差值,说明有些连接被直接关闭了(例如,在未分配工作进程时)。
    • requests:自Nginx启动以来,客户端总共发起的请求数量。这是一个累计值,可以用来计算平均每个连接处理的请求数(requests / handled),即“连接复用率”。在HTTP/1.1 Keep-Alive开启的情况下,这个比值越高,说明连接复用效果越好,服务器建立和断开连接的开销越小。
  • Reading, Writing, Waiting:这三个是对Active connections的进一步细分,是分析服务器当前工作状态的“显微镜”。

    • Reading:正在读取请求头的连接数。如果这个值异常高,可能意味着客户端网络很慢,或者正在上传大文件。
    • Writing:正在向客户端发送响应的连接数。这是服务器“正在工作”的主要体现。如果Writing数量很多且持续,可能意味着后端应用响应慢,或者正在返回大量数据。
    • Waiting:处于空闲状态,正在等待后续请求的持久连接(Keep-Alive)数。这是健康状态的标志。在连接复用场景下,一定数量的Waiting连接是正常的,它们避免了频繁建立新连接的开销。但如果Waiting连接数过多,而ReadingWriting很少,可能意味着你的keepalive_timeout设置得过长,导致连接资源被闲置占用。

实操心得:不要只看Active connections的绝对值。我习惯将ReadingWritingWaiting的比例作为一个健康度指标。在一个处理API请求的服务上,理想状态下Writing占主导,Waiting维持一定比例,Reading很少。如果发现Reading长期偏高,我就会去检查是否有慢速客户端攻击,或者调整client_header_timeout

3. 核心方法二:利用操作系统网络工具进行宏观分析

当Nginx的stub_status模块不可用,或者你需要从更底层、更全局的视角来审视连接情况时,操作系统的网络工具就派上用场了。它们能告诉你系统层面所有与Nginx端口相关的连接,包括一些处于异常状态的连接(如TIME_WAIT,CLOSE_WAIT),这些信息在Nginx状态页面上是看不到的。

3.1netstat命令的经典用法

netstat是一个历史悠久的网络统计工具,虽然在新系统中逐渐被ss命令取代,但其输出格式对很多人来说更直观。

# 查看所有与Nginx监听端口(例如80和443)相关的连接 netstat -anp | grep -E ‘:(80|443)’ | grep ESTABLISHED # 更详细的统计,按状态分类 netstat -ant | awk ‘/^tcp/ {print $6}’ | sort | uniq -c | sort -rn

第一条命令可以快速查看当前正在活动的业务连接数。第二条命令则是一个经典技巧,它能统计出所有TCP连接的各种状态数量,输出类似:

125 ESTABLISHED 32 TIME_WAIT 5 LISTEN 2 CLOSE_WAIT

这对于发现连接泄漏问题非常有用。例如,如果TIME_WAIT状态连接堆积如山(成千上万),可能会耗尽本地端口资源,这通常需要调整内核参数net.ipv4.tcp_tw_reusenet.ipv4.tcp_tw_recycle(注意,tcp_tw_recycle在较新内核中已废弃,需谨慎使用)。

3.2ss命令:更现代、更快速的替代方案

ss(Socket Statistics)是netstat的替代品,来自iproute2工具包,速度更快,信息更详细。

# 查看所有连接到Nginx工作进程的端口 ss -tlnp sport = :80 or sport = :443 # 查看Nginx进程建立的所有连接(更精确) # 首先获取Nginx master进程的PID,通常worker进程是它的子进程 sudo ss -tnp dst :80 or dst :443 | grep nginx # 按状态快速统计 ss -ant | grep -v ‘State’ | awk ‘{print $1}’ | sort | uniq -c

为什么更推荐ss在连接数非常高的服务器上(例如超过数万),netstat可能会因为遍历/proc/net/tcp文件而显得缓慢,消耗更多CPU。而ss直接从内核获取信息,效率极高。在应急排查时,使用ss能更快地得到结果。

3.3 通过/proc文件系统直接读取

Linux万物皆文件,连接信息也记录在/proc文件系统中。Nginx每个工作进程(worker process)的连接信息,可以在其对应的/proc/[pid]/fd/目录下窥见一斑(每个socket连接对应一个文件描述符)。但更直接的是查看全局的TCP信息:

# 查看所有TCP连接,并过滤出目标端口是80或443的 cat /proc/net/tcp | awk ‘{print $2, $3}’ | grep ‘:0050\|:01BB’ # 0050是80的十六进制,01BB是443的十六进制

这种方法比较原始,输出是十六进制,可读性差,一般不用于手动检查,但它是很多监控代理(如Zabbix agent, Telegraf)采集数据的基础方式,因为直接读取文件开销极小。

实操心得:我通常将ss命令作为日常巡检和故障排查的首选。特别是ss -tnp可以同时看到连接和对应的进程名,在排查“哪个进程占用了大量连接”时非常高效。记得结合watch命令进行动态观察:watch -n 1 ‘ss -tnp dst :80 | grep nginx | wc -l’,可以每秒刷新一次Nginx 80端口的活跃连接数,在压测或故障时非常直观。

4. 核心方法三:解析Nginx访问日志进行间接推断

日志是历史的记录,虽然不能反映实时瞬间的连接数,但它是分析连接趋势、识别异常客户端和复盘历史问题的宝贵资料。通过分析特定时间窗口内的日志条目,我们可以推算出当时的并发请求情况,这近似于该时间段内的平均活跃连接数。

4.1 使用awk进行快速时间窗口分析

假设你的Nginx访问日志格式是默认的combined格式,并且时间戳在第四列。我们可以用awk来统计每秒的请求数,这在一定程度上能反映连接的并发度。

# 统计最近1分钟内,每秒的请求数量,观察波峰 awk -vDate=`date -d’-1 min’ +[%d/%b/%Y:%H:%M:%S` ‘$4 > Date {print $4}’ /var/log/nginx/access.log | cut -d[ -f2 | cut -d] -f1 | awk -F: ‘{print $1“:”$2“:”$3}’ | sort | uniq -c | sort -rn | head -20

这个命令看起来复杂,拆解一下:

  1. date -d’-1 min’生成一分钟前的时间。
  2. awk ‘$4 > Date’筛选出日志时间戳在一分钟内的记录。
  3. 后续的cutawk用于提取出精确到秒的时间戳(如02/Aug/2023:15:30:45)。
  4. sort | uniq -c统计每秒出现的次数(即每秒请求数)。
  5. sort -rn | head -20列出请求数最高的前20秒。

4.2 使用专业日志分析工具:GoAccess

对于长期、深入的日志分析,命令行工具可能力不从心。我强烈推荐使用GoAccess。它可以生成实时的、交互式的HTML报告,从连接(访问者)维度提供丰富的洞察。

安装GoAccess后,你可以这样使用:

# 生成一个HTML报告 zcat /var/log/nginx/access.log.*.gz | goaccess -a -o /path/to/report.html # 或者实时分析当前日志文件 tail -f /var/log/nginx/access.log | goaccess -a -o /path/to/report.html --real-time-html

在GoAccess的报告中,你可以清晰地看到:

  • 独立访客数:近似于同一时间段的并发连接用户数。
  • 请求频率:每秒/每分钟/每小时的请求数图表,直接对应了连接的繁忙程度。
  • 客户端IP排名:迅速找出哪些IP建立了过多的连接,可能是爬虫、攻击源或者有问题的客户端。

实操心得:日志分析的价值在于“事后诸葛亮”和“趋势发现”。我曾经通过分析GoAccess报告,发现每天凌晨3点总有几个固定的IP产生大量请求,但响应状态码都是499(客户端提前关闭连接)。顺藤摸瓜,发现是一个配置错误的内部定时任务在疯狂重试。因此,将日志分析与实时连接监控结合,才能构建完整的监控视野。对于生产环境,建议将Nginx日志实时接入ELK(Elasticsearch, Logstash, Kibana)或Grafana Loki这类日志平台,进行更强大的聚合和告警。

5. 核心方法四:集成第三方监控系统实现自动化

手动执行命令只适用于临时检查,对于7x24小时运行的业务系统,我们需要自动化的、可视化的监控方案。将Nginx连接数指标接入Prometheus这样的监控系统,是当前业界的标准做法。

5.1 使用Nginx Exporter暴露指标

Nginx本身不直接提供Prometheus格式的指标。我们需要一个“翻译官”——nginx-prometheus-exporter。这个exporter会去抓取我们前面配置的stub_status页面的数据,并将其转换为Prometheus能够识别的格式。

部署方式通常很简单,可以下载二进制文件直接运行:

./nginx-prometheus-exporter -nginx.scrape-uri=http://localhost:8080/nginx_status

Exporter默认会在9113端口提供一个/metrics端点。访问这个端点,你会看到格式化的指标,例如:

# HELP nginx_connections_active Active client connections # TYPE nginx_connections_active gauge nginx_connections_active 123 # HELP nginx_connections_reading Connections where NGINX is reading request header # TYPE nginx_connections_reading gauge nginx_connections_reading 5 ...

5.2 配置Prometheus抓取与Grafana可视化

接下来,在Prometheus的配置文件prometheus.yml中,添加一个针对exporter的抓取任务:

scrape_configs: - job_name: ‘nginx’ static_configs: - targets: [‘your-nginx-server-ip:9113’] scrape_interval: 15s # 每15秒抓取一次

重启Prometheus后,它就会开始定期收集Nginx的连接数数据。最后,在Grafana中创建一个仪表盘,使用PromQL查询语句来绘制图表:

  • 活跃连接数趋势图nginx_connections_active
  • 读写等待连接分布nginx_connections_reading,nginx_connections_writing,nginx_connections_waiting
  • 请求率rate(nginx_requests_total[5m])(计算每秒请求数)

你还可以设置告警规则,例如当活跃连接数超过worker_connections的80%时,触发告警通知。

实操心得:搭建监控体系初期可能会觉得麻烦,但一旦建成,它带来的价值是巨大的。除了基础连接数,我还建议收集nginx_up(exporter自身健康状态)和nginx_exporter_scrape_failures_total(抓取失败次数)等指标。在Grafana面板上,我将活跃连接数与服务器CPU、内存使用率、后端应用响应时间放在同一个视图里,这样当出现问题时,可以一眼看出是网络流量问题、服务器资源问题还是应用代码问题,极大提升了故障定位效率。

6. 常见问题与排查技巧实录

掌握了查看方法,更重要的是能解决实际问题。下面是我在多年运维中积累的一些关于Nginx连接数的典型问题场景和排查思路。

6.1 连接数异常飙升,服务器响应变慢

现象:通过stub_statusss命令发现Active connectionsWriting连接数突然暴涨,服务器负载升高,响应时间变长。

排查思路

  1. 区分流量来源:首先用ss -tnp dst :80查看这些连接的客户端IP。如果来自少量IP,可能是CC攻击或某个失控的客户端。如果来源广泛,可能是正常流量高峰或某个热点内容被传播。
  2. 检查后端健康:Nginx连接数高,很可能是因为后端应用(如PHP-FPM, Tomcat, Node.js)处理变慢,导致请求堆积在Nginx。立即检查后端应用的监控指标(响应时间、错误率、队列长度)。
  3. 分析日志:使用tail -f查看Nginx错误日志(error.log)和访问日志(access.log)。关注是否有大量502 Bad Gateway504 Gateway Timeout错误,这明确指向后端问题。同时查看访问日志中慢请求(可通过$request_time记录)的模式。
  4. 检查系统资源:使用top,htop,vmstat 1查看CPU、内存、磁盘I/O和系统负载。确认不是服务器本身资源耗尽。
  5. 限流与降级:如果确定是异常流量,立即启用Nginx的限流模块(如limit_req_zone)进行临时控制,并考虑将非核心功能降级。

我的一个案例:有一次,Writing连接数持续高位,但后端应用监控正常。最后发现是Nginx配置中proxy_buffering被关闭,且一个API接口返回了一个巨大的JSON(几十MB),导致Nginx必须同步地、缓慢地将数据发送给每一个慢速的移动端客户端,占用了大量工作进程。开启proxy_buffering后,Nginx可以快速从后端读完响应,再异步发送给客户端,连接数迅速下降。

6.2TIME_WAIT状态连接过多

现象:使用ss -ant | grep TIME-WAIT | wc -l发现数量极大(比如上万),有时甚至会影响新连接的建立。

原因分析:TCP连接关闭时,主动关闭方(对于Nginx作为反向代理,它向后端建立连接时是客户端,关闭时可能是主动方)会进入TIME_WAIT状态,等待2MSL(Maximum Segment Lifetime,通常为60秒)时间,以确保网络中残留的数据包已经消失。高并发短连接场景下,此状态连接会快速积累。

解决方案与权衡

  1. 启用端口复用:修改内核参数,这是最常用的方法。
    sysctl -w net.ipv4.tcp_tw_reuse=1 # 允许将TIME-WAIT sockets重新用于新的TCP连接 # net.ipv4.tcp_tw_recycle 在较新内核中已废弃,不建议使用 sysctl -w net.ipv4.tcp_max_tw_buckets=180000 # 增大系统允许的TIME_WAIT数量上限
    将这些写入/etc/sysctl.conf使其永久生效。
  2. 优化Nginx与后端连接:启用HTTP/1.1的Keep-Alive,让Nginx与后端服务器复用连接,而不是每次请求都新建连接。这在upstream配置块中设置:
    upstream backend { server 10.0.0.1; keepalive 32; # 保持最多32个空闲连接向上游 } location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection “”; }
  3. 调整Nginx连接关闭行为:可以尝试调整keepalive_timeoutkeepalive_requests,让客户端连接更合理地复用和关闭。

注意:盲目调整tcp_tw_reuse等参数可能有风险,特别是在负载均衡器或NAT环境下。修改前最好在测试环境验证,并充分理解其含义。

6.3 Nginx状态页面显示acceptshandled数值不相等

现象:在stub_status输出中,acceptshandled两个数字有微小差距。

深度解析:这通常不是大问题,但值得理解其含义。accepts代表从内核接受(accept)的连接数,handled代表被Nginx工作进程成功处理的连接数。两者不相等,意味着有些连接在从内核“接受”到被工作进程“处理”这个极短的空窗期内就被关闭了。可能的原因有:

  • 客户端在完成TCP三次握手后,立即发送了RST包断开连接(可能是端口扫描行为或客户端异常)。
  • 在连接被放入监听队列(listen queue)后,但在被worker进程accept之前,客户端超时关闭。

如果这个差值(accepts - handled)持续且显著增大,则需要关注netstat -s | grep listen中的times the listen queue of a socket overflowed(监听队列溢出次数)是否在增加。这可能意味着瞬间的并发连接请求超过了net.core.somaxconn和Nginxlisten指令中backlog参数的限制,需要考虑适当调大这些参数。

排查清单速查表

问题现象可能原因排查命令/位置解决思路
活跃连接数(Active)持续高位1. 真实流量大
2. 后端应用慢
3. 客户端慢(如大文件上传下载)
1.ss -tnp看连接分布
2. 检查后端监控
3. 查看Nginx$request_time日志
1. 扩容
2. 优化后端
3. 调整proxy_buffering,send_timeout
Writing连接数特别高1. 后端响应慢,Nginx在“等”
2. 响应体巨大,发送慢
3. 客户端网络差
1. 后端应用监控
2. 检查接口返回数据大小
3. Nginx错误日志
1. 优化后端
2. 开启Gzip压缩,分页
3. 调整proxy_send_timeout
Waiting连接数异常多keepalive_timeout设置过长查看Nginx配置适当调低keepalive_timeout
大量TIME_WAIT连接高并发短连接,TCP连接频繁建立关闭ss -ant | grep TIME-WAIT | wc -l1. 调内核参数(tcp_tw_reuse)
2. 启用upstream keepalive
新建连接被拒绝1.worker_connections耗尽
2. 系统文件描述符限制
3. 监听队列溢出
1. Nginxstub_status
2.ulimit -n
3.netstat -s | grep listen
1. 增加worker_connections
2. 增加系统nofile限制
3. 增大somaxconnbacklog

掌握这些方法后,你看待Nginx连接数的视角就从一个个孤立的数字,变成了一个动态的、反映系统整体健康状况的仪表盘。真正的能力不在于记住命令,而在于当数字异常时,能结合上下文,快速形成排查假设并验证。这需要你对Nginx工作原理、操作系统网络和业务特性都有一定的理解。建议你在自己的测试环境中,模拟不同的场景(如使用ab,wrk进行压测,或使用tc命令模拟网络延迟),观察连接数指标的变化,积累第一手的经验。

返回列表