
在数据中心运维中,我遇到过这样一个棘手的问题:在 Ubuntu 22.04 的数据中心香港服务器上,使用 Apache 作为反向代理时无法正确访问后端应用,而系统上同时还部署了 Nginx。通过一系列细致的排查、配置优化和性能检测,我最终定位到是 Nginx 与 Apache 监听端口和模块冲突引起的问题。
一、环境概况与硬件配置
本文中的测试环境基于A5IDC数据中心标准香港服务器www.a5idc.com配置:
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu Server 22.04 LTS |
| 内核版本 | 5.15.x |
| CPU | Intel Xeon Silver 4214R (12核 24 线程) |
| 内存 | 64GB DDR4 ECC |
| 磁盘 | 2×1TB NVMe SSD (RAID1) |
| 网络 | 10Gbps 公网直连,内网 1Gbps |
| Web 服务器 | Apache 2.4.57 + Nginx 1.22.1 |
| 后端应用 | Spring Boot(监听 8081)、Node.js(监听 3000) |
我在该服务器同时部署 Nginx 和 Apache,是为了分别处理不同服务域名的流量------Nginx 负责静态内容和反向代理 Node 应用,而 Apache 负责某些 PHP 和 Java 应用的反向代理。
二、故障现象
当我配置 Apache 反向代理将流量转发到后端 Spring Boot 服务时,浏览器返回 502 Bad Gateway 或 504 Gateway Timeout:
bash
curl -I http://example.com/api
HTTP/1.1 502 Bad Gateway
而使用 curl 直接访问后端服务是正常的:
bash
curl -I http://127.0.0.1:8081
HTTP/1.1 200 OK
这意味着后端应用本身是正常的,而请求在到达 Apache 阶段就被阻断。
三、问题初步分析
1. 端口监听与冲突检查
由于服务器上既有 Apache 也有 Nginx,两者都可能监听相同端口(如80/443),或抢占某些资源,被动影响反向代理行为。
检查监听端口:
bash
sudo ss -tulnp | grep -E "80|443|8081|3000"
输出示例:
tcp LISTEN 0 128 *:80 *:* users:(("nginx",pid=1234),("apache2",pid=2345))
tcp LISTEN 0 128 *:443 *:* users:(("apache2",pid=2346))
tcp LISTEN 0 128 *:8081 *:* users:(("java",pid=3456))
可见 Nginx 和 Apache 都监听了 80 端口,这在同一 IP 上是无法共存的,会触发绑定失败或内核级别的端口抢占。
四、冲突定位与验证
1. 系统日志分析
查看 Apache 错误日志:
bash
sudo tail -n 100 /var/log/apache2/error.log
通常包含如下错误提示:
(98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
即 Apache 无法绑定 80 端口。
查看 Nginx 错误日志:
bash
sudo tail -n 100 /var/log/nginx/error.log
可能包含:
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
同时又显示 Nginx 自身正常监听,但冲突说明配置上未做好区分。
五、解决思路
方法一:端口分离策略
推荐方案 ------ 将 Nginx 和 Apache 分到不同端口或不同 IP 上监听。
方案 A:Nginx 监听 80,Apache 监听 8080
修改 Apache 监听端口:
bash
sudo sed -i 's/Listen 80/Listen 8080/' /etc/apache2/ports.conf
修改所有默认虚拟主机:
<VirtualHost *:8080>
ServerName api.example.com
...
</VirtualHost>
重启 Apache:
bash
sudo systemctl restart apache2
此时 ss -tulnp 显示:
tcp LISTEN 0 128 *:80 *:* users:(("nginx",pid=1234))
tcp LISTEN 0 128 *:8080 *:* users:(("apache2",pid=2345))
确保不冲突后,再检查反向代理。
方案 B:使用不同 IP
如果服务器有多个公网 IP,将 Apache 绑定到特定 IP:
bash
Listen 192.0.2.100:80
Nginx 绑定另外一个 IP:
bash
listen 192.0.2.101:80;
方法二:统一由 Nginx 作为前端反向代理
这种方式我们通过 Nginx 进行统一调度,将 Apache 部署在内网端口(如 8080),Nginx 负责路由:
Nginx 示例配置:
nginx
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
然后 Apache 在 8080 上运行,只处理内部请求,不直接对外:
bash
Listen 127.0.0.1:8080
六、验证反向代理
1. Apache 反向代理配置示例(如果独立运行)
启用模块:
bash
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
默认配置 /etc/apache2/sites-available/api.conf:
apache
<VirtualHost *:8080>
ServerName api.example.com
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8081/
ProxyPassReverse / http://127.0.0.1:8081/
ErrorLog ${APACHE_LOG_DIR}/api_error.log
CustomLog ${APACHE_LOG_DIR}/api_access.log combined
</VirtualHost>
注意 :若 Apache 与 Nginx 共存,Listen *:8080 更稳妥。
重启:
bash
sudo systemctl restart apache2
访问:
bash
curl -I http://example.com/api
HTTP/1.1 200 OK
成功返回就表明反向代理生效。
七、性能与细节优化
1. 内核参数优化
对于高并发连接,编辑 /etc/sysctl.conf:
bash
net.core.somaxconn = 4096
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_tw_reuse = 1
生效:
bash
sudo sysctl -p
2. Apache 连接池与 MPM
对于 Apache 反向代理高并发场景,推荐使用 mpm_event:
bash
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
调整 /etc/apache2/mods-available/mpm_event.conf:
apache
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestWorkers 400
八、故障排查技巧总结
| 排查项 | 检查命令 | 典型提示 | 意义 |
|---|---|---|---|
| 端口监听冲突 | ss -tulnp |
80 被两个进程监听 | 端口冲突 |
| 日志错误 | tail error.log |
Bind 错误 | 服务无法启动 |
| 进程状态 | systemctl status |
Failed | 配置错误 |
| 网络连通性 | curl -I |
502/504 | 反代失败 |
九、总结
Nginx 与 Apache 在同一台 Ubuntu 22.04 机上共存时,最常见的问题是端口监听冲突和反向代理配置不当。通过如下步骤:
- 检查端口监听与冲突;
- 明确端口策略或使用不同 IP ;
- 确认反向代理模块和配置是否正确;
- 合理调优内核和服务器参数;
可以迅速定位并解决无法访问后端应用的问题。希望本文深入剖析的过程和实战技巧,能为你在类似场景下提供帮助。