Apache —— Web 服务器的"老贵族"

Apache —— Web 服务器的"老贵族"
Apache —— Web 服务器的"老贵族",三分天下有其一

一、先说两句

在 Nginx 流行之前,整个互联网的 Web 服务器只有一个名字:**Apache**。

它 1995 年出生,比 Google 还早。到 2000 年代初期,全球超过 60% 的网站跑在 Apache 上。虽然现在被 Nginx 超过了,但仍然有大约 **三分之一的网站** 在使用它。

Apache 的全称是 **Apache HTTP Server**(也叫 httpd)。它的诞生故事很有意思——最初是一个叫 NCSA 的 Web 服务器项目停了,一群开发者自己打补丁维护,最后拼凑出一个新项目,取名 "A Patchy Server"(一堆补丁的服务器),后来演变成了 Apache。

它的核心设计哲学和 Nginx 完全相反:

```
Nginx 的理念:
  功能少而精,能做的就几件事,但每件都做到极致
  配置集中管理,严格而清晰

Apache 的理念:
  功能多而全,什么都能做,靠模块堆能力
  配置极度灵活,每个目录都能单独改
```

这两种理念没有对错,只是取舍不同。**Nginx 选择了性能和简洁,Apache 选择了兼容和灵活。**

这也是为什么在 2025 年的今天,Apache 仍然有它的生存空间——有些场景下,灵活比性能更重要。


二、Apache 为什么能活三十年?

**1. 模块化架构 —— 想要什么功能就加载什么功能**

Apache 的核心很轻量,几乎一切功能都是通过模块(Module)实现的:

```bash
Apache 的模块系统:
核心功能 → 啥也没有,就一个 HTTP 服务器骨架
加模块  → 加功能

常见模块:
  mod_php      → 直接处理 PHP(不用 PHP-FPM)
  mod_ssl      → HTTPS 支持
  mod_rewrite  → URL 重写(伪静态)
  mod_proxy    → 反向代理
  mod_alias    → 路径别名
  mod_auth     → 用户认证
  mod_deflate  → Gzip 压缩
  mod_cache    → 缓存
  mod_status   → 服务器状态监控
  mod_security → Web 应用防火墙(WAF)
  … 还有上百个
```

**想用哪个加载哪个,不想用就不加载。** 这让 Apache 可以极其轻量(只装需要的模块),也可以极其强大(全模块加载)。

**2. .htaccess —— 每个目录都能独立配**

这是 Apache 最独特、也最受争议的功能。

```bash
# Nginx:改配置要编辑 /etc/nginx/nginx.conf
# 改完要 nginx -s reload
# 普通用户没权限碰配置

# Apache:每个目录放一个 .htaccess 文件
# 改完即时生效,不需要重启
# 不需要 root 权限

# .htaccess 能做到的事情:
RewriteEngine On
RewriteRule ^article/([0-9]+)$ /show.php?id=$1 [L]

AuthType Basic
AuthName "Restricted Area"
AuthUserFile /path/to/.htpasswd
Require valid-user

Redirect 301 /old-page.html /new-page.html
```

对**虚拟主机用户**来说,.htaccess 就是神——你不需要联系服务器管理员,自己上传一个文件就能改网站的行为。

对**系统管理员**来说,.htaccess 是噩梦——每次请求都要检查每个目录有没有 .htaccess 文件,性能开销不小。

**3. 兼容性 —— 什么老项目都能跑**

Apache 对老技术的支持是最好的:

```bash
Apache 还在支持的东西(Nginx 不爱管的):
  - CGI 脚本(1993 年的技术)
  - SSI(Server Side Includes,1995 年的模板技术)
  - mod_perl(直接在 Apache 里跑 Perl)
  - .htpasswd 基本认证(最古老但最简单的登录方式)
  - FTP 集成(某些发行版)
  - IPv4/IPv6 双栈(很早就支持了)
  - 各种认证后端(LDAP、DBM、SMB……)
```

如果你的公司还有**跑了十几年的老系统**,大概率跑在 Apache 上。不是因为它有多好,而是因为它兼容一切。

**4. 动态内容处理 —— mod_php 的便利**

LNMP 架构里,PHP 是通过 PHP-FPM 单独跑的,Nginx 用 FastCGI 连上去。

Apache 的处理方式简单得多:

```apache
# 加载 PHP 模块
LoadModule php_module modules/libphp.so

# 告诉 Apache .php 文件交给 PHP 处理
<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>
```

**没有独立的 PHP 进程、没有 FastCGI 的配置、没有 socket 连接。** PHP 直接在 Apache 进程里运行,配置简单到极致。

当然,这也意味着每个 Apache 进程都要带着 PHP 解释器,内存占用更大。**简单和性能,总得选一个。**


三、Apache 的两种工作模式

Apache 有两种处理请求的方式,直接影响性能和内存占用:

**1. Prefork(预派生)模式**

```bash
# 配置
<IfModule mpm_prefork_module>
    StartServers        5      # 启动时创建 5 个进程
    MinSpareServers     5      # 最少空闲 5 个
    MaxSpareServers     10     # 最多空闲 10 个
    MaxRequestWorkers   150    # 最多 150 个进程同时工作
    MaxConnectionsPerChild 10000  # 每个进程处理 10000 个请求后重启
</IfModule>
```

特点:
```
✅ 每个请求一个独立进程,互不干扰(一个挂了不影响别的)
✅ 兼容所有模块(包括 mod_php)
❌ 内存占用大(150 个进程 × 每个几十 MB = 好几个 GB)
❌ 并发能力有限
```

**适合:** 跑 PHP 的网站、需要 mod_php 的场景、稳定性优先的应用。

**2. Worker(混合线程)模式**

```apache
# 配置
<IfModule mpm_worker_module>
    StartServers        3
    MinSpareThreads     75
    MaxSpareThreads     250
    ThreadsPerChild     25
    MaxRequestWorkers   400
    MaxConnectionsPerChild 10000
</IfModule>
```

特点:
```
✅ 每个进程里开多个线程,每个线程处理一个请求
✅ 内存比 Prefork 小得多
✅ 并发能力比 Prefork 强
❌ 不能加载 mod_php(PHP 很多函数不是线程安全的)
❌ 一个线程挂了可能影响同一进程的其他线程
```

**适合:** 纯静态内容、代理场景、不用 mod_php 的应用。

**3. Event 模式(Apache 2.4+,推荐)**

```apache
<IfModule mpm_event_module>
    StartServers        3
    MinSpareThreads     75
    MaxSpareThreads     250
    ThreadsPerChild     25
    MaxRequestWorkers   400
    MaxConnectionsPerChild 10000
</IfModule>
```

特点:
```
✅ 在 Worker 基础上改进了长连接的处理(空闲连接不占用线程)
✅ Apache 2.4 以后性能最好的模式
✅ 接近 Nginx 的事件驱动效果
❌ 仍然不能加载 mod_php(和 Worker 一样的问题)
```

**这个模式让 Apache 在高并发下的表现改善了很多**,虽然还是比不上 Nginx,但差距缩小了很多。


四、最常用的配置

**1. 虚拟主机 —— 一个 Apache 跑多个网站**

```apache
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com

    <Directory /var/www/example.com>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
</VirtualHost>

<VirtualHost *:80>
    ServerName another.com
    DocumentRoot /var/www/another
    <Directory /var/www/another>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

**2. URL 重写(伪静态)—— 靠 mod_rewrite**

这是 Apache 最常用的功能之一:

```apache
RewriteEngine On
RewriteRule ^article/([0-9]+)$ /show.php?id=$1 [L,QSA]
RewriteRule ^category/([a-z]+)$ /list.php?cat=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L]
```

WordPress 的 .htaccess 就是最经典的例子:
```apache
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
```

这四行就是 WordPress 伪静态的核心——如果请求的不是真实文件或目录,全部转发给 index.php。

**3. HTTPS**

```apache
<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /var/www/example.com

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem

    <Directory /var/www/example.com>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

# HTTP → HTTPS 跳转
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>
```

**4. 反向代理**

```apache
<VirtualHost *:80>
    ServerName app.example.com

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/

    <Location />
        Require all granted
    </Location>
</VirtualHost>
```


五、Apache vs Nginx —— 现在还选 Apache 吗?

| 维度 | Apache | Nginx |
|------|--------|-------|
| 架构 | 进程/线程 | 事件驱动(异步) |
| 静态文件性能 |
👤
hermes
AiTech 技术博客,专注于计算机技术、云计算、编程开发和 AI 前沿领域的深度报道与技术分析。
文章评论 0 条
U
👍 👎 @
K
Kevin
2 小时前
Rust 的 async 生态终于要完善了!Async Iterator 和 async closure 这两块一直是我觉得最欠缺的。期待今年的进展!
👀 12 💬 回复
S
Sarah
5 小时前
编译速度优化这块太重要了,我们项目从 5 分钟降到 2 分钟就是巨大的效率提升。期待并行前端解析的上线。
👀 8 💬 回复

🎨 配色自定义设置