NGINX代理服务器
1、NGINX是什么?
1.1、NGINX的简介
来自俄罗斯的Igor Sysoev在为Rambler Media(http://www.rambler.ru/ ) 工作期间, 使用C语言开发了Nginx。Nginx作为Web服务器,一直为俄罗斯著名的门户网站RamblerMedia提供着出色、稳定的服务。IgorSysoev将Nginx的代码开源。由于Nginx使用基于事件驱动的架构能够并发处理百万级别的TCP连接,高度模块化的设计和自由的许可证使得扩展Nginx功能的第三方模块层出不穷,而且优秀的设计带来了极佳的稳定性,因此其作为Web服务器被广泛应用到大流量的网站上,包括腾讯、新浪、网易、淘宝等访问量巨大的网站。
Nginx是一个高性能HTTP服务器代理软件,也是一台IMAP/POP3/SMTP/TCP代理服务器。对于高效处理大规模并发连接,支持epoll工作模式,在安装上相比Apache仅仅只有几百K,在功能实现上都采用模块化结构设计,都支持通用的语言接口,如PHP,PERL,PYTHON等,同时还支持正向和反向代理、虚拟主机、URL重写、压缩传输、SSL加密传输等。支持跨平台,可运行在Linux、FreeBSD、Solaris、AIX、MacOS、Windows等操作系统上。
1.2、NGINX的市场发展情况
Apache的发展时期很长,在很长一段时间Apache都是世界第一大Web服务器,而Nginx在进几年发展迅猛,受到各类大型网站的青睐,不远的未来一定会成为世界第一Web服务器。
图一是截止2019年2月28日的世界Web服务器的使用排名情况。
图一:
2、为什么选择NGINX?
2.1、选择NGINX的优势所在
现如今快速增长的互联网用户群以及业内所有互联网服务提供商越来越好的用户体验, 都促使我们在大流量服务中用Nginx取代其他Web服务器。 Nginx先天的事件驱动型设计、 全异步的网络I/O处理机制、极少的进程间切换以及许多优化设计,都使得Nginx天生善于处理高并发压力下的互联网请求,同时Nginx降低了资源消耗,可以把服务器硬件资源“压榨”到极致
通过上面的简单介绍,可以看出,Nginx作为HTTP服务器的优势是显而易见的,它有很多其他Web服务器无法比拟的性能和优势;
- 作为Web服务器,Nginx处理静态文件、索引文件,自动索引的效率非常高
- 作为代理服务器,Nginx可以实现无缓存的反向代理加速,提高网站运行速度
- 作为负载均衡服务器,可以支持HTTP代理服务器对外进行服务,同时还支持简单的容错和利用算法进行负载均衡。
- 在性能方面,Nginx专门为性能优化而开发,它采用内核POLL模型,可以支持更多的并发连接,单机可以支持100000以上的并发连接,而且占用很低的内存资源。理论上,Nginx支持的并发连接上限取决于内存,10万远未封顶。当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的。
- 在稳定性方面,Nginx采取了分阶段资源分配技术,使得CPU与内存的占用率非常低。Nginx官方提示,在保持10000个非活跃的HTTP长连接,而这些连接只占用2.5MB内存
- 在高可用性方面,master管理进程与worker工作进程的分离设计,使得Nginx能够提供热部署功能,即可以在7×24小时不间断服务的前提下,升级Nginx的可执行文件。当然,它也支持不停止服务就更新配置项、 更换日志文件等功能。
- 在扩展性方面,Nginx它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。这种低耦合度的优秀设计,造就了Nginx庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样易使用。
3、NGINX的组成与工作原理
Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅是通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个命令,用于URL匹配),而在这个location中所配置的每个命令将会启动不同的模块去完成相应的工作。
Nginx的模块从结构上分为核心模块、基础模块和第三方模块,其中,HTTP模块、EVENT模块和MAIL模块等属于核心模块,HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块属于基本模块,而HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块属于第三方模块,用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支持,Nginx功能才会如此强大。
Nginx的模块从功能上分为如下三类:
- Handlers(处理器模块)。此类模块之间处理请求,并进行输出内容和修改headers信息等操作,handlers处理器模块一般只能有一个。
- Filters(过滤器模块)。此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。
- Proxies(代理类模块)。此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
如图二所示Nginx模块常规的HTTP请求和响应的过程:
图二:
- Nginx的模块直接被编译进Nginx,因此属于静态编译方式。在启动Nginx后,自动加载Nginx的模块,不像在Apache中一样,首先将模块编译为一个SO文件,然后在配置文件中指定是否加载。在解析配置文件时,Nginx的每个模块都有可能去处理某各请求,但是同一个处理请求只能有一个模块来完成。
4、NGINX安装与部署
- Nginx的官方网站是(https://nginx.org),从这里可以获得Nginx的最新版本信息。Nginx一般有三个版本:稳定版、开发版和历史稳定版。开版更新较快,包含最新的功能和BUG的修复,存在不稳定因素。稳定版更新慢,BUG少,作为生产环境的首选,本文已目前生产版本nginx-1.12.1作为安装讲解对象。
4.1、实验环境
平台 | IP | 用途 | 版本 | |
---|---|---|---|---|
CentOS 6.7 64Bit | 192.168.2.245 | WEB代理和负载均衡 | 1.12.1 |
4.2、安装EPEL源
1 | [root@localhost ~]# rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/Packages/e/epel-release-6-8.noarch.rpm |
4.3、安装编译开发环境
1 | [root@localhost ~]# yum groupinstall "Development Tools" -y |
4.4、安装各项依赖组件
1 | [root@localhost ~]# yum install pcre-devel zlib-devel libjpeg-devel libpng-devel freetype-devel openssl-devel curl curl-devel libxml2 libxml2-devel libjpeg libjpeg-devel libpng libpng-devel libmcrypt libmcrypt-devel openldap openldap-devel openssh-client -y |
4.5、解压NGINX及各项第三方模块
1 | [root@localhost soft]# unzip nginx-limit-upstream-master.zip |
4.6、安装NGINX及各项模块
1 | [root@localhost soft]# cd nginx-1.12.1 |
5、NGINX配置与维护技巧
5.1、NGINX配置文件详解
- Nginx安装完毕后,会产生相应的安装目录,根据前面的编译安装路径,Nginx的配置文件结构如图三,这里重点介绍nginx.conf配置文件。
图三:
- Nginx配置文件主要分为四个部分:main全局设置、server主机设置、upstream负载均衡服务器设置和location(URL匹配设置)。main部分设置的指令将影响其他所有设置;server部分的指令主要用于指定主机和端口;upstream指令主要用于负载均衡,设置一系列的后端服务器;location部分用于匹配网页位置。这四者的直接关系如下:server继承main,location继承server,upstream既不会继承其他设置也不会被继承。一个完整的配置文件结构如图四:
图四:
5.1.1、NGINX全局配置
1 | user www www; |
如上通过一个Nginx配置实列详细介绍nginx.conf每个命令的含义。解释如下:
- user:是个主模块指令,指定Nginx Worker进程运行用户以及用户组,默认是nobody用户运行。
- worker_processes:是个主模块指令,指定了Nginx要开启的进程数。每个Nginx进程平均耗费10~12MB内存。如果是多核CPU,建议指定和CPU的数量一样多的进程数即可
- error_log:是个主模块指令,用来定义全局错误日志文件。日志输出级别又debug、info、notice、warn、error、crit可供选择,其中,debug输出的日志作为详细
- pid:是个主模块指令,用来指定进程id的存储文件位置。
- worker_rlimit_nofile:用于绑定worker进程和cpu,linux内存2.4以上可用
- events:指令用来设定Nginx的工作模式及连接数上限
- use:是个事件模块指令,用来指定Nginx的工作模式,Nginx支持的工作模式又select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系统中。对于Linux系统,epoll工作模式是首选。
- worker_connections:也是个事件模块指令,用于定于Nginx每个进程的最大连接数,默认是1024。最大客户的链接数由worker_processes和worker_connections决定,在作为反向代理时变为:max_clients=worker_connections*worker_processes/4。
进程的最大连接数是手linux操作系统最大打开文件数限制,在执行操作系统命令”ulimit -n 65536”后worker_connections的设置才能生效。
5.1.2、HTTP服务器配置
1 | http { |
如下内容是Nginx对HTTP服务器相关属性的配置,解析如下:
- include:主模块命令,实现对配置文件所包含文件的设定,可以减少主配置文件复杂度
- defailt_type:属于HTTP核心模块命令,这里设定默认类型为而二进制流,也就是当文件类型未定义时使用这种方式,列如,在没有配置PHP环境时,Nginx是不与解析的,此时,用浏览器访问PHP文件就会出现下载窗口。
- log_format:用于指定Nginx日志的输出格式。Main为此日志输出格式的名称,可以在下面的access_log命令中引用。
- client_max_body_size:用来设置允许客户端请求的最大单个文件字节数。
- client_header_buffer_size:用于指定来自客户端请求头的headerbuffer大小。对于大多数请求,1KB的缓冲区大小已经足够,如果自定义了消息头或更大的cookie,可以增加缓冲区大小。这里设置为32KB.
- large_client_header_buffers:用来指定客户端请求中较大的消息头的缓存最大数量和大小,”4”为个数,”128K”为大小,最大缓存量为4个128KB。
- sendfile:用于开启高效文件传输模式。将tcp_nopush和tcp_nodelay两个命令设置为”on”用于防止网络阻塞。
- keepalive_timeout:设置客户端连接保持活动的超时时间。在超过这个世界之后,服务器会关闭该连接。
- client_header_timeout:设置客户端请求头读取超时时间。如果超过这个世界,客户端还有没发送数据,Nginx将返回”Request time out(408)”错误。
- client_body_timeout:设置客户端请求主体读取超时时间。如果超过这个时间,客户端还没有发送任何数据,Nginx将返回”Request time out(408)”错误,默认值60秒。
- send_timeout:指定响应客户客户端的超时时间,这个超时仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx将会关闭连接。
5.1.3、负载均衡配置
upstream是Nginx的HTTP Upstream模块,这个模块通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。在下面的设定中,通过upstream指令指定了一个负载均衡器的名称lisir.com。这个名称可以任意指定,在后面配置虚拟主机(域名)的地方需要直接调用。
1
2
3
4
5
6
7upstream lisir.com {
ip_hash;
server 192.168.1.30:2100;
server 192.168.1.30:2103 down;
server 192.168.1.30:2106 max_fails=3 fail_timeout=20s;
server 192.168.1.30:2109 backup;
}Nginx的负载均衡模块目前支持4种调度算法。
- 轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器死机,自动剔除故障,使用户访问不受影响。
- weight:指定轮询权值,weight值越大,分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。
- ip_hash:每个请求按访问IP的哈希结果进行分配,这样来自同一个IP的方可固定访问一台后端服务器,主要用于解决动态网页存在session共享问题。
- fair:它是比上面两种更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡。需安装upstream_fair模块
- url_hash:按访问URL的哈希结果来分配请求,使每个URL定向到同一台后端服务器,可以进一步提高后端缓存服务器的效率。需安装url_hash模块。
- down:表示当前的server服务器暂时不参与负载均衡。
- backup:预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器。
- max_fails:允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream模块定义的错误信息。
- fail_timeout:在经历了max_fails次失败后,暂停服务器的时间。max_fails和fail_timeout可以一起使用
5.1.4、server虚拟主机配置
1 | server { |
建议将对虚拟主机进行配置的内容写进另外一个文件,然后通过include命令包含进来,这样更便于维护和管理。配置虚拟主机代码中每个参数的含义如下:
- server:定义虚拟主机开始的关键字。
- listen:用于指定虚拟主机的服务端口。
- server_name:用来指定IP地址或域名,多个域名之间用空格分开。
- index:用于设定访问的默认首页地址。
- root:用于指定虚拟主机的网页根目录,这个目录可以是相对路径,也可以是绝对路径。
- charset:用于设置网页的默认编码格式。
- acess_log:用来指定此虚拟主机的访问日志存放路径,最后的main用于指定访问日志的输出格式。
5.1.5、url匹配配置
URL地址匹配是Nginx配置中最灵活的部分。通过location关键字定定义了地址匹配的开始。location支持正则表达式匹配,也支持条件判断匹配。用户可以通过location命令实现Nginx对动态、静态网页进行过滤处理。在上面这段location代码中,所有扩展名以.gif、.jpg、.jpeg、.png、.bmp、.swf结尾的静态文件都交给Nginx处理,而expires用来指定静态文件的过期时间,这里是30天。
1
2
3
4location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
root /web/wwwroot/images;
expires 30d;
}同理,下面这段代码是将upload和tml下所有的文件都交给Nginx来处理,当然,upload和html目录包含在/web/wwwroot目录中。
1
2
3
4location ~ ^/(upload|html)/ {
root /web/wwwroot/images;
expires 30d;
}在下面这段代码中,通过location关键字实现了将所有以.jsp为后缀的文件都交给本机的8080端口处理。
1
2
3
4location ~ .*.jsp* {
index index.jsp;
proxy_pass http://localhost:8080;
}location正则表达式匹配,其中:
1
2
3
4
5
6
7
8
9
10
11
12~ 为区分大小写匹配
~* 为不区分大小写匹配
!~和!~*分别为区分大小写不匹配及不区分大小写不匹配
^ 以什么开头的匹配
$ 以什么结尾的匹配
转义字符。可以转. * ?等
* 代表任意字符
= 开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,不是正则匹配
/ 通用匹配, 如果没有其它匹配,任何请求都会匹配到
优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
5.1.6、错误信息返回页面配置
1 | error_page 404 /404.html; |
- 通过error_page命令可以定制各种错误信息的返回页面。在默认情况下,Nginx会在主目录中查找指定的返回页面。在默认情况下,Nginx会在主目录的html目录中查找指定的返回页面。
5.2、NGINX日常维护技巧
5.2.1、NGINX配置正确性检查
Nginx提供的配置文件调试功能非常有用,可以快速定位配置文件存在的问题。执行如下命令检测配置文件的正确性:
1
2
3
4
5
6
7
8[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
#或者
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
#其中-t参数用于检查配置文件是否正确,但并不执行。-c参数用于指定配置文件的路径,如果不指定,Nginx默认会在安装目录下查找conf/nginx.conf文件。另外,Nginx也提供了查看版本及相关编译信息的功能,在命令行执行以下命令可以显示安装Nginx的版本信息:
1
2
3
4
5
6
7
8
9
10
11[root@localhost ~]# /usr/local/nginx/sbin/nginx -v
nginx version: 1.12.1
#仅显示版本信息
[root@localhost ~]# /usr/local/nginx/sbin/nginx -V
nginx version: 1.12.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --with-http_ssl_module --add-module=/soft/naxsi-master/naxsi_src --add-module=/soft/nginx-limit-upstream-master --add-module=/soft/nginx-upstream-jvm-route-master
#-V显示安装Nginx版本和相关编译信息
5.2.2、NGINX的启动、关闭与重启
Nginx对进程的控制能力非常强大,可以通过信号命令控制进程。常用的信号有:
- QUIT:表示处理完当前请求后关闭进程。
- HUP:表示重新加载配置,即关闭原有的进程并开启新的工作进程。此才做不会中断用户的请求,因此,可以通过此信号平滑的重启Nginx。
- USER1:用于Nginx的日志切换,也就是重新打开一个日志文件,例如,每天要生成一个新的日志文件时,可以使用这个信号来控制。
- USER2:用于平滑升级可执行程序。
- WINCH:从容的关闭工作进程
Nginx的启动非常简单,只需要输入:
1 | [root@localhost ~]# /usr/local/nginx/sbin/nginx |
关闭Nginx,只需要输入:
1
kill -QUIT 主进程pid
Nginx的平滑重启可以使用如下命令:
1
[root@localhost ~]# kill -HUP 'cat /usr/local/nginx/logs/nginx.pid'
5.3、生产NGINX负载均衡配置案例
5.3.1、NGINX安装信息
1 | [root@localhost sbin]# ./nginx -V |
5.3.1、主配置文件:nginx.conf
1 | #日志格式 |
5.3.2、域名虚拟主机配置
1 | server { |
6、NGINX双机热备
6.1、keepalived工作原理
- Keepalived是一个基于VRRP协议来实现的服务高可用方案,可以利用其来避免IP和主机单点故障,一般不会单独部署,主要与其它负载均衡技术(如lvs、haproxy、nginx)一起工作来达到集群的高可用,本文档基于Keepalived实现了Nginx服务高可用,其网络架构如下图:
6.2、安装keepalived
1 | # yum install -y openssl-devel |
6.3、配置keepalived
6.3.1、修改主keepalived配置文件
1 | vim /etc/keepalived/keepalived.conf |
6.3.2、修改从keepalived配置文件
1 | vim /etc/keepalived/keepalived.conf |
6.4、配置keepalived主备日志文件
1 | #以下操作均在主备节点执行 |
6.5、配置keepalived主备切换通知脚本
1 | #以下操作均在主备节点执行 |
6.6、验证结果
7、NGINX目前状况
7.1、商业并购
- 3月11日,F5与NGINX 宣布了一项最终协议,根据该协议,F5将收购 NGINX 的所有已发行股票,总价值约为6.7 亿美元。
- F5 是应用交付网络(ADN)领域的全球领先厂商,其解决方案有助于整合不同的技术,以便更好地控制基础架构,提高应用交付和数据管理能力,并使用户能够通过企业桌面系统和智能设备无缝、安全并更快速地接入应用。而 NGINX 最知名产品 Nginx 是互联网上最受欢迎的 Web 服务器之一,NGINX 提供一整套用于开发和交付现代应用的技术,同时它也是应用交付领域的开源领导者。
被收购后 Nginx 会不会闭源?
1、微软收购了 GitHub,并免费开放私有仓库,微软用75亿美元收购了全球最大的社交编程及代码托管网站 GitHub。并承诺保持 GitHub 的独立运营,随后又做出免费开放私有仓库的决定。但也不是所有的收购,都能保证其原始的开源承诺
2、Oracle 收购了 MySQL,并更改了开源协议(GPL),MySQL在收购前一直使用 GPL 许可分发,而 GPL 许可是不可撤销的,这意味着至少被收购之前的最后一个 Release 可以无限制地免费使用(包括源代码),而且源代码可以被社区二次开发。这就是为什么,mysql现在有企业版和社区版的区别,就好像jdk和openjdk一样。所以NGINX未来被闭源的可能性是很低的,依然可能会像现在这样,出现nginx plus企业版和社区版,两条不同的分支有没有 Nginx 的替代方案?
Tengine
Tengine是由淘宝网发起的Web服务器项目。它在 Nginx 的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。
从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护着它。Tengine团队的核心成员来自于淘宝、搜狗等互联网企业