Py学习  »  NGINX

小白眼中的Nginx。。。

芋道源码 • 5 月前 • 153 次点击  

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP CRMAI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本 

来源:小白debug


你是一个程序员,你在电脑上编辑了一段文本,将它保存为 txt 文件 。将它拖到浏览器打开,就能看到文件里的内容。

但这看起来太过单调,为了让画面更丰富,我们定个规则,在文本边上加个两个h1符号,文本就以标题 形式展示。

加入ul和li就能变成列表 ,加入img还能让url文本 直接变成对应的图片 。

这些带尖括号的特殊符号,我们叫它标签 。只要浏览器识别到这些标签,就展示对应的样式。

为了将这个自带标签的文本跟 txt 纯文本区分开来,我们给了它新的后缀名, html 。

浏览器只要识别到文件是 html,就会解析里面的标签,这样我们就有了标题、输入框等各种丰富的内容了。这其实就是我们平时在浏览器中看到的网页 。

但不同的是,这个 html 文件是浏览器从我们本地 电脑文件中打开的。

本地浏览器打开html
本地浏览器打开html

而我们平时访问的网页,则是从某台远端服务器 ,将文件传到我们电脑的浏览器后打开的。

从远端服务器得到html打开
从远端服务器得到html打开

那么问题就来了,我们是怎么获得这个远端服务器上的 html 文件的 ?

没有什么是加一层中间层不能解决的,如果有,那就再加一层 ,这次我们要加的中间层是 Nginx .

nginx中间层
nginx中间层

假设我们完全不了解 nginx,来看下它是怎么设计出来的。

HTTP 服务器是什么?

想要让本地的浏览器,获取到放在远端服务器上的 html 文件。

那很简单,我们可以在远端服务器启动一个进程 ,这个进程对外提供 http 服务 ,说白了就是提供了个 url 。

用户在浏览器中输入这个 url, 回车,浏览器就会向 这个进程发起 http 请求  ,

进程收到浏览器的请求后,就将 html 文件发给浏览器,浏览器完成解析和展示,完美。

而像这种根据浏览器请求,返回 html 文件的服务进程,其实就叫 http 服务器 。

有了它,前端开发老哥写的各种 html 文件就能部署到远端服务器上,对外提供网页服务 了。

http服务器是什么
http服务器是什么

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

反向代理是什么?

但一个完整产品往往不止有前端页面 ,还有后端服务 ,比如某宝,前端商城页面需要从后端服务那获取最新的商品数据。

前后端分离
前后端分离

假设现在前端页面已经被加载到浏览器中,浏览器会按页面里写好的代码逻辑,向后端商品服务发起请求,获取数据,流量小的时候没什么问题,流量变大后,后端服务器扛不住的话,就需要增加商品服务的个数,服务变多后,每个都有对应的 ip 和端口,浏览器就不知道该访问哪个服务了。

所以我们还需要在这几个后端服务前面加一个进程 ,对外提供一个 url 域名,请求来了,由这个进程均匀转发给背后的几个服务,让每个服务都能处理上请求,也就实现了所谓的负载均衡 。

像这种,屏蔽掉背后具体有哪些服务器的代理方式,就是我们常说的反向代理 。

反向代理
反向代理

有了反向代理,我们对外就可以只提供一个url域名,背后根据需要, 随时扩缩容服务 。

这个反向代理的功能,正好可以加到前面放 html 文件的进程上。

那现在这个进程就很灵性了,既可以为 前端 html 文件提供 http 服务器的功能,当 html 文件被加载到浏览器,并向后端发起请求的时候,这个进程还能为后端服务器提供反向代理的功能。

http服务器+反向代理
http服务器+反向代理

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

模块化网关能力

既然是中间层,所有网络流量都要经过进程,那它高低也算个网关 了。

网关
网关

于是我们就可以顺理成章的在它上面加入一些通用网关能力 ,比如加个日志 ,记录每次调用的结果,方便后续排查问题,又比如加个对输入输出的内容进行压缩 的功能,减小网络带宽消耗,又或者是对某个 IP 进行限流或封禁 ,甚至还可以修改输入输出 的内容。能实现的功能实在太多,想象空间很大,于是将这部分功能设计为开放接口 ,让用户通过自定义模块 来实现特定功能。

这还不够,现在这个网关只支持http,我们其实还能扩展下,让它支持tcp,udp,http2和websocket,你能想到的我都要支持,我本来不支持的,自会有人通过自定义模块帮我支持。

支持多种通用能力和协议
支持多种通用能力和协议

配置能力

前面提到那么多种能力,用户肯定不会全用上,所以需要有个地方让人选择用哪些能力,于是我们可以加个配置文件,也就是nginx.conf ,用户想用什么能力,就在配置文件上声明清楚就行,非常方便。

nginx.conf配置
nginx.conf配置

单线程

现在这个网关进程的主要任务就是跟上下游建立网络连接,顺便内部做下处理。多个客户端请求通过网络进入到一个进程,如果用多线程并发处理,那就需要考虑并发问题,同时影响性能。怎么办呢?

多线程
多线程

很简单!外部不管有多少有个网络连接,网关进程收到客户端请求后,都统一塞到一个线程 上,在一个线程上处理客户端请求,什么并发问题 和线程切换开销 ,完全不存在!

单线程
单线程

多 worker 进程

但单个进程要单线程处理那么多流量,哪怕再快,压力也不小,万一这里面有美羊羊发的流量,你觊觎那么久?怎么忍心让她久等?沸羊羊你说话!

怎么办呢?既然多线程不行,那我们就上多进程 。

于是可以将单个进程改成多个进程,我们管它们叫 worker 进程 。进程之间互相独立,一个 worker 跪了不影响另外一个 worker 进程。

多worker进程
多worker进程

让多个 worker 进程同时监听一个 ip 地址+端口。只要一有流量进来,操作系统就会随机给到其中一个进程处理。将进程数量 设置为跟操作系统cpu核数 一致,那每个进程都能得到一个核,开足马力猛猛干。

worker数与核数一致
worker数与核数一致

看到这里,问题就来了,为什么多个进程同时监听一个端口不会出现端口冲突 (port is already in use),评论区告诉我答案。

共享内存

但多 worker 进程的情况下,同一个客户端的多个请求会随机打到某个 worker ,对于限流这种需要计数的场景,就会被分散到多个 worker 上单独计数,那还怎么限流,所以还需要给这些 worker 进程 分配一个共享内存 区域,方便多个进程之间共用同一份数据做逻辑,确保系统数据一致性。

共享内存
共享内存

proxy cache

作为网关,它在收到前端网页请求后,会转发给后端,并将后端处理结果中转给前端。如果它能将响应结果缓存 起来,这样下次收到同样的请求 ,直接将缓存里的数据返回给前端,从而减少响应时间和网络负载 。

那这个数据是放在共享内存里吗?内存贵,不合适,我们可以维护些磁盘文件,用于在前端请求后端的过程中,暂存后端响应的结果,后面再有相同请求,就可以将磁盘里的数据返回。

这又是经典的空间换时间 ,用廉价的磁盘空间换取网络传输和cpu计算耗时。对于后端响应较慢或重复请求较多的场景,读写磁盘总归比直接将请求打到后端来得快。这些用于缓存响应数据的磁盘文件 ,就是 所谓的proxy cache 。

proxy cache
proxy cache

加入 master 进程

但这还不够,现在每个 worker 都会分走一部分流量,如果功能更新,所有 worker 同时一起重启,上面的网络连接就会全部断掉。更好的方式是创建 worker 和关闭 worker 挨个陆续执行,这样前端网页连接断开后还能去连另外一个worker,保证任意时间一直有worker在工作。也就是所谓的滚动升级 。因此还需要一个新的进程协调各个 worker 谁先谁后,这个协调进程 ,就是所谓的 master 进程 。让master读取前面提到的nginx.conf 配置,统一管理多个worker。

master进程
master进程

nginx 是什么

好啦,到这里,当初那个简陋的单进程网关服务,就变成了一个支持动态配置多种通用网关能力和多种网络协议,单 master 多 worker 架构、多个worker进程之间共享内存和proxy cache,对外提供一个IP+端口,支持 http 服务器和反向代理的高性能网关服务。

它就是所谓的 nginx 。

nginx是什么
nginx是什么

它不仅支持日志、限流等各种通用能力、还支持自定义网关能力,只要你写好配置,就能让它给你当牛做马。性能上 5w qps 非常轻松,应付你那只有几十 qps 的服务更是绰绰有余了。

现在大家通了吗?好啦,如果你觉得这个视频对你有帮助,记得点赞并转发给你那不成器的兄弟,文字版的笔记见评论区。

最后遗留一个问题,想必大家也发现了,聊到现在它其实也只是某台服务器上的多个进程,一旦服务器跪了,nginx 也就跪了,存在单点问题 。

nginx单点问题
nginx单点问题

怎么解决 nginx 的单点问题 呢?nginx 有集群模式 吗?

欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/189821