Nginx下构建PC站点说白了就是把一台普通服务器变成能对外提供网页服务的入口让用户用电脑浏览器输入域名后能正常打开你的网站。我这些年经手过的大小项目里面向PC的官网、资讯站、活动落地页、前后端分离的管理后台最终基本都落在Nginx这一层。原因很直接它处理静态文件的能力强、配置轻量、转发逻辑清晰而且出问题的时候日志和排查路径都很成熟。这篇内容适合两类人——刚接触服务器、想独立把一个PC站点跑起来的开发者以及已经接了Nginx但配置全靠复制粘贴、报错只能到处搜资料的运维新手。我会从目录规划讲到缓存策略把每一步为什么要这么做一起说清楚。1. 先理清Nginx构建PC站点的核心思路1.1 PC站点与普通Web服务有什么不一样PC站点指的是主要面向桌面浏览器访问的网站和移动端页面相比有几个明显特点。屏幕尺寸普遍在1280像素以上页面布局宽一次加载的图片、JS、CSS资源通常比移动端页面大不少用户大多通过域名直接进入对首次打开速度很敏感交互方式以鼠标点击为主路由跳转、异步请求更频繁。这些特点决定了部署思路不能照搬移动端H5那套。PC站点的资源体积大就需要在静态文件响应上做好缓存和压缩异步请求多就需要把Nginx和后端服务之间的连接参数调得足够顺手如果站点是前后端分离的架构前端产物是一堆静态文件后端接口单独部署在一台或多台服务上Nginx就承担了“把静态资源直接返回给浏览器、把接口请求转给后端进程”的双重角色。想清楚这个分工后面所有配置就都有了主线。1.2 从目录规划开始动手动手配置之前我建议先想清楚站点属于哪一类。如果是一个纯静态展示站所有内容都是HTML、CSS、JS、图片服务器上不需要跑任何应用进程Nginx直接找到文件返回就行了。如果是有后台功能的PC站点比如登录、查数据、提交表单那就要区分静态资源和接口地址配置里需要单独维护一段转发规则。无论哪种类型目录规划都建议按站点隔离。我的习惯是在服务器上建一个总目录比如/www/pc-site下面放三类东西dist放前端构建产物logs放该站点的访问日志和错误日志conf放这个站点自己的Nginx配置片段。这样多站点部署时互不干扰日志排查也不用跑到全局日志里翻半天。2. 环境准备与基础安装2.1 Nginx安装与默认目录说明在主流Linux发行版上安装Nginx通常用系统自带的软件包管理工具就能完成不需要编译安装。以Debian系为例更新索引后直接安装sudo apt update sudo apt install nginx -y安装完成后Nginx会自动注册成系统服务可以用systemctl status nginx查看运行状态。默认的站点根目录通常在/var/www/html全局配置在/etc/nginx/nginx.conf日志在/var/log/nginx/下access.log记录访问error.log记录错误。不同的发行版对站点配置文件的组织方式不太一样。有的是sites-available和sites-enabled两套目录搭配软链接有的直接用conf.d。我建议统一用conf.d来管理因为它更直观每个站点一个.conf文件名字一眼能看出来是哪个项目启用和停用只需要增删文件然后重载。确认nginx.conf的http块里有一行include /etc/nginx/conf.d/*.conf;没有就手动加上。2.2 第一份能跑起来的PC站点配置假设前端构建产物已经上传到/www/pc-site/dist目录下有index.html和一堆资源文件。新建一个站点配置直接指向这个目录server { listen 80; server_name example.com; root /www/pc-site/dist; index index.html; }几个关键参数说明一下。listen 80表示监听HTTP默认端口server_name表示匹配哪个域名访问时使用这个配置块root定义了站点的根目录index指定当请求路径是目录时默认返回的文件。写完配置后先检查语法再重载sudo nginx -t sudo systemctl reload nginxnginx -t会检查配置文件有没有语法错误提示syntax is ok才能继续。重载会平滑地应用新配置不会中断正在处理的请求不要用restart尤其在生产环境restart会瞬间断开所有连接。3. 静态资源与接口转发的正确姿势3.1 root、index、alias怎么用才不出错root和alias是很多新手最容易搞混的一组指令。root会把整个location的匹配路径拼到根目录后面而alias会用配置里的路径替换掉location的前缀。举个例子如果你的PC站点目录里有一个static子目录希望请求/static/logo.png时返回/www/pc-site/dist/static/logo.png用root这样写location /static/ { root /www/pc-site/dist; }Nginx拼接后的实际路径是/www/pc-site/dist/static/logo.png因为root后面的路径会加上完整请求URI。如果资源实际存放在/www/pc-site/assets/下但希望通过/static/这个路径访问就需要用aliaslocation /static/ { alias /www/pc-site/assets/; }此时请求/static/logo.pngNginx会去找/www/pc-site/assets/logo.png。多数404问题都出在这里root配了不存在的完整路径或者alias少了末尾的斜杠导致路径拼接出错。另外如果PC站点用了前端框架的history路由刷新一个子页面时请求的是/about这样的真实路径但服务器上没有这个文件会直接404。这种情况用try_files兜底location / { root /www/pc-site/dist; try_files $uri $uri/ /index.html; }流程是先尝试按原路径找文件再尝试把它当目录处理都找不到就返回index.html让前端框架自己去解析路由。这个配置对单页应用几乎是标配。3.2 静态资源缓存策略PC站点的静态资源文件一般很大如果每次访问都从磁盘完整读出既浪费带宽也拖慢速度。Nginx默认不会主动给响应加长缓存头需要自己配置location ~* \.(css|js|jpg|png|gif|svg|ico|woff2?)$ { expires 30d; add_header Cache-Control public, max-age2592000; }expires 30d会告诉浏览器这个文件可以缓存30天同时自动生成Expires响应头。Cache-Control里的public表示浏览器和中间缓存都可以存一份max-age单位是秒2592000就是30天。这里有一个原则性的坑HTML文件本身不要设长缓存。因为HTML是入口通常会引用带版本号的CSS和JS如果入口被缓存住用户就永远看不到新发布的内容。给HTML单独设成不缓存或者短缓存location ~* \.(html)$ { add_header Cache-Control no-cache; }no-cache的意思是每次使用之前都要回服务器确认一下文件没变就用本地缓存变了就拉新的。配合前端构建时的文件名hash机制就能做到“改过的文件立刻更新没改的文件继续用缓存”这是PC站点上线后保证用户能看到新版本的关键。3.3 接口转发与后端服务参数PC站点有登录、查询等动态功能时前后端分离是常见架构。前端静态文件由Nginx返回接口请求统一走某个路径前缀比如/api/转发给内网的后端服务location /api/ { 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; proxy_connect_timeout 5s; proxy_read_timeout 30s; }proxy_pass是把这个location下的请求转给后端的8080端口后端再返回结果给Nginx最后由Nginx回应浏览器。proxy_set_header里的三行很重要Host保留原始域名后端才能判断出该处理哪个站点的请求X-Real-IP和X-Forwarded-For把用户真实IP传给后端否则后端看到的全是127.0.0.1没法做IP维度的分析和限制。超时参数容易被忽略。proxy_connect_timeout 5s是Nginx和后端建立连接的最大等待时间proxy_read_timeout 30s是等待后端返回数据的最大时间。如果不设置默认值可能长达几十秒用户点一个按钮转圈半分钟体验会非常糟糕。3.4 HTTPS证书落地与HTTP跳转现在的PC站点基本都应该上HTTPS哪怕只是一个静态展示页。证书文件申请下来之后放到站点目录下的ssl文件夹里配置如下server { listen 443 ssl; server_name example.com; ssl_certificate /www/pc-site/ssl/example.com.pem; ssl_certificate_key /www/pc-site/ssl/example.com.key; ssl_protocols TLSv1.2 TLSv1.3; root /www/pc-site/dist; index index.html; }同时把原来的80端口配置改成自动跳转到HTTPSserver { listen 80; server_name example.com; return 301 https://$host$request_uri; }这样用户访问http://开头的地址时会收到301重定向浏览器自动换成https://。return 301适合做整站跳转不会损失SEO权重。上HTTPS之后浏览器地址栏的锁标能大幅提升用户信任感也避免PC站点在办公网络或企业环境中被内容类安全设备拦截。4. 性能、安全与日志调优经验4.1 gzip压缩让PC页面瘦一圈PC站点的HTML、JS、CSS都是纯文本压缩率非常高。开启gzip后传输体积通常能减少60%以上。在nginx.conf的http块里加上gzip on; gzip_min_length 1k; gzip_comp_level 5; gzip_types text/plain text/css application/json application/javascript application/xml image/svgxml;gzip_min_length 1k表示小于1KB的文件不压缩因为压缩小文件消耗的CPU比传输节省得还多不划算。gzip_comp_level不建议超过6级别越高CPU占用越大压缩率的提升已经很有限我长期用5效果和性能比较均衡。图片类的jpg、png本身已经是压缩格式不需要再gzip强行压缩反而会增大CPU开销。woff2字体文件也一样不用进gzip列表。4.2 常见的Nginx并发参数调整PC站点如果遇到大流量默认配置不一定够用。nginx.conf里几个核心参数值得单独看worker_processes auto; worker_connections 1024; keepalive_timeout 65;worker_processes auto让Nginx按CPU核心数创建进程worker_connections定义了每个工作进程能同时保持的最大连接数keepalive_timeout控制客户端长连接的空闲超时。PC站点用户打开页面后会连续请求HTML、CSS、JS、图片等多个资源长连接能让这些请求复用同一个TCP连接大大减少握手耗时。这几个参数不是越大越好。worker_connections调高需要同时考虑服务器的内存和文件句柄数限制如果盲目改成65535连接数没上来系统先扛不住了。实际调整时先看当前连接量再决定后面第6章会讲验证方法。4.3 隐藏版本信息与基础安全加固Nginx默认会在响应头里暴露版本号比如Server: nginx/1.24.0。版本号公开后等于把系统信息展示给所有人某些自动化扫描工具会针对旧版本漏洞直接尝试攻击。关掉这个输出server_tokens off;对于只提供页面访问的PC站点可以对HTTP方法做限制。正常浏览器行为无非是GET、HEAD、POST如果收到PUT、DELETE这类非预期方法直接返回405limit_except GET HEAD POST { deny all; }这里面limit_except的作用就是“除了括号里的方法其他一律拒绝”。比用if判断更干净也避免Nginx官方文档多次警告过的if使用风险。接口容易被脚本反复调用时可以做简单的访问频率限制。在http块定义规则limit_req_zone $binary_remote_addr zonepc_api:10m rate10r/s;在location /api/里引用location /api/ { limit_req zonepc_api burst20 nodelay; proxy_pass http://127.0.0.1:8080; }这样同一个IP默认每秒最多请求10次允许突发20个请求超过的会直接返回503。配置好了PC站点即使遇到扫接口的程序后端服务也能稳得住。4.4 日志格式、错误页与日志轮转访问日志默认格式信息量有限建议自定义一个更完整的格式log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent;然后在server块里指定使用access_log /var/log/nginx/pc-site.access.log main; error_log /var/log/nginx/pc-site.error.log warn;日志按站点独立存放排查问题的时候只看自己站点的文件效率高很多。访问日志会无限增长所以一定要配上日志轮转。主流发行版都自带了logrotate只需在/etc/logrotate.d/nginx下配置按天切割、保留多少份即可默认的nginx配置文件一般已经存在确认里面的日志路径包含了你的站点日志文件。错误页也别用Nginx默认的白底黑字至少换成自己设计的页面error_page 403 /403.html; error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location /403.html { root /www/pc-site/error_pages; internal; }internal表示这个地址只能由Nginx内部跳转访问用户无法直接请求。PC站点自定义错误页对品牌形象影响很大比默认丑陋页面能减少很多无效工单。5. 常见问题排查与避坑实录5.1 打开页面返回404问题多半在路径404是最常见的报错原因集中在三块一是root或alias路径写错文件实际不在那个目录二是站点文件没有上传到对应位置三是前端路由的try_files没有配置。排查第一步先确认Nginx返回404时实际去找的是哪个路径。用curl -I请求页面看响应头不会有太多信息更直接的方法是打开错误日志看末尾的open() failed信息那一行会明确写出文件路径。接着用ls检查这个路径下的文件是否存在、文件名是否大小写一致。Linux路径是区分大小写的Index.html和index.html完全是两个文件。5.2 页面403权限问题优先排查403表示Nginx找到了文件路径但没有权限读取。常见的错误操作是chmod -R 777给整个目录全部权限这种做法隐患很大。正确的做法是目录要755可读可执行但没有写权限文件要644所有者可写其他人只读。执行sudo chown -R www-data:www-data /www/pc-site sudo find /www/pc-site/dist -type d -exec chmod 755 {} \; sudo find /www/pc-site/dist -type f -exec chmod 644 {} \;如果Nginx的工作进程用户不是www-data需要先确认编译或安装时的用户再替换成对应用户名。对PC站点来说权限问题经常发生在用root上传文件之后默认文件属主是rootNginx进程跑在www-data下读不了所以上传后统一调整属主是非常必要的。5.3 接口返回502或504先分清是谁的问题502 Bad Gateway表示Nginx把请求转给后端但后端没有成功应答。可能原因有后端进程没启动、监听端口变了、防火墙拦截、后端启动后崩溃。先在服务器上检查端口ss -tlnp | grep 8080能看到监听说明服务在跑再用curl http://127.0.0.1:8080/api/health直接请求后端本机地址如果返回正常问题就在proxy_pass配置或者网络链路如果直接拒绝连接基本是后端进程的问题。504 Gateway Timeout则表示后端进程在但响应时间超过了Nginx等待上限。这个时候优先调大proxy_read_timeout同时看后端日志里有没有慢查询或阻塞调用。注意排查时不要一上来就调超时超时只是表象根因往往在后端处理的效率上。5.4 配置改了但没生效几个隐蔽原因我遇到过几次“明明改完配置也reload了但访问行为没变”的情况。第一改错了文件。站点实际加载的是conf.d/pc-site.conf却一直改nginx.conf检查方式是在nginx.conf头部注释前用nginx -T输出全部生效配置再搜索你的站点关键词。第二同一server_name出现了两遍Nginx会优先匹配第一个修改的却是第二个。第三浏览器缓存了旧页面尤其是HTML被设成expires 30d之后改了什么配置用户都看不到新页面需要在无痕窗口里验证。还有一类容易被忽略的问题server_name不匹配导致走了默认站点。如果你用服务器IP访问而server_name里只写了域名请求会落到Nginx的默认server块。测试环境用IP访问时要么把IP也写进server_name要么在listen 80后面加default_server参数。5.5 跨域报错与缓存头互相干扰PC站点对接接口时如果前端域名和后端域名不一致浏览器会拦截跨域请求。通常在后端或Nginx加上Access-Control-Allow-Origin响应头可以解决add_header Access-Control-Allow-Origin $http_origin always; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-Headers Authorization, Content-Type;这里用$http_origin而不是写死*是因为带上用户自己的Origin更安全也兼容需要带Authorization头的请求。always参数确保即使出错也能返回这个头。有个细节需要注意如果同一个location同时配置了add_header Cache-Control和add_header Access-Control-Allow-OriginNginx会在某些情况下只输出第一条add_header导致浏览器拿到缓存头却没有跨域头。解决办法是确认两条add_header在同一个location里都写了不要分成外层和内层两个地方。6. 上线检查与验证6.1 多站点场景的配置组织方式一个Nginx上可能同时跑多个PC站点每个站点一个独立配置文件是最清晰的组织方式。比如/etc/nginx/conf.d/下放置# pc-site-a.conf server { listen 80; server_name a.example.com; root /www/pc-site-a/dist; } # pc-site-b.conf server { listen 80; server_name b.example.com; root /www/pc-site-b/dist; }Nginx会根据请求头里的Host字段自动匹配对应的server_name同一个IP和端口可以服务任意多个域名。维护上要注意几点日志文件各自独立配置里不要写重复的server_name新加的配置先单独nginx -t再重载。公共的缓存、gzip设置在nginx.conf的http块里做站点个性化配置放在各自的server块里。6.2 部署前的自检和简单压测每次变更都要做一套自检动作。先检查语法再重载然后用curl验证本机响应sudo nginx -t sudo systemctl reload nginx curl -I http://127.0.0.1/看返回的HTTP/1.1 200、Content-Type、Content-Length是否符合预期。如果你已经配了HTTPS再加上curl -I https://example.com/确认证书没有过期、没有混合内容警告。上线前做一次简单的并发验证是值得的用ab工具就能完成ab -n 1000 -c 100 http://example.com/-n 1000表示总共发起1000个请求-c 100表示同时100个并发。跑完后看Requests per second和Failed requests两个指标。如果失败率不为0或者每秒请求数低得离谱说明配置或机器资源有问题。压测的时候注意工具和Nginx最好不在同一台机器上否则压测本身会占用CPU和网络测出来的数据失真。真实上线流量会比这个小规模压测复杂得多但至少能暴露明显的配置错误。最后说一个我自己的体会Nginx配置本身不复杂难的是一旦把几个站点、缓存、HTTPS、日志全堆在一个文件里还硬撑着不拆分后面维护全是坑。按目录隔离、按功能分文件、每改一处都先nginx -t这套习惯养成了PC站点的日常维护基本就是半个小时的活。搭完第一个站点之后强烈建议把HTTPS跳转和按天日志切割补上——这两件事做在前面后面能省掉大量沟通和排查成本。
阅读完成 · 觉得有帮助?