文章目录
一、Nginx 介绍
Nginx是一个高性能的 HTTP 和 反向代理 服务,也是一个IMAP/POP3/SMTP服务。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。
在高连接并发的情况下,Nginx是Apache服务器不错的替代品。
二、为什么选择 Nginx
Nginx 是一个高性能的 Web 和 反向代理 服务器, 它具有很多非常优越的特性:
单机环境下参考服务器配置。 并发连接数在7000+ -8000左右。 集群模式20000+
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应。
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perl要好的多。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器。能够在不间断服务的情况下进行软件版本的升级。
三、nginx功能特性
1、基本功能
实现与服务静态文件(静态资源的web服务器),能缓存打开的文件描述符;
反向代理服务器,缓存、负载均衡、健康状态检测;
支持FastCGI;
模块化机制,非DSO机制,支持多种过滤器gzip,SSI和图像的模块完成图形大小调整等;
支持SSL;
2、扩展功能
基于名称和IP做虚拟主机;
支持keeplive;
支持平滑配置更新或程序版本升级;
定制访问日志,支持使用日志缓存以提高性能;
支持URL rewrite;
支持路径别名;
支持基于IP及用户的认证;
支持速率限制,并发数限制等;
四、Nginx的优缺点
- 优点:
- 占内存小,可实现高并发连接,处理响应快
- 功能种类比较多。可实现http服务器、虚拟主机、反向代理、负载均衡
- 支持epoll模型,在实际生产环境能够支撑3万左右并发连接。
- 利用nginx可以对IP限速,可以限制连接数。
- Nginx 可跨平台,而且配置相对来说难度较低。
- 可以不暴露正式的服务器IP地址
- Nginx 内置健康检查功能,如果负载均衡其中一个服务器宕机了,则接受到的请求会发送给其他服务器去处理。
- 支持Gzip压缩,可以添加浏览器本地缓存的Header头。
- Nginx 支持热部署,可以在不间断服务的情况下平滑进行配置的更改。
- 异步接收用户请求,减轻了Web服务器的压力。
- 缺点:
动态处理差:nginx处理静态文件好,耗费内存少,但是处理动态页面则很鸡肋,现在一般前端用nginx作为反向代理抗住压力
五、nginx应用场景
-
HTTP服务器(包含动静分离)。可以先通过 动态/静态 内容分离,而后为静态内容(html/css/js/图片等)提供HTTP访问功能;而动态内容可以整合代理模块,代理给上游服务器,来支持对外部程序的直接调用或者解析,如FastCGI支持PHP。(PHP并发约500-1500,MySQL 并发约300-1500)。
-
反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会应为某台服务器负载高宕机而某台服务器闲置的情况。日pv2000W以下,都可直接用nginx做代理。
-
虚拟主机。可以实现在一台服务器虚拟出多个网站,例如个人网站使用的虚拟机。
六、Nginx高并发的原理
原理:nginx 通过 多进程 + io多路复用(epoll) 实现了高并发
进程和线程(进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位)
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
1、多进程单线程
在工作方式上,Nginx分为单工作进程和多工作进程两种模式。在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的;在多工作进程模式下,每个工作进程包含多个线程。Nginx默认为单工作进程模式。
Nginx在启动后,会有一个master进程和多个worker进程。
(1)master进程:管理进程
master进程主要用来管理worker进程,具体包括如下4个主要功能:
- 接收来自外界的信号。
- 向各worker进程发送信号。
- 监控woker进程的运行状态。
- 当woker进程退出后(异常情况下),会自动重新启动新的woker进程。
master进程
项目 | Value |
---|---|
socket() | 通常在父子进程之间通信前,会先调用socketpair创建一组套接字 |
listen() | 监听 |
bind() | 绑定端口 |
fork() | 创建 |
(2)worker进程:处理请求
主要任务是处理基本的网络事件,完成具体的任务逻辑。
- 多个worker进程之间是对等且相互独立的,他们同等竞争来自客户端的请求。
- 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。
- worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。而且,nginx为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。
worker 进程主要工作
项目 | 作用 |
---|---|
accept() | 与客户端建立连接 |
recv() | 接收客户端发过来的数据 |
send() | 向客户端发送数据 |
close() | 关闭客户端连接 |
(3)进程控制方式
对Nginx进程的控制主要是通过master进程来做到的,主要有两种方式:
- 手动发送信号
从上图可以看出,master接收信号以管理众woker进程,那么,可以通过kill向master进程发送信号,比如kill -HUP pid用以通知Nginx从容重启。所谓从容重启就是不中断服务:master进程在接收到信号后,会先重新加载配置,然后再启动新进程开始接收新请求,并向所有老进程发送信号告知不再接收新请求并在处理完所有未处理完的请求后自动退出。
- 自动发送信号
可以通过带命令行参数启动新进程来发送信号给master进程,比如./nginx -s reload用以启动一个新的Nginx进程,而新进程在解析到reload参数后会向master进程发送信号(新进程会帮我们把手动发送信号中的动作自动完成)。当然也可以这样./nginx -s stop来停止Nginx。
(4)网络事件
Nginx(多进程)采用异步非阻塞的方式来处理网络事件,类似于Libevent(单进程单线程),具体过程如下图:
- master进程先建好需要listen的socket后,然后再fork出多个woker进程,这样每个work进程都可以去accept这个socket。
- 当一个client连接到来时,所有accept的work进程都会受到通知,但只有一个进程可以accept成功,其它的则会accept失败。
- Nginx提供了一把共享锁accept_mutex来保证同一时刻只有一个work进程在accept连接,从而解决惊群问题。
- 当一个worker进程accept这个连接后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完成的请求就结束了。
2、异步,非阻塞
(1)同步与异步
同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式。
同步:当一个同步调用发出去后,调用者要一直等待调用结果的通知后,才能进行后续的执行。
异步:当一个异步调用发出去后,调用者不能立即得到调用结果的返回。
(2)阻塞与非阻塞
阻塞与非阻塞的重点在于进/线程等待消息时候的行为,也就是在等待消息的时候,当前进/线程是挂起状态,还是非挂起状态。
阻塞:阻塞调用在发出去后,在消息返回之前,当前进/线程会被挂起,直到有消息返回,当前进/线程才会被激活
非阻塞:非阻塞调用在发出去后,不会阻塞当前进/线程,而会立即返回。
(3)异步非阻塞
每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?
处理到可能发生阻塞的地方,比如向后端服务器转发request,并等待请求返回。那么,这个处理的worker不会这么一直等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。这就是异步。此时,如果再有request 进来,他就可以很快再按这种方式处理。这就是非阻塞和IO多路复用。
而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。这就是异步回调。
总的来说,Nginx采用异步非阻塞的好处在于:
- 不需要创建线程,每个请求只占用少量的内存
- 没有上下文切换,事件处理非常轻量
3、IO多路复用
Nginx采用了异步非阻塞的方式工作。那么Nginx是如何实现异步非阻塞的呢?那得先了解一下I/O多路复用。
(1)什么是IO复用
- I/O复用解决的是并发性请求的问题。
- 处理多个并发请求,要产生多个I/O流来进行系统内核数据的读取。
- 常用的两种处理方式是串行,前一个阻塞,后面无法继续进行处理;
并行,可实现最大并发和吞吐
。- I/O复用定义为:一个socket作为复用来完成整个I/O流的请求链接建立,处理请求则采用多线程。
(2)IO多路复用
第一种方法就是最传统的多进程并发模型 (每进来一个新的I/O流会分配一个新的进程管理。)
第二种方法就是I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流 。)
I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流。发明它的原因,是尽量多的提高服务器的吞吐能力。
在同一个线程里面, 通过拨开关的方式,来同时传输多个I/O流。
(3)IO多路复用模型
IO复用的实现方式主要有select,poll和epoll,而 Nginx 采用的 IO多路复用模型 epoll。
ngnix会有很多连接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。epoll 可以说是I/O 多路复用最新的一个实现,epoll 修复了select/poll绝大部分问题, 比如:
-
epoll 线程安全的。
-
epoll 告诉你具体哪个sock有数据,你不用自己去找了。