Nginx的官方站点:www.nginx.orgphp
Nginx:是engine X的简写前端
有两个分支比较流行:nginx
Nginx在研发时调用了libevent这个组件,libevent是一个通用的高性能的网络库。它里边实现了epoil()这么一个调用,epoil()其实就是基于事件驱动的event模型的一个开发好的库文件。所以咱们要想实现事件驱动模型,直接调用epoil()就能够了。而Nginx就调用了libevent这个高性能网络库中的epoil(),虽然咱们说调用epoil(),事实上Nginx对这些众多的网络并发编程库支持的普遍程度还应该是超出想象的。程序员
所以做为程序员能够为Nginx设计第三方模块,不过与httpd不一样的是,Nginx早期包括如今的版本虽然是模块化的,也就意味着说咱们能够自行开发第三方模块对Nginx进行扩展,可是Nginx不支持模块动态装卸载的,也就是说编译的时候只能静态直接编译进Nginx并且随Nginx的启动而启动,即模块编译好以后能够直接使用,但只能直接编译成Nginx组成部分,只要Nginx启动,那么这个模块就必定会启动,它不支持动态装卸载。可是Tengine对Nginx的改进使得Tengine支持模块动态装卸载。web
这是已经通过市场普遍验证的;它的高可靠性是靠其特殊的工做机制来实现的,其高可靠性依赖于主控进程与工做进程或工做线程的架构来实现的。虽然形容为特殊可是其实httpd也是这么工做的。Nginx的组成部分其实是由一个主控进程master加多个子进程worker共同组成的,它有一个主控进程master,主控进程并不负责接收并响应任何用户请求,主控进程负责生成多个工做进程worker。其主控进程主要负责读取并验证即解析配置文件、建立绑定或关闭套接字、以及启动或终止维护worker进程的个数、还有无需重启进程让新配置文件中的新配置加载甚至于完成平滑版本升级等等。而worker子进程有多种种类,有的worker是实现缓存加载的,这在其反向代理模式中才有用、而有些是负责响应用户请求说白了就是接收传入并处理客户端的链接请求的、此外worker进程中还有一种进程叫作Cache Manager用来实现缓存管理。正则表达式
因为Nginx是使用一个内存响应n个请求的,因此它对内存的消耗很是低,有人作过统计说1w个保持链接keep-alive状态或模式下的connection,Nginx只须要消耗2.5M内存来维护;编程
所谓热部署指的是若是咱们的配置文件更新了不用重启Nginx,新配置文件就可以生效了。甚至于Nginx的版本更新了,如如今用的是1.4的版本想升级到1.6,1.4的版本不用停机,1.6的慢慢就会切上去了。事后等1.6的切换完成了可让1.4的再下线。后端
因此他支持热部署,所以这里的热部署指的是不停机而更新配置文件或者是更换日志文件即日志文件的滚动也包括升级程序版本等等都能实现。这就是热部署的功能。浏览器
虽然称Nginx为一个Web服务器,可是事实上它能支持多种功能,如:缓存
最根本的它是静态资源的web服务器而不是一个应用程序服务器。说白了若是打开一个文件这个文件对应的描述符信息它可以缓存下来,因此从而使得咱们再次访问同一个文件时打开的性能会被提高。
所以它既能够做为一个WEB服务器工做也能够做为一个WEB服务器的反向代理服务器工做。那反向代理服务器是什么呢?咱们简单作一下介绍。
原本咱们Web服务器的工做模式是在浏览器或客户端(User Agent)和服务器端之间直接进行的,全部的用户请求是直接从User Agent经过网络提交给Web服务器的。响应也是由Web服务器直接响应给客户端浏览器的。可是这样一来,用户将直接面对Web服务器,或者换句话来说,Web服务器将直接面对众多的客户端,那也就意味着Web服务器本身记得负责创建链接维持链接还得负责处理用户请求,这样会使得Web服务器压力过大。
更重要的是,有些用户可能会攻击Web服务器。就像此前作nat同样,若是咱们可以把用户和服务器之间加一个隔离层也照样能让用户请求可以到达Web服务器是否是可能会更好?所以这样一来咱们能够再Web服务器的前端放一个主机,咱们能够把这个主机称为代理。
什么叫代理呢?代理即它把本身声称为叫Web服务器,可是事实上它不是。全部用户请求直接到达给这个代理主机,这个主机本身也监听在80端口上也可以接受http的请求,但它本身并不负责提供任何内容,而是当用户请求到达这个服务器后,这个服务器本身负责把用户请求接进用户空间,由于他有一个进程,注意,它也有一个服务进程。这个服务进程称为代理进程,他解析用户请求而且判断一下这个客户端是否是容许访问的,若是不是,一解析以后直接拒绝了。这个请求甚至就不能到达Web服务器的。若是咱们容许它访问,这个时候它也不会把用户的请求直接扔给后端服务器,而是它本身把用户的请求再改成封装成另一种样子然后再向后端服务器发送。好比咱们要发一个快递因而咱们本身作了一个包装,这个包装扔给快递公司了,好比像什么顺丰,扔给快递公司以后快递公司须要打包,空运也好陆运也罢反正得帮你运过去,可是顺丰认为你的包装不够安全,运输过程中可能会致使邮件损坏因此它把你的封装通通拆掉,再从新打包成它们认为安全可靠的封装,因此就这样作了改换。
所以当用户请求到达之后,这个服务器把用户请求分析完之后发现是可靠的,没问题,我能够帮你发给Web服务器让Web服务器进行响应,注意它本身没有任何内容而是它再一次把用户请求从新封装起来发给后端服务器。那这时候在后端服务器看来请求的发出者是中间这台主机,由于真正的请求是由他发出的,包括源地址也是中间服务器的地址,因此这样一来它就彻底隔离的客户端和后端服务器。也就是说,它可以声称本身是Web服务器,接收用户对Web的请求,可是却又不负责提供任何内容而是转而把这个用户请求本身从新封装后交给后端服务器从后端服务器取回内容。可是各位应该知道,从后端服务器取回内容后,咱们本身对取回的内容没有任何欲求,因此他带来的结果就是它会把这个取到的内容再一次把响应报文响应给客户端。因此客户端一看它向这个服务器发了请求服务器也响应给它了,可是事实上中间这台服务器并无响应任何内容,它只是代为到后端服务器去取相关内容的。可是它把本身扮演成的确是那台服务器的样子,因此咱们说这叫作反向代理。
而反代是能够n级的,即反向代理代理的也不是WEB服务器,它是另外更高一级的或更上一层的反向代理,能够代理n次。可是咱们说过http协议当中有一个请求方法是TRACE,TRACE方法就是探测从请求这到最终服务器之间到底中间通过了哪些代理服务器。这些代理就称为反向代理。以下图:
那什么是正向代理呢?正向代理与反向代理相似,注意,反向代理一般只为一个或有限的一部分网站提供反代。但正向代理指的是,用户不管访问任何网站,都把对网站的请求提交给代理主机,代理主机本身不管用户请求的是什么网站,都本身做为客户端到互联网上去联系那台服务器,而且把取到的结果直接在本地封装之后或者在本地构建之后响应给客户端。因此所谓正向代理指的是它主要表明客户端请求任何网站;所谓反向代理服务器指的是它只是代为接收用户请求而且自行让到某些或者某个有限的服务器上去取那个内容的,而不是到任何网站服务器去内容。因此反代主要是把本身扮演成某个特定服务器的样子,而正向代理是把本身扮演成全部服务器的样子,能够这么去理解。
关于代理的目的,不光只是代理、不光是隔离它还有加速的做用,代理服务器还能够在本地提供缓存,刚才咱们说过代理服务器本身到原始服务器上取到内容之后就构建了响应报文响应给请求者了。可是这样子当客户端请求同一个内容时他还得再来一遍,那为了不这个过程,对于某静态内容不常常发生改变的内容,咱们的代理服务器能够取到内容之后先缓存在本地。注意,缓存在本地的时候它是基于键值关系缓存的,有可能直接缓存在内存中,键一般是用户请求的URL,而值一般是对应的数据流,因此当同一个用户甚至是不一样用户来请求同一段内容时,咱们的代理服务器若是发现这个内容是能够被缓存,并且缓存还没有失效的话,那么他就从缓存中直接取得这个结果返回给客户端了,而不会向上游服务器或原始服务器发请求的。像这种他可以起到加速的做用而且极大的下降了或者减轻了后端服务器的压力。这就是所谓的反向代理。而Nginx能做为http、smtp、pop3这三种协议的反向代理,不光是Web,可是目前来看,众多的应用场景都是用在http协议上,smtp或POP被Nginx拿来反代的是很鲜见的。
刚才说过,缓存是用来加速的。
同时它还甚至于支持负载均衡机制,所谓负载均衡指的是在反代时后端的主机能够不止一个。若后端主机只有一个,用户请求直接交给后端,可是后端服务器实在是太忙了,扛不住,由于它有多是提供动态内容的,基于cgi模块或fastcgi模型,有多是一个httpd服务器,直接提供动态的脚本,向php内容提供。而前端服务器做为Nginx来说,能够轻易扛得住1万个并发请求,请求链接进来它可以帮你接进来。可是它把每个请求都转发给后端服务器,一个服务器最多并发到1千个就至关不错了,若是实在扛不住,怎么办呢?
能够多加几个后端服务器,所以,它能够把一部分用户请求发到第一台服务器,另一部分发到第二个,在一部分发到第三个服务器上。因此使得众多前端用户请求被分发至后端多台主机上来了,这就是一种负载均衡机制。而前面这台主机既是代理同时又是一个负载均衡调度器。可是做为调度器负载均衡时,和只反代一个主机时,它们两个所须要解决的问题其实它的复杂度是相去甚远的。
为何呢?各位能够明白,咱们给予负载均衡机制时,若是第一个用户过来请求时,假设这是一个电商站点,咱们给它转发到第一台服务器上去了。它在第一个服务器上登陆了而后再购物车中加了一堆商品,你们知道,http协议是无状态的,过一会链接断开,他一刷新,又被从新分发至第二台主机上来了。第二台主机上没有它的购物车,也没有它的相关信息。那所以这显然是没办法接受的,因此一旦要支持负载均衡机制,那么session保持,就是此前用户曾经创建的会话如何执行并进行保持将成为一个很是重要亟待解决的问题。
那如何解决这个问题,咱们有多种方案,后面讲到负载均衡时会详述这里的解决方案。但无论怎么讲,各位应该知道,这是Nginx另外的基本功能,它既能实现缓存加速又能实现负载均衡。固然缓存加速也主要是在反代时实现,负载均衡亦是如此。
那也就意味着,可以跟基于fpm模式工做的php服务器结合起来提供LNMP。LNMP指的是Nginx、MariaDB、PHP等相关对应的结合。其实除了fastcgi以外还有像uWSGI协议实现跟Python语言所研发的Web服务器应用程序进行交互等等。
从而可以提供https服务;
固然它也支持基于端口的虚拟主机;
Nginx基于用户的访问控制须要借助于httpd的htpassword来实现。
说白了就是来自于同一个IP咱们最多可以发起几个并发链接请求,同时来自于同一个IP最多可以发起多大的访问速率或者我给你传输数据时速率最多为多少等等。
事实上,Nginx有的功能,httpd都有,而httpd有的Nginx未必有,因此目前来看,Nginx取代不了httpd。
因此它的工做模式咱们能够理解为是这样的:
Nginx是由一个master进程,称为主进程,负责生成一个或多个worker进程或线程,这些worker进程才是真正去负责去接收并处理用户请求的。
那若是基于反代的话它还可以基于反代的Cache来实现加速,而既然有Cache了,你们知道缓存它总然会有一个时刻会失效的,每个缓存都有一个存活期限,那所以Cache Loader负责加载缓存,而Cache manager负责过时以及清理缓存等。
那么事实上worker与本地进程磁盘IO是支持AIO、mmap(内存映射)、各类高级IO机制、甚至还支持sendfile机制。
另外它还支持http协议、fastcgi协议、memcache等等跟各类后端存储进行打交道,它还能够做为反代向后进行打交道的。
而此前提到的几个Nginx特性此处也有展现:事件驱动、异步、非阻塞。
epoll机制是Linux上实现的事件驱动,可是若是使用的是BSD或者是Unix的话就不必定了。若是使用的是BSD则使用的是kqueue机制,若是是Servers的话,则用到的是/dev/poll。epoll、kqueue、/dev/poll这三个都是事件驱动模型,第一个是Linux上用的,第二个是BSD上用的,第三个是Servers上用的。但它们都是实现了相似的功能,而Nginx几乎都支持。
另外IO复用的时候,它支持select、poll、rt signal,也叫IO复用器。
sendfile默认状况下只能发送很小的文件可能最大不会超过几个K,而sendfile64能够支持更大的文件,能够在内核中直接实现响应。它们的大小上限是有要求的。
sendfile:
做为一个静态内容来说,当用户请求进来时它必定要先进入内核,由于用户的请求要先进入网卡设备。到达网卡设备后这个请求会经过注册监听在80端口上的内核套接字绑定,根据用户请求的目标端口从而使得实现向用户空间的Web服务器进行转发。WEB服务器收到请求后发现用户请求了某一个静态资源,因而它向内核发起IO请求,内核负责把文件从磁盘加载进内核内存,然后从内核内存复制给进程内存。接着进程接下来就应该响应这个用户请求了,那怎么响应啊?
构建响应报文,内容又从进程内存发往内核内存,由于不发往内存它怎么可以经过网卡响应给客户端,而咱们说过能调用网卡的只有内核,因此它又一次发起IO调用,只不过这一次IO是网络IO而不是磁盘IO。发起调用时会把数据从本身的进程内存空间发往内核内存空间,放到网卡发送队列中去进而经过网卡设备发出去了。
在这个过程中,咱们的数据是怎么走的?数据的走向,首先从磁盘到内核,从内核到用户空间,从用户空间又回到内核了。其实没有作什么改变,直接响应过去了,除了加了一个响应报文以外就发过去了。咱们能够发现这两次IO过程除了白白浪费时间是没有任何更好的效果的。那咱们能不能这样,当这个资源从内核取得以后直接就从内核响应给客户端得了,数据从内核到磁盘内存然后直接构建一个响应报文直接响应给客户端了。而这种机制就叫作sendfile。
固然,sendfile并非一种多么新鲜的机制,httpd也支持,不光是Nginx。
它与前面对应的httpd的prefork、worker、event相比较而言,它的模式就是:
非阻塞、事件驱动、由一个master进程生成多个worker线程,每一个worker响应n个请求。
因此若是做为Web服务器而言,他整体可以支持的响应并发数等于worker * n;若是生成了10个worker,每一个worker能响应1万个,那一共就能够响应10万个。固然了,Nginx没有这么大的能力,由于每个请求或链接进来咱们都得给它一个套接字,所以套接字所谓TCP来说最大数量端口也只有65535个,在考虑到其它服务在用,它系统在保留一些,因此能使用5万个就不错了。所以Nginx没准在有些极端场景中,听说有人曾经使用Nginx最大支持单机并发达到5.2万个。虽然这是理论值,可是国内有人让它很轻松支持3万个是没问题的。再多就有困难了。
不过还有特别强调的是,在反代模型下,有可能会更少。
Nginx刚才说过它是模块化的,所以有众多模块,那模块类型有哪些呢?无非就这样几个:(在官方文档中是这么分类的)
注意,前四种模块Nginx都自带,第五种模块,也就是所谓的第三方模块咱们须要在编译Nginx的时候本身手动指定模块在何处,本身手动指明模块文件。然后在编译时才能把它编译成Nginx的组成部分。
Nginx已然成为一个很是流行的Web服务器解决方案了,因此Nginx自己虽然没有直接被收入进咱们CentOS系统,但也已经被收入进EPEL源了。
使用yum查看是否有相关的包:
安装方法:
此处先演示一下如何源码编译Nginx。由于不一样的公司对于Nginx的定制安装是有着不一样要求的。
下载源码包:
编译安装程序包时,须要提供好最基本的开发环境。
注意:Nginx哪怕已经提供了开发环境时,也会有可能不会自动安装的一个依赖的软件包叫pcre-devel
说明:它要用到pcre-devel来实现poll扩展的这么一种表达式以实现URL重写。通常来说,URL重写的功能若是咱们须要用到,就有可能用到pcre-devel,因此建议把这个安装上。
查看配置选项:
选项说明:
--prefix=PATH:默认安装路径 --sbin-path=PATH:Nginx主程序的安装路径 --conf-path=PATH:主配置文件的路径 --error-log-path=PATH:错误日志路径 --pid-path=PATH:pid文件路径 --lock-path-PATH:锁文件路径 --user=USER:Nginx启动后它的worker会以哪一个普通用户的身份来运行,通常来说工做线程都应该以普通用户的身份运行。 --group=GROUP --with-…:表示启用这个功能的,须要注意的是,提示为with表示默承认能没启用;要启用使用with; --without-…:表示禁用这些功能的,而提示为without的表示默认启用了,要想禁用使用without; --http-client-body-temp-path=PATH:http协议若是对方使用的是PUT或POST方式请求,客户端会提交一些内容过来,这个内容经过网络传输一些数据它是流式化的,
是一个一个数据传过来的。所以若是传输的数据很大的话,客户端上传一个2G的数据咱们不能将其都放在内存中等待接受。
因此咱们能够把客户端上传的内容先放在一个临时目录中因此这是咱们定义临时目录位置的。因此这是客户端提交数据时临时存放的文件的路径。 --http-proxy-temp-path=PATH:做为代理服务器时代理内容,由于代理服务器咱们要从服务器取得内容在本地作处理之后在打包给客户端,他也须要用到一个临时目录。 --http-fastcgi-temp-path=PATH:fastcgi协议; --http-uwsgi-temp-path=PATH:uwsgi协议; --http-scgi-temp-path=PATH:scgi协议 注意:上述协议在反代时也都各自须要一些工做空间,咱们能够指定它们的工做时临时使用的临时路径。不指定也没有关系,它本身会找一个位置当成临时路径的。 --with-pcre:支持URL重写时,基于pcre可以支持更强大的正则表达式引擎; --with-openssl=DIR:支持使用openssl,仅用于指明openssl在什么地方的,其实咱们要启用对https的支持要是用的是—with-http-ssl_module模块的,
默认是没启用的,须要使用with启用。
建立用户用于运行Nginx进程:
[root@localhost nginx-1.6.3]# ./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --user=nginx --group=nginx --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx/nginx.pid --lock-path=/var/lock/nginx.lock --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-http_flv_module --with-http_mp4_module --http-client-body-temp-path=/var/tmp/nginx/client --http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi
注意:为了可以便于实现未来当系统损坏时,重装系统后配置文件存在有两种途径能够解决这个问题:要么放在etc下,未来得按期备份;要么就干脆不指定了就放在安装路径下这是最合理的作法。不少时候咱们未来安装时并不会把它的配置文件路径都指到/etc目录下去,而就放在安装目录下。这样会使得咱们未来迁移整个程序会变得很是容易。那此处仍然遵循风格,好比说为了咱们未来使用时方便仍然指定为/etc/nginx/nginx.conf,专门指定一个特定目录。注意一旦把主配置文件指在此处,那咱们主配置文件所用到的其它辅助配置文件也都会放在同一个目录下,因此咱们这里打开一个单独的目录来指明。
查看是否有程序监听80端口,若没有直接启动便可:
测试访问:
至此,安装完成!
worker_process:指定启动的worker进程数;
有配置指令,并且有些会有花括号,花括号表示这是一个配置段,只对其中一部份内容生效。其中有一部份内容是直接写在配置文件中,顶格写的。有一部分是events定义一个容器后里面能够定义一部份内容;有一个是http甚至还有其它内容。
因此整个Nginx的配置文件主要由这样几部分组成:
说白了就是对于其余配置段都是有效的;
全部跟web服务相关的配置都只能定义在http配置段当中;
注意:Nginx的全部配置指令通常而言是不区分大小写的,可是要以分号结尾。不然就是语法错误
语法格式:
directive value1 [value2…]
Nginx支持使用变量
变量分为两类:
内置变量是由模块自带的,每引入一个模块,这个模块都有可能提供一些新变量。因此模块会提供内建变量的定义;那核心模块提供一堆变量,其它模块像标准的TCP/IP模块也会提供一堆的变量。
在配置文件中使用set var_name value表示给它定义了一个变量并定义了一个值。然后咱们就能够在配置文件的其余位置进行调用了。
其实,咱们要想可以配置Nginx就须要不断的修改它的配置文件来实现,而它的配置文件刚才咱们说过有主配置段、event配置段、http配置段组成。main配置段的指令配置很是多,Nginx的指令参数大概有上百个之多,咱们不可能一一去了解它,也不必一一去了解,只了解一些关键的就行。可是尽管这么讲,它的主配置段的指令大致能够分为四类:
注意:事实上,event也算做是main配置的组成部分,由于event那一段对全部的协议包括http、smtp等等也都同样是生效的。
接下来就对Nginx的每个指令功用或者是最核心的指令使用机制、功用来作介绍。其中主配置段的指令当中有不少个,讲完以后接下来就将Nginx本身的配置,好比如何使用虚拟主机、如何后使用别名、如何定义location、如何定义URL重写等等。