练镇中 發表於 2024-11-1 12:05:00

不敢相信,Nginx 还能这么玩?

<p class="md-end-block md-heading"><span class="md-plain">大家好,我是程序员鱼皮。今天来聊聊 Nginx 技术,这是一个企业项目必用,但是却经常被程序员忽略的技术。学好 Nginx,可以助你在求职中脱颖而出。</span></p>
<p class="md-end-block md-p"><span class="md-plain">或许你会想:“Nginx 不就是用来部署网站的服务器嘛?这有何难?”</span></p>
<p class="md-end-block md-p"><span class="md-plain">但其实这不过是九牛一毛罢了,Nginx 的实用操作和使用技巧还多着呢,下面这篇文章,就带大家轻松入门 Nginx、并且循序渐进地学习 Nginx 真正的用法!</span></p>
<blockquote>
<p class="md-end-block md-p"><span class="md-plain">推荐观看本文对应的视频版本,有更多操作演示哦:<span class="md-link md-pair-s">https://bilibili.com/video/BV1TW1LYkE59</span></span></p>
</blockquote>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">一、Nginx 入门 - 牛刀小试</span></h2>
<p class="md-end-block md-p"><span class="md-plain">首先要了解什么是 Nginx?注意读音,是 Engine X,而不是恩静因克斯。</span></p>
<p class="md-end-block md-p"><span class="md-plain">根据官方定义,它是世界上最受欢迎的 Web 服务器、高性能负载均衡器、反向代理、API 网关和内容缓存。</span></p>
<p class="md-end-block md-p"><span class="md-plain">虽然听不懂,但是感觉很厉害的样子。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111843818-16e71e5f-7b5f-4a15-a06e-b9224c5e3f19.jpeg"><img src="https://pic.yupi.icu/1/1730111843818-16e71e5f-7b5f-4a15-a06e-b9224c5e3f19.jpeg"></span></p>
<p class="md-end-block md-p"><span class="md-plain">简单来说,Nginx 不仅能部署网站,而且相比其他的 Web 服务器,它能够用更少的资源,同时处理更多用户的请求,让网站速度更快更稳定,这也是企业选择 Nginx 的原因。</span></p>
<p class="md-end-block md-p"><span class="md-plain">下面我们就牛刀小试,用 Nginx 启动一个网站!</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">1、Nginx 安装</span></h3>
<p class="md-end-block md-p"><span class="md-plain">首先我们需要安装 Nginx ,先到官网中根据操作系统下载一个稳定版本的压缩包,下载完成之后解压一下。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729138488833-938c5c6a-cd30-4743-8bb2-fda7fdc3164d.png"><img src="https://pic.yupi.icu/1/1729138488833-938c5c6a-cd30-4743-8bb2-fda7fdc3164d.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">如果是 Windows 系统,双击 exe 文件启动即可;如果是 Mac 或 Linux 系统,可以打开终端并进入该目录,手动编译安装后执行 Nginx 命令启动。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729133895506-5d74012a-0d82-43bc-aac7-292d9fa49185.png"><img src="https://pic.yupi.icu/1/1729133895506-5d74012a-0d82-43bc-aac7-292d9fa49185.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">当然也可以使用第三方的包管理工具,比如 Chocolatey(Windows)、Homebrew(Mac)、Yum(Linux)。</span></p>
<p class="md-end-block md-p"><span class="md-plain">或者使用现成的服务器运维面板,比如宝塔 Linux,可以傻瓜式一键安装:</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111733529-29eb8c71-a1dd-4d7f-b3b0-ad37ca46f345.png"><img src="https://pic.yupi.icu/1/1730111733529-29eb8c71-a1dd-4d7f-b3b0-ad37ca46f345.png"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">2、修改网页文件</span></h3>
<p class="md-end-block md-p"><span class="md-plain">启动成功后,我们访问本机域名 <span class="md-pair-s"><code>localhost:80</code><span class="md-plain"> (80 为默认端口,可以省略),就可以看到 Nginx 为我们提供的默认网站了。</span></span></span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729133971776-9318e35a-c96f-47b1-9646-31d5b198f6a7.png"><img src="https://pic.yupi.icu/1/1729133971776-9318e35a-c96f-47b1-9646-31d5b198f6a7.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">那如果想自己修改网页内容,怎么办呢?</span></p>
<p class="md-end-block md-p"><span class="md-plain">我们要找到 Nginx 的大脑,也就是配置文件。进入配置目录 <span class="md-pair-s"><code>conf</code><span class="md-plain"> ,就可以看到配置文件 <span class="md-pair-s"><code>nginx.conf</code><span class="md-plain"> 了。配置文件由块和指令组成,可以通过修改配置实现各种功能,比如通过 location 块和 root 指令配置网站文件的根路径:</span></span></span></span></span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729134064981-11ec6c59-7f27-4d40-9cdf-ed590a9284bd.png"><img src="https://pic.yupi.icu/1/1729134064981-11ec6c59-7f27-4d40-9cdf-ed590a9284bd.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">我们找到这个 index.html 文件,修改网页的内容并保存:</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729138650518-f612c394-cc59-4aba-9c4f-321e1e9c60fe.png"><img src="https://pic.yupi.icu/1/1729138650518-f612c394-cc59-4aba-9c4f-321e1e9c60fe.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">重新访问就可以看到效果啦!</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729134188746-34171b05-50f9-40e9-9df5-3053624861da.png"><img src="https://pic.yupi.icu/1/1729134188746-34171b05-50f9-40e9-9df5-3053624861da.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">看到这里,恭喜你,已经超过 30% 的程序员了!</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">二、Nginx 常用操作 - 明劲</span></h2>
<p class="md-end-block md-p"><span class="md-plain">下面,我们要成为 Nginx 明劲武者。所谓明劲,就是要熟悉 Nginx 的基本配置和常用操作,能够满足企业开发中的大多数需求,如果你的目标是开发岗,那么学完下面这些就足够找工作了。</span></p>
<h3 class="md-end-block md-heading"><span class="md-plain">1、静态文件服务</span></h3>
<p class="md-end-block md-p"><span class="md-plain">我们开发好的网站,通常包含像 HTML、CSS、JavaScript、图片等文件,由于这些文件的内容在存储时是固定的,被称为静态文件。</span></p>
<p class="md-end-block md-p"><span class="md-plain">如果你要让别人访问到开发好的网站,只把网站文件放到服务器上还是不够的,还需要一个 Web 服务器,能够接受用户的访问请求,并找到对应位置的文件进行响应。</span></p>
<p class="md-end-block md-p"><span class="md-plain">Nginx 最基本的功能,就是作为 Web 服务器提供静态文件服务。</span></p>
<p class="md-end-block md-p"><span class="md-plain">打开 Nginx 的配置文件 <span class="md-pair-s"><code>nginx.conf</code><span class="md-plain"> ,添加 location 块,用于根据请求地址处理请求。比如我们通过 root 指令定义静态文件根目录,通过 index 指令定义默认首页文件:</span></span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp;<span class="cm-string-2">listen&nbsp;&nbsp; &nbsp; &nbsp; 80;<br><span>&nbsp;<span class="cm-string-2">server_name&nbsp;localhost;<br><span><span>​<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;/ {<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/tmp/nginx/html; &nbsp;<span class="cm-comment"># 指定静态文件根目录<br><span>&nbsp; &nbsp;<span class="cm-keyword">index&nbsp;<span class="cm-keyword">index.html; &nbsp;<span class="cm-comment"># 默认首页<br><span>}<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">保存配置,然后执行 <span class="md-pair-s"><code>nginx -s reload</code><span class="md-plain"> 命令来重载配置,再次访问网站时就会返回刚配置的目录下的首页文件。</span></span></span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729057494088-685f77b3-ba64-4ed5-a720-41479bd5c503.png"><img src="https://pic.yupi.icu/1/1729057494088-685f77b3-ba64-4ed5-a720-41479bd5c503.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">企业项目中,需要为特定路径定义不同的处理规则,location 块的配置会更复杂。支持根据请求路径的特定部分、正则表达式等进行匹配,比如到特定目录去寻找图片:</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp;<span class="cm-string-2">listen&nbsp;80; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 监听 80 端口<br><span>&nbsp;<span class="cm-string-2">server_name&nbsp;example.com; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 指定域名<br><span><span>​<br><span>&nbsp;<span class="cm-comment"># 根路径的配置,返回静态文件<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;/ {<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/var/www/html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 指向静态文件的根目录<br><span>&nbsp; &nbsp;<span class="cm-keyword">index&nbsp;<span class="cm-keyword">index.html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 默认首页文件<br><span>&nbsp; &nbsp;<span class="cm-string-2">try_files&nbsp;<span class="cm-number">$uri&nbsp;$uri/ =404; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 如果文件不存在,则返回 404<br><span>}<br><span><span>​<br><span>&nbsp;<span class="cm-comment"># 处理以 /images/ 开头的请求<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;/images/ {<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/var/www/assets/images/; &nbsp;<span class="cm-comment"># 指向图片目录<br><span>}<br><span><span>​<br><span>&nbsp;<span class="cm-comment"># 正则匹配,处理以 .php 结尾的请求<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;<span class="cm-number">~&nbsp;<span class="cm-number">\.<span class="cm-number">php$&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">include&nbsp;fastcgi_params; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 包含 FastCGI 参数<br><span>&nbsp; &nbsp;<span class="cm-string-2">fastcgi_pass&nbsp;127.0.0.1:9000; &nbsp; &nbsp;<span class="cm-comment"># 将请求转发到 FastCGI 处理程序<br><span>&nbsp; &nbsp;<span class="cm-keyword">fastcgi_index&nbsp;<span class="cm-keyword">index.php; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 设置 FastCGI 的默认索引文件<br><span>&nbsp; &nbsp;<span class="cm-keyword">fastcgi_param&nbsp;<span class="cm-number">SCRIPT_FILENAME&nbsp;$document_root$fastcgi_script_name; &nbsp;<span class="cm-comment"># 定义脚本文件名<br><span>}<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">2、反向代理</span></h3>
<p class="md-end-block md-p"><span class="md-plain">Nginx 的另一个常用功能是用作反向代理服务器。什么是反向代理呢?一句话:Nginx 作为中介,帮后端服务器接受请求。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111918040-c1ac2030-7ec9-45af-9251-4be683642379.png"><img src="https://pic.yupi.icu/1/1730111918040-c1ac2030-7ec9-45af-9251-4be683642379.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">反向代理有什么作用呢?</span></p>
<p class="md-end-block md-p"><span class="md-plain">首先是请求转发和解决跨域。比如在 location 块中添加 proxy_pass 配置,可以将 Nginx 在 80 端口收到的 /api 路径的请求转发到本地 8080 端口的后端服务。</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">listen&nbsp;80; &nbsp;<span class="cm-comment"># 监听 80 端口<br><span>&nbsp; &nbsp;<span class="cm-string-2">server_name&nbsp;localhost; &nbsp;<span class="cm-comment"># 替换为你的域名或 IP 地址<br><span><span>​<br><span>&nbsp; &nbsp;<span class="cm-variable-2">location&nbsp;/<span class="cm-number">api&nbsp;{<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-string-2">proxy_pass&nbsp;<span class="cm-variable-2">http://localhost:8080; &nbsp;<span class="cm-comment"># 代理到本地的 8080 端口<br><span>&nbsp; }<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样就隐藏了后端服务器的 IP 地址,让客户端完全感知不到后端服务器的存在,更加安全。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111965107-c64f6d0f-05d8-4d4c-8587-b170946f1fca.png"><img src="https://pic.yupi.icu/1/1730111965107-c64f6d0f-05d8-4d4c-8587-b170946f1fca.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">而且还能让前端和后端的域名统一,解决了跨域问题。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111974498-de9ea8f5-d2f3-4ab1-a5bf-450789c0df47.png"><img src="https://pic.yupi.icu/1/1730111974498-de9ea8f5-d2f3-4ab1-a5bf-450789c0df47.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">反向代理还可以用于实现负载均衡。由于企业项目的流量巨大,通常需要有多台后端服务器。Nginx 可以作为高性能网关,统一接收请求,并将请求按照特定规则转发到不同的后端服务器进行处理,从而分散了请求压力,避免单一服务器过载。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730111982669-dd6efc04-4cee-4f07-a654-07deb26b6b30.png"><img src="https://pic.yupi.icu/1/1730111982669-dd6efc04-4cee-4f07-a654-07deb26b6b30.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">在 Nginx 中实现负载均衡非常简单,首先通过 upstream 块定义了一个名为 backend 的服务器组,其中包含两个后端服务器,然后通过反向代理配置将请求转发到这个服务器组即可:</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">upstream&nbsp;<span class="cm-tag">backend&nbsp;{<br><span>&nbsp;<span class="cm-variable-2">server&nbsp;localhost:8080; &nbsp;<span class="cm-comment"># 第一个后端服务器<br><span>&nbsp;<span class="cm-variable-2">server&nbsp;localhost:8081; &nbsp;<span class="cm-comment"># 第二个后端服务器<br><span>}<br><span><span>​<br><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp;<span class="cm-string-2">listen&nbsp;80;<br><span>&nbsp;<span class="cm-string-2">server_name&nbsp;localhost;<br><span><span>​<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;/<span class="cm-number">api&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">proxy_pass&nbsp;<span class="cm-variable-2">http://backend; &nbsp;<span class="cm-comment"># 代理到负载均衡的后端服务器<br><span>}<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样每次都访问同一个地址,会交替返回两种不同的内容,这是因为 Nginx 的默认负载均衡算法是轮询,请求会被平均转发到两个不同的服务进行处理。</span></p>
<p class="md-end-block md-p"><span class="md-plain">反向代理还有更多的作用,比如缓存常见请求的响应、减少后端负担,集中处理 SSL 加密、认证和日志记录等功能,后面会依次讲解。</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">3、改写请求和响应</span></h3>
<p class="md-end-block md-p"><span class="md-plain">第三个 Nginx 的常用功能是改写请求和响应。在请求到达服务器或响应返回给客户端之前,Nginx 可以对其进行修改。</span></p>
<p class="md-end-block md-p"><span class="md-plain">改写请求与响应有什么作用呢?有几个比较典型的场景:</span></p>
<h4 class="md-end-block md-heading"><span class="md-plain">1)控制浏览器缓存</span></h4>
<p class="md-end-block md-p"><span class="md-plain">首先,<span class="md-pair-s "><strong>设置响应头</strong><span class="md-plain"> 可以帮助我们控制浏览器缓存。通过 Nginx 的 <span class="md-pair-s"><code>add_header</code><span class="md-plain"> 指令,可以为响应添加自定义的 HTTP 头部,从而指导浏览器如何处理缓存。比如设置缓存有效期为 30 天:</span></span></span></span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">location&nbsp;/images/ {<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/tmp/nginx/html;<br><span>&nbsp; &nbsp;<span class="cm-keyword">expires&nbsp;30d; &nbsp;<span class="cm-comment"># 设置缓存有效期为 30 天<br><span>&nbsp; &nbsp;<span class="cm-keyword">add_header&nbsp;<span class="cm-number">Cache-Control&nbsp;<span class="cm-string">"public"; &nbsp;<span class="cm-comment"># 设置缓存头<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样,当用户访问图片时,浏览器会在本地缓存这些图片,下次访问时就不用访问服务器了,提高速度并减少对服务器的请求。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730112450998-16905345-0e44-40b7-bef2-18e1f9e6304a.png"><img src="https://pic.yupi.icu/1/1730112450998-16905345-0e44-40b7-bef2-18e1f9e6304a.png"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h4 class="md-end-block md-heading"><span class="md-plain">2)重定向</span></h4>
<p class="md-end-block md-p"><span class="md-plain">请求重定向允许我们将请求从一个地址自动引导到另一个地址,常见的应用场景包括将 HTTP 请求重定向到 HTTPS,或者将旧地址重定向到新地址。</span></p>
<p class="md-end-block md-p"><span class="md-plain">在 Nginx 中,可以使用 <span class="md-pair-s"><code>return</code><span class="md-plain"> 指令 + 302 状态码配置重定向:</span></span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">location&nbsp;/<span class="cm-tag">old-page&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-keyword">return&nbsp;<span class="cm-number">302 https://codefather.<span class="cm-number">cn&nbsp;&nbsp;<span class="cm-comment"># 重定向到新页面<br><span>}</span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">当用户访问某个过期页面时,会被重定向自动跳转到新网站。</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h4 class="md-end-block md-heading"><span class="md-plain">3)URI 重写</span></h4>
<p class="md-end-block md-p"><span class="md-plain">比重定向更高级一些,Nginx 提供了 <span class="md-pair-s"><code>rewrite</code><span class="md-plain"> 指令,支持正则表达式,可以非常灵活地将请求重写为不同的路径或网站。比如将 <span class="md-pair-s"><code>/api/v1/users</code><span class="md-plain"> 的请求重写为 <span class="md-pair-s"><code>/api/users</code><span class="md-plain">:</span></span></span></span></span></span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">location&nbsp;/api/v1/ {<br><span>&nbsp; &nbsp;<span class="cm-keyword">rewrite&nbsp;<span class="cm-number">^/api/v1/<span class="cm-number">(.*<span class="cm-number">)$&nbsp;/api/<span class="cm-number">$1 break; &nbsp;<span class="cm-comment"># 将 /api/v1/ 的请求重写为 /api/<br><span>}</span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样一来,后端就不用再关注 <span class="md-pair-s"><code>/api/v1/</code><span class="md-plain"> 的存在了,这种方法在网站迁移或者结构调整时非常有用。大家也不用去记忆改写的具体语法,随用随查就行。</span></span></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<div class="md-hr md-end-block"><hr></div>
<p class="md-end-block md-p">&nbsp;</p>
<p class="md-end-block md-p"><span class="md-plain">看到这里,恭喜你,超过 60% 的程序员了。</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">三、Nginx 高级操作 - 暗劲</span></h2>
<p class="md-end-block md-p"><span class="md-plain">下面,我们要成为 Nginx 的暗劲高手。所谓暗劲,又分为 2 种境界。</span></p>
<ul class="ul-list" data-mark="+">
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">熟悉 Nginx 的各种特性和高级配置,能更快速地配置和管理 Nginx,为小圆满</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">熟悉 Nginx 工具和模块生态,能够灵活运用 Nginx 进行架构设计、并巧妙地解决各种需求,为大圆满。</span></p>
</li>
</ul>
<p class="md-end-block md-p"><span class="md-plain">暗劲境界的高手,挑战大厂开发、架构师、高级系统管理员岗位,不成问题。</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">1、Nginx 高级配置</span></h3>
<p class="md-end-block md-p"><span class="md-plain">我们先挑战小圆满,Nginx 的配置项实在是太多了,这里我就挑选几个相对实用的来讲解。</span></p>
<h4 class="md-end-block md-heading"><span class="md-plain">1)日志记录</span></h4>
<p class="md-end-block md-p"><span class="md-plain">为了分析网站流量、用户行为和报错信息,我们可以开启 Nginx 日志功能。分为访问日志和错误日志。</span></p>
<p class="md-end-block md-p"><span class="md-plain">访问日志会记录所有请求的信息,更全面,可以通过修改 access_log 指令调整日志存储路径:</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">http&nbsp;{<br><span>&nbsp;<span class="cm-keyword">log_format&nbsp;<span class="cm-number">custom_format&nbsp;<span class="cm-string">'yupi $remote_addr - $remote_user [$time_local] "$request" '<br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-string">'$status $body_bytes_sent "$http_referer" '<br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-string">'"$http_user_agent" "$http_x_forwarded_for"';<br><span>&nbsp;<br><span>&nbsp;<span class="cm-keyword">access_log&nbsp;/rap/access.<span class="cm-number">log custom_format; &nbsp;<span class="cm-comment"># 配置访问日志<br><span><span>​<br><span>&nbsp;<span class="cm-variable-2">server&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">listen&nbsp;&nbsp; &nbsp; &nbsp; 80;<br><span>&nbsp; &nbsp;<span class="cm-string-2">server_name&nbsp;localhost;<br><span>&nbsp;<br><span>&nbsp; &nbsp;<span class="cm-variable-2">location&nbsp;/ {<br><span>&nbsp; &nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/tmp/nginx/html; &nbsp;<span class="cm-comment"># 指定静态文件根目录<br><span>&nbsp; &nbsp; &nbsp;<span class="cm-keyword">index&nbsp;<span class="cm-keyword">index.html; &nbsp;<span class="cm-comment"># 默认首页<br><span>&nbsp; }<br><span>}<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">而错误日志仅记录 Nginx 在处理请求时遇到的问题,错误又分为 8 个级别:</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1730112505465-0c8ba6ae-e9d8-40d0-b3ee-e50ab350cdbf.png"><img src="https://pic.yupi.icu/1/1730112505465-0c8ba6ae-e9d8-40d0-b3ee-e50ab350cdbf.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">可以为不同的级别指定不同的日志输出路径:</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-keyword">access_log&nbsp;/rap/access.<span class="cm-tag">log custom_format; &nbsp;<span class="cm-comment"># 配置访问日志<br><span><span class="cm-keyword">error_log&nbsp;/rap/error.<span class="cm-tag">log error; &nbsp;<span class="cm-comment"># 配置错误日志</span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">开启日志功能后,就能直接在文件中查看日志了。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729140954262-5cc92e8e-b67f-48b8-ad35-4a83b5a41061.png"><img src="https://pic.yupi.icu/1/1729140954262-5cc92e8e-b67f-48b8-ad35-4a83b5a41061.png"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h4 class="md-end-block md-heading"><span class="md-plain">2)访问控制</span></h4>
<p class="md-end-block md-p"><span class="md-plain">如果有恶意用户攻击我们的网站,怎么办?</span></p>
<p class="md-end-block md-p"><span class="md-plain">莫慌,Nginx 提供了访问控制功能,可以使用 <span class="md-pair-s"><code>allow</code><span class="md-plain"> 和 <span class="md-pair-s"><code>deny</code><span class="md-plain"> 指令对 IP 访问进行限制,比如不让 127.0.0.1 这个 IP 访问:</span></span></span></span></span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">listen&nbsp;80;<br><span>&nbsp; &nbsp;<span class="cm-string-2">server_name&nbsp;localhost;<br><span><span>​<br><span>&nbsp; &nbsp;<span class="cm-variable-2">location&nbsp;/ {<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 拒绝特定 IP 地址<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-keyword">deny&nbsp;127.0.0.1;<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 除了写具体 ip 外,也可以写网段<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-keyword">deny&nbsp;192.168.1.0/24;<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 允许所有其他 IP 地址<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-keyword">allow&nbsp;all;<br><span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-string-2">proxy_pass&nbsp;<span class="cm-variable-2">http://localhost:8081;<br><span>&nbsp; &nbsp;<br><span>&nbsp; }<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样一来,攻击者就访问不了网站了!</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729141114593-ffc8f923-4364-41fb-b31d-0d6ff5511b63.png"><img src="https://pic.yupi.icu/1/1729141114593-ffc8f923-4364-41fb-b31d-0d6ff5511b63.png"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h4 class="md-end-block md-heading"><span class="md-plain">3)限流</span></h4>
<p class="md-end-block md-p"><span class="md-plain">为了保护网站,我们还可以使用 Nginx 的限流功能。比如下面这段配置,通过定义请求限流区域并应用于根路径,限制每个 IP 地址在一分钟内最多只能发送 2 个请求。</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-comment"># 定义限流区域,使用客户端的二进制 IP 地址作为唯一标识<br><span><span class="cm-comment"># zone=one:10m 表示创建一个名为 "one" 的内存区域,大小为 10MB<br><span><span class="cm-comment"># rate=2r/m 表示每个 IP 地址每分钟最多允许 2 个请求<br><span><span class="cm-keyword">limit_req_zone&nbsp;<span class="cm-tag">$binary_remote_addr zone=one:<span class="cm-tag">10m rate=2r/m;<br><span><span>​<br><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp;<span class="cm-string-2">listen&nbsp;80; &nbsp;<span class="cm-comment"># 监听 80 端口,接收 HTTP 请求<br><span>&nbsp;<span class="cm-string-2">server_name&nbsp;localhost; &nbsp;<span class="cm-comment"># 设置服务器名称为 localhost<br><span><span>​<br><span>&nbsp;<span class="cm-variable-2">location&nbsp;/ { &nbsp;<span class="cm-comment"># 配置根路径的请求处理<br><span>&nbsp; &nbsp;<span class="cm-comment"># 应用限流配置,使用之前定义的 "one" 区域<br><span>&nbsp; &nbsp;<span class="cm-comment"># burst=10 表示可以允许最多 10 个额外请求超出正常限速<br><span>&nbsp; &nbsp;<span class="cm-comment"># nodelay 表示在突发请求情况下,这 10 个请求将立即被处理,不会被延迟<br><span>&nbsp; &nbsp;<span class="cm-keyword">limit_req&nbsp;zone=<span class="cm-number">one burst=<span class="cm-number">10 nodelay;<br><span><span>​<br><span>&nbsp; &nbsp;<span class="cm-comment"># 将请求转发到本地的 8080 端口<br><span>&nbsp; &nbsp;<span class="cm-string-2">proxy_pass&nbsp;<span class="cm-variable-2">http://localhost:8080; &nbsp;<span class="cm-comment"># 反向代理请求到后端服务<br><span>}<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">这样后端服务就不被流量激增影响,能够提高系统的稳定性。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729141298510-a77cb084-bb1b-4c5f-b11b-7d8c2b689f1a.png"><img src="https://pic.yupi.icu/1/1729141298510-a77cb084-bb1b-4c5f-b11b-7d8c2b689f1a.png"></span></p>
<h4 class="md-end-block md-heading"><span class="md-plain">4)虚拟主机</span></h4>
<p class="md-end-block md-p"><span class="md-plain">在企业开发中,我们为了节省成本,经常会在同一台服务器上部署多个网站项目,这时就需要使用 Nginx 的虚拟主机功能了。</span></p>
<p class="md-end-block md-p"><span class="md-plain">每个网站通常就是一个虚拟主机,会有一个 server_name 名称对应访问网站的域名,比如我这里配置 2 台虚拟主机:</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-comment"># 虚拟主机1<br><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">listen&nbsp;80; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 监听 80 端口<br><span>&nbsp; &nbsp;<span class="cm-string-2">server_name&nbsp;localhost; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 配置域名为 example.com<br><span><span>​<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/tmp/nginx/html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-tab"><span class="cm-tab">&nbsp;<span class="cm-comment"># 网站根目录<br><span>&nbsp; &nbsp;<span class="cm-keyword">index&nbsp;localhost.html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 默认首页<br><span>}<br><span><span>​<br><span><span class="cm-comment"># 虚拟主机2<br><span><span class="cm-variable-2">server&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-string-2">listen&nbsp;80; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 监听 80 端口<br><span>&nbsp; &nbsp;<span class="cm-string-2">server_name&nbsp;127.0.0.1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-comment"># 配置域名为 another.com<br><span><span>​<br><span>&nbsp; &nbsp;<span class="cm-string-2">root&nbsp;/tmp/nginx/html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="cm-tab"><span class="cm-tab">&nbsp;<span class="cm-comment"># 网站根目录<br><span>&nbsp; &nbsp;<span class="cm-keyword">index&nbsp;127.html; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="cm-comment"># 默认首页<br><span>}</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p"><span class="md-plain">配置虚拟主机后,Nginx 就能够根据请求的域名找到对应的网站配置,并处理请求。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/1729141769653-83116e9f-26ad-4245-b632-efeb4818d7c8.png"><img src="https://pic.yupi.icu/1/1729141769653-83116e9f-26ad-4245-b632-efeb4818d7c8.png"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h4 class="md-end-block md-heading"><span class="md-plain">5)其他</span></h4>
<p class="md-end-block md-p"><span class="md-plain">除了上面这些,还有很多企业开发中可能会用到的 Nginx 高级配置和技巧。</span></p>
<p class="md-end-block md-p"><span class="md-plain">比如可以:</span></p>
<ul class="ul-list" data-mark="-">
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">通过后端响应缓存配置,让 Nginx 直接从缓存中读取数据来响应请求,这样能够显著提升性能、减少服务器压力。</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">通过正向代理的设置,Nginx 可以作为 “跳板机”,帮客户端发起请求,从而访问原本无法直接访问的资源。</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">通过自定义错误页面,能够给用户提供更友好的错误提示信息。</span></p>
</li>
</ul>
<p class="md-end-block md-p"><span class="md-plain">此外,Nginx 支持 WebSocket、HTTPS 和 HTTP/2 等多种协议,还可以配置 Gzip 压缩来减少传输的数据量,进一步优化性能。</span></p>
<p class="md-end-block md-p"><span class="md-plain">最后,Nginx 自身也支持一系列性能调优的配置,比如工作进程与连接数配置,可以从容应对高并发和大流量场景。</span></p>
<pre class="md-fences md-end-block ty-contain-cm modeLoaded"><span><span class="cm-keyword">worker_processes&nbsp;auto;&nbsp;<span class="cm-comment"># 自动检测 CPU 核心数,设置工作进程数<br><span><span>​<br><span><span class="cm-variable-2">events&nbsp;{<br><span>&nbsp; &nbsp;<span class="cm-keyword">worker_connections&nbsp;2048;&nbsp;<span class="cm-comment"># 每个工作进程的最大连接数<br><span>}</span></span></span></span></span></span></span></span></span></span></span></pre>
<p class="md-end-block md-p">&nbsp;</p>
<h3 class="md-end-block md-heading"><span class="md-plain">2、Nginx 工具和模块生态</span></h3>
<p class="md-end-block md-p"><span class="md-plain">想成为 Nginx 大圆满高手,就要懂得利用工具和生态,比如可视化工具、模块和开源项目。</span></p>
<p class="md-end-block md-p"><span class="md-plain">首先,Nginx 的配置和运维对初学者来说可能比较复杂,这时可以利用 Nginx 官方推出的 Nginx Amplify、轻量级的 Nginx-UI 或者宝塔 Linux 服务器管理面板等可视化工具,通过图形界面来更直观地查看配置、分析流量和性能指标,从而提高操作和运维效率。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/dashboard_zh_CN.png"><img src="https://pic.yupi.icu/1/dashboard_zh_CN.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">其次,Nginx 的功能并不是一成不变的,我们可以通过各种各样的模块来扩展它的能力,比如我们常用于健康检查的 nginx_upstream_check_module 模块、实现 JavaScript 语言扩展的 njs 模块。</span></p>
<p class="md-end-block md-p"><span class="md-plain">但手动安装模块的过程是比较繁琐的,需要下载源码并进行编译。</span></p>
<p class="md-end-block md-p"><span class="md-plain">这种情况下,我们就可以选择 OpenResty 这样一个基于 Nginx 的高性能 Web 平台,它集成了大量模块、依赖项和 Lua 脚本库,能够让你直接在 Nginx 里开发复杂的业务逻辑,充分利用 Nginx 的非阻塞 I/O 模型来提升应用的性能,适合超高并发的场景。</span></p>
<p class="md-end-block md-p"><span class="md-plain">比如下图是网上的一个基于 OpenResty 实现的灰度发布架构:</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://pic.yupi.icu/1/v2-f8a301ee0e5d5d3631e03abcf081987b_r.jpg"><img src="https://pic.yupi.icu/1/v2-f8a301ee0e5d5d3631e03abcf081987b_r.jpg"></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">四、Nginx 原理 - 化劲</span></h2>
<p class="md-end-block md-p"><span class="md-plain">想要突破为化劲强者,你需要去理解 Nginx 的核心原理,甚至是去钻研那晦涩难懂的 C 语言源码。</span></p>
<p class="md-end-block md-p"><span class="md-pair-s "><strong>当然,为了应对面试,现在很多程序员迫不得已朝着化劲强者进发。</strong></span></p>
<p class="md-end-block md-p"><span class="md-plain">原理的学习就不是几分钟的视频能搞定的了,但是我可以帮大家划划重点。</span></p>
<ul class="ul-list" data-mark="-">
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">负载均衡机制</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">事件驱动模型</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">请求处理流程</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">多进程架构</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">进程间通信机制</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">限流机制</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">缓存机制</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">压缩机制</span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-plain">资源复用</span></p>
</li>
</ul>
<p class="md-end-block md-p"><span class="md-plain">能搞懂这些,并且融会贯通,你就能够更自如地优化 Nginx 的性能和可用性等等,也就超过 99% 的程序员了。</span></p>
<p class="md-end-block md-p"><span class="md-plain">当然,编程是学不完的,真正的 Nginx 绝世高手,可以给 Nginx 贡献代码,甚至是自立门户、手写 Nginx 的竞品。</span></p>
<p class="md-end-block md-p"><span class="md-pair-s "><strong>我相信看到这里的小伙伴中肯定会出现绝世高手~</strong></span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">结尾</span></h2>
<p class="md-end-block md-p"><span class="md-plain">最后,我把这份 Nginx 学习路线文字版、以及常问的面试题都放到了自己的小博客,还有更多学习路线也可免费获取。</span></p>
<p class="md-end-block md-p"><span class="md-image md-img-loaded" data-src="https://cdn.nlark.com/yuque/0/2024/png/33547719/1730113119795-d6f6a98b-d78d-4050-9491-345b212b009c.png"><img src="https://cdn.nlark.com/yuque/0/2024/png/33547719/1730113119795-d6f6a98b-d78d-4050-9491-345b212b009c.png"></span></p>
<p class="md-end-block md-p"><span class="md-plain">希望对大家有帮助,学会的话也还请给本文一个点赞支持哦~</span></p>
<p class="md-end-block md-p">&nbsp;</p>
<h2 class="md-end-block md-heading"><span class="md-plain">更多编程学习资源</span></h2>
<ul class="ul-list" data-mark="-">
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">Java前端程序员必做项目实战教程+毕设网站</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">程序员免费编程学习交流社区(自学必备)</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">程序员保姆级求职写简历指南(找工作必备)</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">程序员免费面试刷题网站工具(找工作必备)</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新Java零基础入门学习路线 + Java教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新Python零基础入门学习路线 + Python教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新前端零基础入门学习路线 + 前端教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新数据结构和算法零基础入门学习路线 + 算法教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新C++零基础入门学习路线、C++教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新数据库零基础入门学习路线 + 数据库教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新Redis零基础入门学习路线 + Redis教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新计算机基础入门学习路线 + 计算机基础教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新小程序入门学习路线 + 小程序开发教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新SQL零基础入门学习路线 + SQL教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新Linux零基础入门学习路线 + Linux教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新Git/GitHub零基础入门学习路线 + Git教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新操作系统零基础入门学习路线 + 操作系统教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新计算机网络零基础入门学习路线 + 计算机网络教程</span></span></p>
</li>
<li class="md-list-item">
<p class="md-end-block md-p"><span class="md-meta-i-cmd-link"><span class="md-plain">最新设计模式零基础入门学习路线 + 设计模式教程</span></span></p>
</li>
<li class="md-list-item md-focus-container">
<p class="md-end-block md-p md-focus"><span class="md-meta-i-c md-link md-expand"><span class="md-plain">最新软件工程零基础入门学习路线 + 软件工程教程</span></span></p>
</li>
</ul><br><br>
来源:https://www.cnblogs.com/yupi/p/18519885
頁: [1]
查看完整版本: 不敢相信,Nginx 还能这么玩?