1.1 Nginx
的产生
Nginx
同Apache
一样都是一种web
服务器,基于REST
架构风格,以统一资源描述符(Uniform Resources Identifier)URI
或者统一资源定位符(Uniform Resources Locator)URL
作为沟通依据,通过HTTP
协议提供各种网络服务。
然而,这些服务器在设计之初受到当时环境的局限,例如当时的用户规模,网络带宽,产品特点等局限并且各自的定位和发展都不尽相同。这也使得各个web
服务器有着各自鲜明的特点。
Apache
的发展时期很长,而且是毫无争议的世界第一大服务器。它有着很多优点:稳定、开源、跨平台等等。它出现的时间太长了,它兴起的年代,互联网产业远远比不上现在。所以它被设计为一个重量级的。它是不支持高并发的服务器。在Apache
上运行数以万计的并发访问,会导致服务器消耗大量内存。操作系统对其进行进程或线程间的切换也消耗了大量的CPU
资源,导致HTTP
请求的平均响应速度降低。
这些都决定了Apache
不可能成为高性能web
服务器,轻量级高并发服务器Nginx
就应运而生了。
俄罗斯的工程师Igor Sysoev
,他在为Rambler Media
工作期间,使用C
语言开发了Nginx
。Nginx
作为web
服务器一直为Rambler Media
提供出色而又稳定的服务。
然后呢,Igor Sysoev
将Nginx
代码开源,并且赋予自由软件许可证。
由于:
Nginx
使用基于事件驱动架构,使得其可以支持数以百万级别的TCP
连接- 高度的模块化和自由软件许可证使得第三方模块层出不穷(这是个开源的时代啊~)
Nginx
是一个跨平台服务器,可以运行在Linux,Windows,FreeBSD,Solaris,AIX,Mac OS
等操作系统上- 这些优秀的设计带来的是极大的稳定性
所以,Nginx
火了!
1.2 Nginx
的用武之地
Nginx
是一款自由的、开源的、高性能的HTTP
服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP
代理服务器;Nginx
可以作为一个HTTP
服务器进行网站的发布处理,另外Nginx
可以作为反向代理进行负载均衡的实现。
关于代理
说到代理,首先我们要明确一个概念,所谓代理就是一个代表、一个渠道;
此时就涉及到两个角色,一个是被代理角色,一个是目标角色,被代理角色通过这个代理访问目标角色完成一些任务的过程称为代理操作过程;如同生活中的专卖店~客人到adidas
专卖店买了一双鞋,这个专卖店就是代理,被代理角色就是adidas
厂家,目标角色就是用户。
1.3 正向代理
说反向代理之前,我们先看看正向代理,正向代理也是大家最常接触的到的代理模式,我们会从两个方面来说关于正向代理的处理模式,分别从软件方面和生活方面来解释一下什么叫正向代理。
正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。
客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的IP地址,还有代理程序的端口。如图。
总结来说:正向代理,“它代理的是客户端,代客户端发出请求”,是一个位于客户端和原始服务器(origin server)
之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。
正向代理的用途:
(1)访问原来无法访问的资源
(2)可以做缓存,加速访问资源
(3)对客户端访问授权,上网进行认证
(4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息
1.4 反向代理
明白了什么是正向代理,我们继续看关于反向代理的处理方式,举例如我大天朝的某宝网站,每天同时连接到网站的访问人数已经爆表,单个服务器远远不能满足人民日益增长的购买欲望了,此时就出现了一个大家耳熟能详的名词:分布式部署;也就是通过部署多台服务器来解决访问人数限制的问题;某宝网站中大部分功能也是直接使用Nginx
进行反向代理实现的,并且通过封装Nginx
和其他的组件之后起了个高大上的名字:Tengine
,有兴趣的童鞋可以访问Tengine
的官网查看具体的信息。那么反向代理具体是通过什么样的方式实现的分布式的集群操作呢,我们先看一个示意图(我把服务器和反向代理框在一块,同属于一个环境,后面我有介绍):
通过上述的图解大家就可以看清楚了,多个客户端给服务器发送的请求,Nginx
服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。此时~请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,Nginx
扮演的就是一个反向代理角色。
客户端是无感知代理的存在的,反向代理对外都是透明的,访问者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。
反向代理,“它代理的是服务端,代服务端接收请求”,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。
反向代理的作用:
(1)保证内网的安全,通常将反向代理作为公网访问地址,web
服务器是内网
(2)负载均衡,通过反向代理服务器来优化网站的负载
项目场景
通常情况下,我们在实际项目操作时,正向代理和反向代理很有可能会存在在一个应用场景中,正向代理代理客户端的请求去访问目标服务器,目标服务器是一个反向单利服务器,反向代理了多台真实的业务处理服务器。具体的拓扑图如下:
1.5 二者区别
截了一张图来说明正向代理和反向代理二者之间的区别,如图。
图解
在正向代理中,Proxy
和Client
同属于一个LAN
(图中方框内),隐藏了客户端信息;
在反向代理中,Proxy
和Server同属于一个LAN
(图中方框内),隐藏了服务端信息;
实际上,Proxy
在两种代理中做的事情都是替服务器代为收发请求和响应,不过从结构上看正好左右互换了一下,所以把后出现的那种代理方式称为反向代理了。
1.6 负载均衡
我们已经明确了所谓代理服务器的概念,那么接下来,Nginx
扮演了反向代理服务器的角色,它是以依据什么样的规则进行请求分发的呢?不用的项目应用场景,分发的规则是否可以控制呢?
这里提到的客户端发送的、Nginx
反向代理服务器接收到的请求数量,就是我们说的负载量。
请求数量按照一定的规则进行分发到不同的服务器处理的规则,就是一种均衡规则。
所以,将服务器接收到的请求按照规则分发的过程,称为负载均衡。
负载均衡在实际项目操作过程中,有硬件负载均衡和软件负载均衡两种,硬件负载均衡也称为硬负载,如F5
负载均衡,相对造价昂贵成本较高,但是数据的稳定性安全性等等有非常好的保障,如中国移动中国联通这样的公司才会选择硬负载进行操作;更多的公司考虑到成本原因,会选择使用软件负载均衡,软件负载均衡是利用现有的技术结合主机硬件实现的一种消息队列分发机制。
Nginx
支持的负载均衡调度算法方式如下:
1、weight
轮询(默认,常用,具有HA
功效!):接收到的请求按照权重分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,Nginx
会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。 这种方式下,可以给不同的后端服务器设置一个权重值(weight
),用于调整不同的服务器上请求的分配率;权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。
2、ip_hash
(常用):每个请求按访问ip
的hash
结果分配,这样每个访客固定访问一个后端服务器,这也在一定程度上解决了集群部署环境下session
共享的问题。
3、fair
:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是Nginx
默认不支持fair算法,如果要使用这种调度算法,请安装upstream_fair
模块。
4、url_hash
:按照访问的url
的hash
结果分配请求,每个请求的url
会指向后端固定的某个服务器,可以在Nginx
作为静态服务器的情况下提高缓存效率。同样要注意Nginx
默认不支持这种调度算法,要使用的话需要安装Nginx
的hash
软件包。
1.7 几种常用web
服务器对比
对比项\服务器 | Apache | Nginx | Lighttpd |
---|---|---|---|
Proxy 代理 | 非常好 | 非常好 | 一般 |
Rewriter | 好 | 非常好 | 一般 |
Fcgi | 不好 | 好 | 非常好 |
热部署 | 不支持 | 支持 | 不支持 |
系统压力 | 很大 | 很小 | 比较小 |
稳定性 | 好 | 非常好 | 不好 |
安全性 | 好 | 一般 | 一般 |
静态文件处理 | 一般 | 非常好 | 好 |
反向代理 | 一般 | 非常好 | 一般 |
1.8 Nginx
特点
- 跨平台:可以在大多数
Unix like
系统编译运行。而且也有Windows
的移植版本。 - 配置异常简单:非常的简单,易上手。
- 非阻塞、高并发连接:数据复制时,磁盘
I/O
的第一阶段是非阻塞的。官方测试能支持5万并发连接,实际生产中能跑2~3
万并发连接数(得益于Nginx
采用了最新的epoll
事件处理模型(消息队列)。 Nginx
代理和后端Web服务器间无需长连接;Nginx
接收用户请求是异步的,即先将用户请求全部接收下来,再一次性发送到后端Web服务器,极大减轻后端Web
服务器的压力。- 发送响应报文时,是边接收来自后端
Web
服务器的数据,边发送给客户端。 - 网络依赖性低,理论上只要能够
ping
通就可以实施负载均衡,而且可以有效区分内网、外网流量。 - 支持内置服务器检测。
Nginx
能够根据应用服务器处理页面返回的状态码、超时信息等检测服务器是否出现故障,并及时返回错误的请求重新提交到其它节点上。 - 采用
Master/worker
多进程工作模式 - 此外还有内存消耗小、成本低廉(比F5硬件负载均衡器廉价太多)、节省带宽、稳定性高等特点。
1.9 内部进程模型
Nginx
是以多进程的方式来工作的,当然Nginx
也是支持多线程的方式的,只是我们主流的方式还是多进程的方式,也是Nginx
的默认方式。Nginx
采用多进程的方式有诸多好处。
Nginx
在启动后,会有一个master
进程和多个worker
进程。master
进程主要用来管理worker
进程,包含:接收来自外界的信号,向各worker
进程发送信号,监控 worker
进程的运行状态,当worker
进程退出后(异常情况下),会自动重新启动新的worker
进程。而基本的网络事件,则是放在worker
进程中来处理了。多个worker
进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker
进程中处理,一个worker
进程,不可能处理其它进程的请求。worker
进程的个数是可以设置的,一般我们会设置与机器CPU
核数一致,这里面的原因与Nginx
的进程模型以及事件处理模型是分不开的。
1.10 处理请求
首先,Nginx
在启动时,会解析配置文件,得到需要监听的端口与IP
地址,然后在Nginx
的master
进程里面,先初始化好这个监控的socket
(创建socket
,设置addrreuse
等选项,绑定到指定的IP
地址端口,再listen
),然后再fork
(一个现有进程可以调用fork
函数创建一个新进程。由fork
创建的新进程被称为子进程 )出多个子进程出来,然后子进程会竞争accept
新的连接。
此时,客户端就可以向Nginx
发起连接了。当客户端与Nginx
进行三次握手,与Nginx
建立好一个连接后,某一个子进程会accept
成功,得到这个建立好的连接的socket
,然后创建Nginx
对连接的封装,即ngx_connection_t
结构体。
接着,设置读写事件处理函数并添加读写事件来与客户端进行数据的交换。最后,Nginx
或客户端来主动关掉连接,到此,一个连接就寿终正寝了。