6.4 综合实战:搭建一台生产级服务器 本节摘要:把全书拼装成一台真实的服务器。场景设定:一台 8GB 内存的机器,要跑一个内容站(静态资源 + PHP 动态页)加一个后端 API 服务,要求 HTTPS、HTTP/2、负载均衡、缓存、安全基线齐备。本节按部署顺序走完全流程——每一步都标注"用到了第几章的什么知识",最后交付上线检查单与故障预案。这是全书旅程的终点站。 学习目标 阅读完本节,你应当能够: 按顺序完成从裸机到生产的完整部署; 写出整合 MPM、虚拟主机、代理、缓存、TLS 的完整配置; 执行上线前的分项验证与整体验收; 为这台服务器制定监控与故障预案。
本节摘要:把全书拼装成一台真实的服务器。场景设定:一台 8GB 内存的机器,要跑一个内容站(静态资源 + PHP 动态页)加一个后端 API 服务,要求 HTTPS、HTTP/2、负载均衡、缓存、安全基线齐备。本节按部署顺序走完全流程——每一步都标注"用到了第几章的什么知识",最后交付上线检查单与故障预案。这是全书旅程的终点站。
阅读完本节,你应当能够:
先立需求:内容站主域名(下面配置里的 example 主机,静态资源为主、栏目页 PHP 渲染)、API 前缀转给两台内网应用服务器;预期峰值并发 400,静态动态约 7:3;全站 HTTPS。
容量推导(第 2 章公式):8GB 内存,系统与监控占 1.5GB,PHP-FPM 按每进程 40MB 算 30 个进程约 1.2GB,留给 httpd 约 5GB。选 event MPM,单线程增量小,MaxRequestWorkers 设 600(ServerLimit 12 × ThreadsPerChild 50),并留出余量给突发。KeepAliveTimeout 用 15 秒——event 模型下闲置便宜(第 2 章的结论在这里兑现)。
模块清单(第 1、4 章原则):event、ssl、http2、proxy、proxy_http、proxy_fcgi、proxy_balancer、rewrite、headers、expires、deflate、cache、cache_disk、reqtimeout、log_config、status——按需加载,不用的一个不装。
部署顺序本身是方法论:先地基后上层,每阶段可独立验证,出问题的回滚半径永远只有一个阶段。
阶段一:地基(第 2 章)。 安装、目录结构、服务自启,六步验证清单走一遍:语法检查、端口监听、进程树、本机 200、模块基线、时钟同步。
阶段二:MPM 与全局参数(第 2 章)。 切 event、写参数组、KeepAlive。验证:httpd -V 显示 event;压一轮静态页确认基线吞吐。
阶段三:站点与内容(第 3、4 章)。 默认站点拒绝一切;内容站虚拟主机、静态长缓存(指纹方案)、PHP 对接 FPM。验证:curl 带 Host 头访问各路径,静态 200 且带长缓存头、php 页经 FPM 执行、点文件与版本控制目录一律 403。
阶段四:代理与后端(第 4 章)。 均衡器两成员加健康检查、透传三件套、ProxyTimeout。验证:停一台后端循环请求全 200;后端日志能看到真实客户端 IP。
阶段五:HTTPS 与 HTTP/2(第 5 章)。 证书与 fullchain、协议基线、会话缓存、OCSP 装订、h2、80 端口 301。验证:openssl 看证书链、curl 的 http2 选项确认 h2 生效、重定向链完整。
阶段六:安全与观测(第 6 章)。 信息泄露治理、方法收敛、安全头、慢速攻击防御、HSTS(短 max-age 灰度)、自定义含耗时的日志、轮转。验证:攻击者视角逐项试探全被挡。
关键片段按片段目录组织(结构第 2 章讲过)。全局层:
# ---- 全局:安全基线与服务器参数 ---- ServerTokens Prod ServerSignature Off TraceEnable Off Listen 80 Listen 443 Protocols h2 http/1.1 # 慢速攻击防御 RequestReadTimeout header=20-40,minrate=500 body=10,minrate=500
# ---- 默认站点:接垃圾 ---- <VirtualHost *:80 *:443> ServerName default.invalid <Location /> Require all denied </Location> </VirtualHost>
内容站主虚拟主机:
<VirtualHost *:443> ServerName www.example.com DocumentRoot /var/www/example SSLEngine on SSLCertificateFile /etc/ssl/example/fullchain.pem SSLCertificateKeyFile /etc/ssl/example/privkey.pem SSLProtocol -all +TLSv1.2 +TLSv1.3 SSLSessionCache "shmcb:/var/run/ssl_scache(512000)" SSLUseStapling On # 安全响应头 Header always set Strict-Transport-Security "max-age=300" Header always set X-Content-Type-Options "nosniff" Header always set X-Frame-Options "SAMEORIGIN" # 静态长缓存(指纹方案 · 第5章) <IfModule mod_expires.c> ExpiresActive On ExpiresByType image/png "access plus 1 year" ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" </IfModule> # 栏目页服务器缓存 CacheEnable disk /news CacheDefaultExpire 300 # PHP 经 FPM <FilesMatch \.php$> SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" </FilesMatch> # API 转发到后端池 <Proxy balancer://api> BalancerMember http://10.0.1.11:9000 hcmethod=GET hcuri=/health hcfails=2 hcinterval=10 BalancerMember http://10.0.1.12:9000 hcmethod=GET hcuri=/health hcfails=2 hcinterval=10 </Proxy> ProxyPass /api balancer://api/api ProxyPassReverse /api balancer://api/api ProxyTimeout 30 RequestHeader set X-Forwarded-Proto "https" # 封点文件与备份文件 <FilesMatch "^\.|~$|\.bak$"> Require all denied </FilesMatch> # 含耗时的日志 LogFormat "%h %t \"%r\" %>s %b %Dus %{X-Cache}o" perflog CustomLog ${APACHE_LOG_DIR}/example-access.log perflog </VirtualHost> # ---- 80 全站301 ---- <VirtualHost *:80> ServerName www.example.com RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] </VirtualHost>
这份配置没有一行是新知识——每一块都来自前五章,这也是本节的目的:证明你已经具备的零件能拼出一台完整机器。

分项验证之外,整体验收跑一轮"全链路剧本":新用户首次访问(握手、h2、无缓存全量加载)、回访用户(强缓存命中、304)、API 调用(均衡器分发、透传头正确)、攻击试探(点文件、TRACE、慢速)各一组用例,每项记录预期与实测。
上线后 72 小时是观察期,盯四个指标:错误率(应近零)、95 分位延迟(对照压测基线)、内存水位(验证容量推导)、后端健康(均衡器状态页成员状态)。观察期结束,把 HSTS 的 max-age 提到一年,机器正式转正。
故障预案提前写好:后端单机宕机(自动转移,无需人工)、证书续期失败(告警加手动重载流程)、流量突增(扩容或临时限流的操作步骤)。预案的价值在于"半夜不需要思考"。
从第 1 章那张十站流程图出发,这台服务器上的每个请求仍在走同样的路——但现在你知道:端口后面是 event 的线程池(第 2 章),工单来自虚拟主机与合并规则(第 3 章),干活的是代理与 FPM(第 4 章),归途有缓存、压缩与 TLS 三道工序(第 5 章),全程被安全基线与日志看护(第 6 章)。所谓"配置与优化",不过是给旅程的每一站找到合适的人手与规则。往后遇到任何新问题,回到那张图,定位站点,翻对应章节——这本书的使命到此完成。
💡 全书最后一句话:一个请求的旅程讲完了;你的运维旅程,从这台服务器上线才刚开始。