Nginx入门学习
What
Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器,在高连接并发的情况下Nginx是Apache服务器不错的替代品。其特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。
Nginx作为负载均衡服务器,既可以在内部直接支持Rails和PHP程序对外进行服务,也可以支持作为HTTP代理服务器对外进行服务。Nginx用C进行编写,配置文件简洁(支持Perl语法),启动容易,几乎可以做到服务不间断运行和版本升级。
模块化设计
nginx的设计可以说是高度模块化,每个模块就是一个功能模块,只负责自身的功能,模块之间严格遵循高内聚,低耦合的原则。
- 核心模块:Nginx 服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能。
- 标准 HTTP 模块:提供 HTTP 协议解析相关的功能:端口配置、网页编码设置、HTTP 响应头设置等。
- 可选 HTTP 模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,如:Flash 多媒体传输、解析 Geo IP 请求、SSL 支持等。
- 邮件服务模块:主要用于支持 Nginx 的邮件服务,包括对 POP3 协议、IMAP 协议和 SMTP 协议的支持。
- 第三方模块:扩展 Nginx 服务器应用,完成开发者自定义功能,如:Json、Lua支持等。
安装
Windows安装
下载Windows版本的zip包解压,双击nginx.exe即可。在任务管理器的进程窗口可以看到两个nginx进程,分别是master和worker进程。退出Nginx服务的方法:
- 找到两个进程,右键手动结束任务即可;
- 命令行方法:
./nginx.exe -s stop
- 脚本化方法stop_nginx.bat:
Linux安装
Linux下安装Nginx,至少需要依赖以下几个模块(编译模块时按照这个顺序):
- openssl-fips; 即ssl功能模块
- zlib; 即gzip模块
- pcre. 即rewrite模块
分别搜索得到其下载的地址(包括Nginx),在Linux下执行wget <url>
即可,然后tar zxvf *.tar.gz
,
然后到解压后的目录下执行:
验证Nginx是否安装成功:
同时也可以通过打开localhost:82,成功的话可以看到Nginx的欢迎页面。
注意:在pcre官网会看到pcre2这个版本的库文件,不要下载安装这个,否则会安装Nginx失败:
Mac 安装 nginx
最简单的方法:brew install nginx
The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that nginx can run without sudo。
nginx will load all files in /usr/local/etc/nginx/servers/.
To have launchd start nginx now and restart at login: brew services start nginx
Or, if you don’t want/need a background service you can just run: nginx
停止:nginx -s stop
集群版安装
命令行及工具
nginx原生自带或者支持的命令:
ngxtop
Nginx网站服务器在生产环境中运行时需要进行实时监控;专业的监控软件如Nagios, Zabbix, Munin的网络监控支持Nginx监控,并给出综合性报告或者长期数据统计功能。
ngxtop命令行工具,可以快速简便地监控Nginx服务器的请求,通过分析 Nginx 或者其他日志文件,使用类似 top 命令的界面实时展示出来的。采用python编写,可以通过pip install ngxtop
来安装。
选项:
-l : 指定日志文件的完整路径 (Nginx 或 Apache2)
-f : 日志格式
–no-follow: 处理当前已经写入的日志文件,而不是实时处理新添加到日志文件的日志
-t : 更新频率
-n : 显示行号
-o : 排序规则(默认是访问计数)
-a …: 添加表达式(一般是聚合表达式如: sum, avg, min, max 等)到输出中。
-v: 输出详细信息
-i : 只处理符合规则的记录
一些内置变量:
- bodybytessend
- http_referer
- http_user_agent
- remote_addr
- remote_user
- request
- status
- time_local
实例:
参考:
ngxtop:在命令行实时监控 Nginx 的神器
实现原理
请求处理方式
高性能得益于多进程和异步机制,异步机制使用的是异步非阻塞方式。
多进程
服务器每当收到一个客户端时,由服务器master主进程生成一个worker子进程,和客户端建立连接进行交互,直到连接断开,该子进程就结束。
优点
- 各个进程之间相互独立,不需要加锁,减少使用锁对性能造成影响,降低编程的复杂度,降低开发成本;
- 采用独立的进程,可以让进程互相之间不会影响,如果一个进程发生异常退出时,其它进程正常工作,master 进程则很快启动新的 worker 进程,确保服务部中断,将风险降到最低。
缺点
- 操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销;
- 当有大量请求时,会导致系统性能下降。当有大量请求时,会导致系统性能下降。
异步非阻塞
每个工作进程使用异步非阻塞方式,可以处理多个客户端请求。当某个工作进程接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去处理其他的请求(即为非阻塞);而客户端在此期间也无需等待响应,可以去处理其他事情(即为异步);当 IO 返回时,就会通知此工作进程;该进程得到通知,暂时挂起当前处理的事务去响应客户端请求。
事件驱动模型
在 Nginx 的异步非阻塞机制中,工作进程在调用 IO 后,就去处理其他的请求,当 IO 调用返回后,会通知该工作进程。对于这样的系统调用,主要使用 Nginx 服务器的事件驱动模型来实现。
Nginx 的事件驱动模型由事件收集器、事件发送器和事件处理器三部分基本单元组成。事件收集器负责收集 worker 进程的各种 IO 请求,事件发送器负责将 IO 事件发送到事件处理器,而事件处理器负责各种事件的响应工作。
事件发送器将每个请求放入一个待处理事件的列表,使用非阻塞 I/O 方式调用“事件处理器”来处理该请求。其处理方式称为“多路 IO 复用方法”,常见的包括以下三种:select 模型、poll 模型、epoll 模型。
架构设计
Nginx 服务器使用 master/worker 多进程模式。多线程启动和执行的流程如下:主程序 Master process 启动后,通过一个 for 循环来接收和处理外部信号;主进程通过 fork() 函数产生子进程,每个子进程执行一个 for 循环来实现 Nginx 服务器对事件的接收和处理。
一般推荐 worker 进程数与 cpu 内核数一致,这样一来不存在大量的子进程生成和管理任务,避免进程之间竞争 CPU 资源和进程切换的开销。而且 Nginx 为了更好的利用多核特性,提供 cpu 亲缘性的绑定选项,可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来 cache 的失效。
对于每个请求,有且只有一个工作进程对其处理。每个 worker 进程都是从 master 进程 fork 过来,在 master 进程里面,先建立好需要 listen 的 socket(listenfd)之后,然后再 fork 出多个 worker 进程。所有 worker 进程的 listenfd 会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有 worker 进程在注册 listenfd 读事件前抢 accept_mutex,抢到互斥锁的那个进程注册 listenfd 读事件,在读事件里调用 accept 接受该连接。
当一个 worker 进程在 accept 这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了。一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。
在 Nginx 服务器的运行过程中,主进程和工作进程需要进程交互。交互依赖于 Socket 实现的管道来实现。
- Master-Worker 交互
这条管道与普通的管道不同,它是由主进程指向工作进程的单向管道,包含主进程向工作进程发出的指令,工作进程 ID 等;同时主进程与外界通过信号通信;每个子进程具备接收信号,并处理相应的事件的能力。 - worker-worker 交互
这种交互是和 Master-Worker 交互是基本一致的,但是会通过主进程。工作进程之间是相互隔离的,所以当工作进程 W1 需要向工作进程 W2 发指令时,首先找到 W2 的进程 ID,然后将正确的指令写入指向 W2 的通道。W2 收到信号采取相应的措施。
Apache & nginx
- nginx相对于Apache的优点:
同样是web服务,nginx更轻量级,即比Apache占用更少的内存及资源;对PHP-CGI支持良好、反向代理功能、支持7层负载均衡、前端Cache、维持连接;抗并发,nginx处理请求是异步非阻塞的,而Apache则是阻塞型的;社区活跃,各种第三方高性能模块供选择;
Apache 相对于nginx 的优点:rewrite模块功能比nginx 的rewrite 强大;动态页面模块多;bug少,稳定;Apache有先天不支持多核心处理负载鸡肋的缺点。 - Nginx配置文件简洁,,正则配置"简单"且运行效率高;nginx -t 测试一下配置有效性;Apache复杂;Apache 对 PHP 支持比较简单;
- 最核心的区别在于Apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程;
- 可以充分返回两者的优势,搭配使用,使用nginx做前端以及负载均衡, 后端用Apache配置集群。大型网站建议用nginx自带的集群功能。
负载均衡算法
none/round-robin(轮询)
upstream按照轮询(默认,即没有任何配置信息时)方式进行负载,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。简便、成本低廉。缺点:可靠性低和负载分配不均衡。适用于图片服务器集群和纯静态页面服务器集群。
Least Time(least_time)
请求会分配给响应最快和活跃连接数最少的backend;
weight(权重)
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。下面的负载均衡实战就是使用权重的方式。
ip_hash(访问ip)
每个请求按访问ip的hash函数结果分配,IPv4会考虑前3个octet,IPv6会考虑所有的地址位,这样每个访客固定访问一个后端服务器,可以解决session sticky问题。配置只需要在upstream中加入ip_hash;
即可:
least-connected(最少连接least_conn)
Nginx会把下一个连接分配给具有最小活动连接的服务器,常用于一些请求需要更长的时间才能完成的情况,nginx将尽量不会把过多的请求来使忙碌的应用程序服务器超负荷运行,而是将新的请求分发到不太忙的服务器。把上面的配置信息中的 ip_hash 换成 least_conn 即可。
fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。与weight分配策略类似。需要安装第三方模块。如何得知响应时间长短?
url_hash(第三方)
和IP哈希类似,只不过针对请求的url进行hash(基于缓存的server,页面静态化)。后端服务器为缓存、文件、静态服务器时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法。缺点是当后端服务器宕机的时候,url_hash不会自动跳转的其他缓存服务器,而是返回给用户一个503错误。
应用场景
1.反向代理
正向代理 vs 反向代理
正向代理:一个位于客户端和原始服务器之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。如VPN;
反向代理:指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
优势
- 可以起到保护网站安全的作用,任何来自网络的请求都必须先经过代理服务器。
- 通过缓存静态资源,加速Web请求。
- 实现负载均衡。四层负载均衡的LVS,七层负载均衡的Nginx、Haproxy等。
实战
下面的负载均衡实战,nginx就是一个反向代理服务器;
2.负载均衡
负载均衡,可用于优化资源的利用率, 最大化吞吐量,减少延迟并确保容错配置。
下面以一个偏前端 nginx server 搭配两个后端 Tomcat server 来实现一个超级简单的负载均衡;以Windows 系统为例,其他系统类似;主要步骤:
- 下载 nginx 和 Tomcat zip 解压缩安装包,Tomcat 复制一份(当然,此处也可以下载两个不同版本的Tomcat 安装包,但是在生产环境不建议这么做,不稳定;另一方面,如果是想要升级后端的Tomcat server 的版本,比如为了使用 HTTP 2 的特性,会想要升级生产环境的 Tomcat server的版本,此时可以通过这种方式来实现所谓的灰度发布,即先使用权重负载均衡算法把前端的流量的20%转移分配到新版本的 Tomcat server,80% 的流量依旧使用旧版本,在线上运行一段时间,发现新版本的没有什么问题,后续可以逐步实现完全的流量切换),修改conf/server.xml 配置文件里面的端口 port 实现单机安装多个 Tomcat server,即我们在学习 hadoop 时所谓的伪分布部署模式。此处修改配置端口信息时,建议把 server.xml 里面的所有的端口信息都修改一下,除非是在很熟悉 Tomcat 这几个端口的作用的情况下。
- 同时修改 webapps/ROOT/index.jsp 里面的 body 标签的内容,方便我们识别两个 Tomcat server;效果如图;为了偷懒,第一个 Tomcat server 保持其端口信息不变即可:
- 修改 nginx 的配置文件 nginx.conf:
浏览器访问 http://localhost:81/index.jsp,刷新页面,看到出现 Tomcat2 字样的页面(即请求到达后端Tomcat server 2)的概率是 Tomcat server 1 的2倍,这正是负载均衡算法在起作用。
3. HTTP服务器(包含动静分离)
4.正向代理
5.虚拟主机
改进
虽然 nginx 已经足够强大,性能优越,并且有非常多的扩展模块(可以理解为插件)可以考虑安装使用,但是很多大公司依旧不满意,于是催生出一系列 nginx 的进阶版:
- nginx plus 商业版
difference - tengine 淘宝改进版
- OpenResty
- kong
参考:
Nginx开发从入门到精通
nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
nginx -c /etc/nginx/conf.d/nacos.conf
nginx: [emerg] “upstream” directive is not allowed here in /etc/nginx/conf.d/nacos.conf:1