初探 Nginx 架构
nginx 在启动后,在 unix 系统中会以 daemon 的方式在后台运行,后台进程包含一个 master 进程和多个 worker 进程。我们也可以手动地关掉后台模式,让 nginx 在前台运行,并且通过配置让 nginx 取消 master 进程,从而可以使 nginx 以单进程方式运行。很显然,生产环境下我们肯定不会这么做,所以关闭后台模式,一般是用来调试用的,在后面的章节里面,我们会详细地讲解如何调试 nginx。所以,我们可以看到,nginx 是以多进程的方式来工作的,当然 nginx 也是支持多线程的方式的,只是我们主流的方式还是多进程的方式,也是 nginx 的默认方式。nginx 采用多进程的方式有诸多好处,所以我就主要讲解 nginx 的多进程模式吧。
nginx 在启动后,会有一个 master 进程和多个 worker 进程。master 进程主要用来管理 worker 进程,包含:接收来自外界的信号,向各 worker 进程发送信号,监控 worker 进程的运行状态,当 worker 进程退出后 (异常情况下),会自动重新启动新的 worker 进程。而基本的网络事件,则是放在 worker 进程中来处理了。多个 worker 进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个 worker 进程中处理,一个 worker 进程,不可能处理其它进程的请求。worker 进程的个数是可以设置的,一般我们会设置与机器 cpu 核数一致,这里面的原因与 nginx 的进程模型以及事件处理模型是分不开的。
nginx 的进程模型,可以由下图来表示:
Nginx 的负载均衡策略
负载均衡技术少不了相关的均衡策略,Nginx 中提供了 4 种均衡策略,我们可以根据具体的业务场景选择合适的均衡策略。下面分别介绍这 4 中均衡策略:
1 基于轮询的均衡策略
轮询嘛,就是说对进到 nginx 的 request 按照遍历的方式进行分发,如果 request 1 分发到 Server A,那么 request 2 将被分发到 Server B,…… 以此循环类推。
2 基于最少连接数的均衡策略
最少连接,也就是说 nginx 会判断后端集群服务器中哪个 Server 当前的 Active Connection 数是最少的,那么对于每个新进来的 request,nginx 将该 request 分发给对应的 Server。
3 基于 ip-hash 的均衡策略
我们都知道,每个请求的客户端都有相应的 IP 地址,该均衡策略中,nginx 将会根据相应的 hash 函数,对每个请求的 IP 作为关键字,得到的 hash 值将会决定将请求分发给相应 Server 进行处理。
4 基于加权轮询的均衡策略
加权轮询,很显然这个策略跟我们开题引入的场景是一样的,nginx 会给 Server 配置相应的权重,权重越大,接收的 request 数将会越多。
惊群现象
主进程(master 进程)首先通过 socket () 来创建一个 sock 文件描述符用来监听,然后 fork 生成子进程(workers 进程),子进程将继承父进程的 sockfd(socket 文件描述符),之后子进程 accept () 后将创建已连接描述符(connected descriptor),然后通过已连接描述符来与客户端通信。
那么,由于所有子进程都继承了父进程的 sockfd,那么当连接进来时,所有子进程都将收到通知并 “争着” 与它建立连接,这就叫 “惊群现象”。大量的进程被激活又挂起,只有一个进程可以 accept () 到这个连接,这当然会消耗系统资源。
Nginx 对惊群现象的处理
Nginx 提供了一个 accept_mutex 这个东西,这是一个加在 accept 上的一把共享锁。即每个 worker 进程在执行 accept 之前都需要先获取锁,获取不到就放弃执行 accept ()。有了这把锁之后,同一时刻,就只会有一个进程去 accpet (),这样就不会有惊群问题了。accept_mutex 是一个可控选项,我们可以显示地关掉,默认是打开的。
Nginx 的应用场景
- 高性能 HTTP 服务器(动静分离)
- 反向代理(Reverse Proxy)服务器(负载均衡)
- 正向代理服务器
高性能 HTTP 服务器
Nginx 可以作为一个高性能的 HTTP 服务器,以向用户提供静态资源。
反向代理(Reverse Proxy)服务器(负载均衡)
** 反向代理(Reverse Proxy)** 方式是指以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
通过一个反向代理服务器实现负载均衡是一个很常见的场景。
即,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。
反向代理的用途
** 隐藏服务器真实 IP:** 使用反向代理,可以对客户端隐藏服务器的 IP 地址。
** 负载均衡:** 反向代理服务器可以做负载均衡,根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上。
** 提高访问速度:** 反向代理服务器可以对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度。
** 提供安全保障:** 反向代理服务器可以作为应用层防火墙,为网站提供对基于 Web 的攻击行为(例如 DoS/DDoS)的防护,更容易排查恶意软件等。还可以为后端服务器统一提供加密和 SSL 加速(如 SSL 终端代理),提供 HTTP 访问认证等。
正向代理(Forward Proxy)服务器
正向代理(Forward Proxy)通常都被简称为代理,就是在用户无法正常访问外部资源,比方说受到 GFW 的影响无法访问 twitter 的时候,我们可以通过代理的方式,让用户绕过防火墙,从而连接到目标网络或者服务。
正向代理的工作原理就像一个跳板,比如:我访问不了 google.com,但是我能访问一个代理服务器 A,A 能访问 google.com,于是我先连上代理服务器 A,告诉他我需要 google.com 的内容,A 就去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。
结论就是,正向代理是一个位于客户端和原始服务器 (origin server) 之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标 (原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
正向代理的用途
** 突破访问限制:** 通过代理服务器,可以突破自身 IP 访问限制,访问国外网站,教育网等。
** 提高访问速度:** 通常代理服务器都设置一个较大的硬盘缓冲区,会将部分请求的响应保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
** 隐藏客户端真实 IP:** 上网者也可以通过这种方法隐藏自己的 IP,免受攻击。
Reference
- 《Nginx 开发从入门到精通》 - http://tengine.taobao.org/book/index.html#id3
- Nginx 学习系列(二) ————- 负载均衡 - https://juejin.im/post/5b6a45d5f265da0f9402d118
- 理解 Nginx 工作原理 - https://www.jianshu.com/p/6215e5d24553
- 所有和 Java 中代理有关的知识点都在这了。 - https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650121631&idx=1&sn=c6cfbf6aaaf01899a1d36b562e881f11&chksm=f36bb8bec41c31a865ee13a40fbfa2636328651df3c6af13dd7378511d67eda0dfcc48ec732c&scene=21#wechat_redirect