社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  NGINX

前端容器化部署——实战学习nginx,积累面试经验

前端Q • 4 月前 • 354 次点击  

点击上方 前端Q,关注公众号

回复加群,加入前端Q技术交流群

前文有提到前端项目容器化部署和静态资源部署的两种方式,核心的区别就是在于部署的这个文件服务器在谁的手里管辖。如果说是纯上传静态资源就可以完成部署工作,那么服务器的管辖大概率在运维同学手里;如果说是容器化部署,那意味着我们可以自己管理自己的文件服务器——Nginx。

本文不会细致讲解从零到一的 Nginx 配置、高级玩法,更多是通过我个人遇到的一些实战场景,跟大家一起从真实的角度了解这个我们熟悉又陌生的朋友。

前言

尽管 nginx 相比于 html、css、js 这三剑客来说,并不是前端的必修课,但是它的存在对于整个前端项目来说也不容小觑,毕竟项目经开发完上线,它就要开始发力了。

了解 nginx 可以让我们更加清楚整个 web前端 的工作链路;基于对整生态的上游下熟知从而更加快速地定位一些问题;甚至可以在面试中应对某些开放性场景中表现得游刃有余...

登录场景

企业中,一般都会有一套统一的登录、鉴权的流程。这一套路程中,中间可能存在多个节点,每个节点都各司其职,最终完成一个用户的鉴权、跳登录的这么一个流程。如果此时前端项目的 nginx 不在你手上,你大概率可以不用管这些,只要有关登录失败的问题,直接找运维查日志再找他们就好...

但是如果前端部署的 nginx 是你自己在管理,那么你大概率需要了解这其中的登录上下游关系,并且根据相应的节点做一定的跳转处理,从而完成整个登录流程的接入。以至于出现一些登录异常的问题时,你也需要自己跑到 nginx 里查看对应的日志,来定位一些问题。


如上图所示,我简单的ga了一个鉴权、跳登录的流程图。当前端页面发起一个 /user 的请求获取用户信息时,如果出现鉴权不通过需要跳转登录流程,那承载前端静态资源的 nginx 服务器就需要做一些关于登录的跳转配置了。

面试场景

关于面试场景,能拉上 nginx 来说的就太多了,我就简单例举几个能想到的例子吧。其实大厂面试官很喜欢问一些开放性的问题,就好比:页面白屏、登录失败、为什么会404、分析首屏加载慢的情况这种...相信经历过鹅厂面试的同学多多少少都遇到过,那么针对这些面试题,如果仅仅从纯前端技术的角度回答,确实显得有些苍白无力了...

为什么这么说?因为这类问题大多数都是比较全面性的问题,前端技术并不能完全覆盖其中。而且我相信面试官这样问的目的,也不仅仅是纯考察你的前端技术,我更愿意相信他们是想全面考察你对整个 web 应用的理解有多少。

比如我自己,不认识 nginx 的时候,回答白屏、登录失败、加载慢等这种开放性问题,也只能从前端角度出发。诸如什么js执行出错、网络问题、服务器挂了啊等等,反正背过的没背过的八股文都一拥而上了。但是后来,实战玩过 nginx 后,了解了众多的上下游服务等链路,或许我在回答上可以多一些维度了。比如我从这些角度进行思考:

  1. nginx 进程问题。真实遇到 openresty 中存在死循环 lua 脚本导致 nginx 进程跑满 cpu,此时浏览器访问所有页面都无法加载(纯崩溃状态。
  2. 「配置错误」导致404。我们都知道当访问不存在的资源时就会获得 404 的状态码,但其实,并不是所有的 404 状态码都是资源不存在而导致的,可能是有坑人的配置(下文会详细讲。
  3. nginx 「重试配置」。当遇到请求慢的情况,也有可能是在 nginx 配置了 proxy_next_upstream ,当某个请求上游出错、超时等情况出现时,会尝试转发到下一个上游服务器。这也会导致请求慢的问题,毕竟多次请求的耗时是叠加的,对于用户端来说,请求总时间就长了。
  4. 登录失败——url 长度太长。用户携带了大量的 params 跳转登录,当业务服务器处理完成返回跳转原登录url时,如果 header 超出 nginx 配置的缓冲区大小也会出现登录错误。如:upstream sent too big header while reading response header from upstream 这种的 nginx 错误。

总之,当结合 nginx 的场景再去回答上述开放性面试题时,我相信整个回答的完整度、知识覆盖面等都会比仅仅从前端出发的角度要好,或许这也会为你的面试加上一丢丢的分数。所以,了解、学习 nginx 对于前端同学来说,还是有一定必要性的,不管是应对工作中的一些业务场景,或者是面试。

实战相关

如何用 nginx 部署

前面讲容器化部署的时候,我并没有展开来说,但其实这部分并不复杂,我这里简单提一下。首先我跟大家演示一下,真实前端项目部署上线后,是怎么运行起来的。开发时本地有 vite、webpack 给我们预制好的 dev server,那么当我们将项目打包成 dist 后,应该怎么搞呢?

我这里通过 vite create 搞了个初始化的项目,本地启动后如下图所示。(为了好区分,我特地加了一句:Nginx Test)


基于这个项目,运行打包命令后,我们便会得到一个 dist 包。产物中可以找到我自己加入得那一句 Nginx Test:


这时候,我就把对应的这个 dist 包,拉到我本地装了 nginx 的一个目录中。并且把 nginx 的配置做了下改动:



紧接着我通过 nginx -g "daemon off;" 命令运行 nginx。-g "daemon off;"这个参数大家不用关注也行,它只是我用于让 nginx 前台运行,方便随时停掉的而已(不然有守护进程,停掉比较麻烦。这时候,当我们访问 localhost 应该就能看到我们的 web 界面了(默认 80 端口:


那么,我们在容器化部署时,只需要遵循这样的配置方式,基于 nginx 的基础镜像,就可以打出一个前端项目的镜像包了。当我们基于该镜像启动容器时,运行 nginx 的启动命令,如无意外的情况我们的项目就成功部署好了。

简单看看 Dockerfile 的写法(详细大家可以去官方的nginx镜像仓库看看:

FROM nginx

COPY nginx.conf /etc/nginx/conf.d/
COPY ./dist/ /usr/share/nginx/html/

CMD ["/bin/bash", "-c", "nginx -g 'daemon off;'"]

上述的每一行你都可以在官方的镜像仓库中找到。东西不多,我带着大家一行行看下:

  1. 复制我们项目中的 nginx.conf 配置到一个位置;
  2. 复制 dist 包到一个位置;
  3. nginx 前台启动命令

这样,前端项目的容器化部署就搞定了。不过这一切操作,都不会包含上一篇文章提到的重启容器后静态资源丢失的处理,如需处理重启容器资源丢失问题,请参考上一篇文章的讲解。

真真假假 404


这个熟悉页面一定是众多前端的噩梦!看到它就意味着有问题!不过不知道你有没有想过这么一个问题:怎么出现这个界面的呢?这个界面是由谁写的呢?或者更高级一点的,如 openresty,50x 报错的时候会返回如下的界面:


其实很多线上项目中,通常 web服务器 会因为某些异常状态而返回对应的一些页面(如上述 nginx 的404,openresty 的 50x。这些大部分都不是我们自己开发的(除非自己有需求开发并且配置到 nginx 上了),所以当我第一次在自己域名的项目中遇到一些奇怪的页面,还以为服务器被黑了呢...

那么回到 404 这个问题,我们都知道访问不存在的资源就会 404,那么如果项目是基于默认的 nginx 启动运行的,404 的时候就会返回上面那个大家都比较熟悉的页面。如果我对相应的配置改动一下,如:

error_page  404              /nb.html;
location = /nb.html {
root html;
}

当我们再次访问不存在资源时,页面就如我们配置那样返回了:


上述大概给大家介绍了一下通过 nginx 部署的项目,404 时候的一个表现。虽然我上面皮了一下,给 nginx 的 404 错误配置了一个为 nb.html 的页面作为返回,但线上一般是不会这么玩的是吧?所以我们每次在浏览器接收到的 404.html 的返回结果,就一定是遇到 「404资源不存在的问题吗」

如果你现在问我这个问题时,我会回答「是,但不全是」。为何这么说,我通过这个案例来说明。

前文我将 dist 包拉到 nginx 的 html 的目录时,大家可能也注意到了一个叫 50x.html 的文件是吧:


双击打开这个 html 时,他是长这样的:


这个页面大伙也有点熟悉对吧,如果我们 nginx 上接收到 50x 的报错,按照默认的配置来说便会返回这么一个页面。比如此时的我通过链接访问来模拟上游服务器返回 502 的错误码时前端接收到最终页面返回的情况。


接下来,如果我把这个 50x.html 的文件删了呢?大家可以猜想到结局吗?(这里我已经恢复了404改nb的配置)


没错,实时如你所见,页面显示 404 了。其实你看到这里,也许你会觉得这不是扯淡吗?无稽之谈。但我想说的是,这确实是我实战中遇到的问题。因为我们团队内部对 nginx 基础镜像自己又包了点东西,打了一个自己的 nginx 镜像。但这个镜像中,50x.html 的位置放错了,所以每次上游服务器返回任何 50x 报错的时候,最终到页面上的都是404。

这个配置错误,或者说 50x.html 的位置错误,一定程度上影响了一开始我们排查问题时的思考方向。一直怀疑资源问题的我,直到我查看 error.log 时发现其实对应的请求状态是超时,或者 502时,再联合查看 access.log 后,发现居然是 50x.html 的文件不存在...

所以,如果现在你问我前端接收到 404 返回时,是不是一定是资源不存在的问题时,我会回答:是,又不全是。可能因为 nginx 配置问题,导致全部上游的服务器报错问题都会是 404 的返回结果。

dns缓存

如果你曾遇到过某个项目「每隔一段时间打开后出现 404」,但是重启服务又解决了;如果你的项目也是部署在 aws,并且域名解析到其 ingress 层;那么恭喜你,也许你成功踩到了 nginx 的 dns 缓存的坑了。

nginx 默认行为在启动时会解析所有在配置文件中定义的域名。这些解析结果会被缓存,并在整个 Nginx 运行期间使用。基于这一点,如果某个服务的 ip 在 nginx 运行期间的发生了变动,那么就会出现 404 的问题。因为当 nginx 请求上游服务时,依然访问的旧的 ip 地址...


如上图所示,服务器1 的 ip 改变后,再通过该 nginx 向上游发送请求时,就不能正确返回了。此时我们能做的只有重启 nginx(重启时会重新基于配置做 dns 解析),让 nginx 正确的”找到“这个上游服务器。

这其实也是我在实战中真实遇到的场景,并且这问题不太好定位解决。其一就是它的偶发性,aws 的 ingress 的 ip 并不是每时每刻都在变,所以当你想准确定位这个问题时,你却发现这其实很难复现问题。当每次遇到问题,紧急重启完 nginx 问题后问题就解决了,但是当你去追溯问题时你又发现复现不出来。于是你只能找到你的上游服务的开发者一起探讨...

其实你说坑也确实坑,自己菜也确实菜,毕竟从未遇到过,所以一开始解决起来还是有点耗时和棘手。如果说对 nginx 有更深的认知,或者对云厂商了解过多,或许这样的问题排查就不会这么棘手了。所以还是要不断在实战中积累经验,每踩过的一个坑,都不会白踩。

简单总结,如果现在再遇到面试有人问我 404 的原因,或许我不仅仅能回到资源不存在、nginx 配置问题、还能再补充多一个这样的场景:nginx dns 的缓存问题,当遇到上游服务 ip 变化时,依然会有 404 的问题。

总结

其实,历经容器化部署后,更加体会到 nginx 这类 web服务器 对于前端发展的重要性。当我写这篇文章的时候,不断回想起之前面试各大厂时遇到的一些开放性问题,如果结合 nginx 的维度来进行回答,将会更全面。并且在这个时候,自己也意识到为什么当时面试官会问这样的问题。

本文我仅仅例举了两个实战中碰到的问题,发散开来其实可以对应到种种开放性面试题。并且我还没有对所有遇到的问题做一个总结回顾,所以我是有理由相信 nginx 的知识对于整个前端的从业生涯来说是比较重要的。它可以使我们从更加全面的视野来看待前端,看待问题。

如果当前团队中采用的容器化部署前端项目的方式,并且你有机会能接触到 nginx 的配置,那我觉得你一定要亲自上手玩玩。菜如笔者,不断玩不断学习,也算是在不断积累经验的过程也能有一点点收获,并且可以通过实战的经验反哺到一些开放性面试题中,我觉得对自己的综合实力来说是有提升的。所以你也一定可以有所收获~


往期推荐


产品:你能让网页也像QQ那种一样发出右下角消息吗
GitHub + VitePress,或许是你做笔记的新路子
(已开源)开发了一个纯前端在线代码编辑器、制作一个炫酷动画收藏网站

最后


  • 欢迎加我微信,拉你进技术群,长期交流学习...

  • 欢迎关注「前端Q」,认真学前端,做个专业的技术人...

点个在看支持我吧

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/173948
 
354 次点击