Nginx是一款高性能的web服务器、反向代理服务器及电子邮件(IMAP/POP3)代理服务器,具有占用内存少,并发能力强等优点。


一、nginx相关网站

    官网:http://nginx.org/

    官方文档:http://nginx.org/en/docs/

    中文文档:http://tengine.taobao.org/nginx_docs/cn/docs/


二、nginx的功能与特性

  1、基本功能及特性

    ①作为静态资源的web服务器,能缓存打开的文件描述符;

    ②作为反向代理服务器,可做缓存负载均衡

    ③支持FastCGI

    ④模块化,非DSO机制(不能动态装卸载),过滤器gzip,SSI和图像大小调整等

    ⑤支持SSL

  2、扩展功能:

    ①基于名称和IP做虚拟主机

    ②支持keepalive

    ③支持平滑配置更新或程序版本升级

    ④定制访问日志,支持使用日志缓存以提高性能

    ⑤支持url rewrite

    ⑥支持路径别名

    ⑦支持基于IP及用户的认证;

    ⑧支持速率限制,并发限制等;


三、nginx的进程模型

wKioL1czUGKTDTSKAAK7c_RkVf8516.png

   传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需要占用CPU,过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。

  ◆nginx会运行一个主进程(master)若干个由其fork出来的工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信连接请求就由为数不多的几个仅包含一个线程的worker进程以高效的回环(run-loop)机制进行处理,这样就不会引起很多的进程/线程上下文切换,从而降低了系统开销。每个线程内部对socket的管理方式是异步非阻塞的,使用epoll事件驱动机制来实现对大量socket描述符的管理,当描述符多的时候也只是会占用较多的内存而已,而不会造成占用大量cpu时间,这就是nginx并发能力强的原因。每个worker可以并行处理数千个的并发连接及请求。

   每个worker进程是平等的,当有连接请求进来,交由哪个worker处理呢?master进程在建立需要listen的socket之后,fork出若干个worker进程,所有worker进程会抢互斥锁,抢到的的接受并处理连接请求,返回数据给客户端,最后断开连接,一个请求只在由一个worker处理。

   worker数是可以设置的:如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。

   主进程以root用户身份运行,而worker、cache loader和cache manager均应以非特权用户身份运行。

   主进程主要完成如下工作:

     ①读取并验正配置信息;

     ②创建、绑定及关闭套接字;

     ③启动、终止及维护worker进程的个数;

     ④无须中止服务而重新配置工作特性;

     ⑤控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;

     ⑥重新打开日志文件,实现日志滚动;

     ⑦编译嵌入式perl脚本;

   worker进程主要完成的任务包括:

     ①接收、传入并处理来自客户端的连接;

     ②提供反向代理及过滤功能;

     ③nginx任何能完成的其它任务;

   cache loader进程主要完成的任务包括:

     ①检查缓存存储中的缓存对象;

     ②使用缓存元数据建立内存数据库;

   cache manager进程的主要任务:

     ①缓存的失效及过期检验;


  ◆nginx支持sendfile和mmap

     sendfile()

       在传统的网络文件传输方式中,文件数据实际上是经过了四次copy操作:

          硬盘—>内核buffer—>用户buffer—>socket相关缓冲区—>协议引擎

       而sendfile系统调用则提供了一种减少以上多次copy,提升文件传输性能的方法:

          硬盘—>内核buffer—>socket相关缓冲区—>协议引擎

wKiom1c0AOvBZ_U6AABghDB67iU500.png

        在内核版本2.4之后,sendfile实现了更简单的方式,系统调用方式仍然一样,细节与2.1版本的不同之处在于,当文件数据被复制到内核缓冲区时,不再将所有数据copy到socket相关的缓冲区,而是仅仅将记录数据位置和长度相关的数据保存到socket相关的缓存,而实际数据将由DMA模块直接发送到协议引擎,再次减少了一次copy操作。

wKioL1c0BbmhMS2WAAAw3qYlLbo030.png


     mmap():内存映射

       进程访问文件的传统方法是,先由进程向内核发起系统调用,内核将文件由磁盘加载到内核缓冲区,再copy一个副本到进程空间(用户空间),如果有多个进程访问同一个文件, 则每一个进程在自己的地址空间都包含有该文件的副本,这不必要地浪费了存储空间。       

       mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。内核缓冲区中的普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。  


四、nginx的模块和工作原理

   nginx代码是由内核和一系列的模块组成, nginx内核主要用于提供Web Server的基本功能,以及Web和Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。不过,大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。

  ◆nginx模块从结构上分为:

      核心模块

      http模块

        http标准模块

        http可选模块

          如 http_stub_status_modulehttp_ssl_modulehttp_gzip_static_module

      邮件模块

      第三方扩展模块

  ◆nginx模块从功能上分为:

      handlers:此类模块直接处理请求,并生成内容

      filter:此类模块对其它handlers生成的内容进行修改,最后由nginx输出

      proxies:此类模块主要与后端服务如fastcgi进行交互,实现服务代理和负载均衡等功能


      nginx内核仅仅是通过查找配置文件将http请求映射到一个location block,而此location中所配置的各个指令则会启动不同的模块去完成工作,可以说nginx模块才是真正的劳动者。     

wKioL1czZpHi4tpWAADuN9QhaQ8768.png

  

    模块化设计是nginx的一个重要特点。要注意的是:nginx的模块是静态的,添加和删除模块都要对nginx进行重新编译,这一点与Apache的动态模块不同


五、nginx编译安装

  1、解决依赖关系

      yum -y groupinstall "Development Tools" "Server Platform Development"

      yum -y install gcc pcre-devel openssl-devel zlib-devel

       nginx的rewrite模块和http核心模块会用到PCRE正则表达式语法,所以要安装pcre-devel,PCRE(Perl Compatible Regular Expressions)是一个轻量级的Perl函数库

  2、添加用户nginx,实现以之运行nginx服务进程

      useradd -r -s /sbin/nologin nginx

  3、到官网下载源码包,解压并编译、安装     

      tar xf nginx-1.10.2.tar.gz 

      cd nginx-1.10.2

      ./configure \

       --prefix=/usr/local/nginx-1.10.2 \

       --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 \

       --user=nginx \   #指定以什么身份运行worker进程

       --group=nginx \

       --with-http_ssl_module \

       --with-http_flv_module \   #流媒体模块

       --with-http_stub_status_module \  #监控运行状态的模块

       --with-http_gzip_static_module \

       --http-client-body-temp-path=/usr/local/nginx/client \   #临时包体的暂存路径

       --http-proxy-temp-path=/usr/local/nginx/proxy \

       --http-fastcgi-temp-path=/usr/local/nginx/fcgi \

       --http-uwsgi-temp-path=/usr/local/nginx/uwsgi \

       --http-scgi-temp-path=/usr/local/nginx/scgi \

       --with-pcre

      make && make install

      ln -s /usr/local/nginx-1.10.2 /usr/local/nginx

      ◆说明:

         ①Nginx可以使用Tmalloc(快速、多线程的malloc库及优秀性能分析工具)来加速内存分配,使用此功能需要事先安装gperftools,而后在编译nginx添加--with-google_perftools_module选项即可。

         ②如果想使用nginx的perl模块,可以通过为configure脚本添加--with-http_perl_module选项来实现,但目前此模块仍处于实验性使用阶段,可能会在运行中出现意外

  4、提供服务脚本并添加开机自动启动

      vim /etc/rc.d/init.d/nginx

       ...

      chmod +x /etc/rc.d/init.d/nginx

      chkconfig --add nginx

      chkconfig on nginx

      其它操作:

        vim /etc/profile.d/nginx.sh
          export PATH=$PATH:/usr/local/nginx/sbin   #更新PATH环境变量

        ln -s /usr/local/nginx/conf /etc/nginx/conf   #创建配置文件目录的软链接,便于访问

  5、启动服务

      service nginx start

  6、nginx命令

      用法:nginx [option]...

      常用选项:

        -p prefix:set prefix path,默认是安装时指定的路径

        -c filename:指定配置文件,默认从安装时指定的路径下寻找

        -t:配置文件检查

        -v:显示nginx版本

        -V:显示nginx版本及安装时配置的参数    

[root@node1 ~]# yum -y groupinstall "Development Tools" "Server Platform Development"
...
[root@node1 ~]# yum -y install pcre-devel
...
[root@node1 ~]# useradd -r nginx
[root@node1 ~]# id nginx
uid=496(nginx) gid=493(nginx) groups=493(nginx)
[root@node1 ~]# tar xf nginx-1.10.2.tar.gz 
[root@node1 ~]# cd nginx-1.10.2
[root@node1 nginx-1.10.2]# ls
auto  CHANGES  CHANGES.ru  conf  configure  contrib  html  LICENSE  man  README  src
[root@node1 nginx-1.10.2]# ./configure --prefix=/usr/local/nginx-1.10.2 \
> --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 \
> --user=nginx \
> --group=nginx \
> --with-http_ssl_module \
> --with-http_flv_module \
> --with-http_stub_status_module \
> --with-http_gzip_static_module \
> --http-client-body-temp-path=/usr/local/nginx/client \
> --http-proxy-temp-path=/usr/local/nginx/proxy \
> --http-fastcgi-temp-path=/usr/local/nginx/fcgi \
> --http-uwsgi-temp-path=/usr/local/nginx/uwsgi \
> --http-scgi-temp-path=/usr/local/nginx/scgi \
> --with-pcre
...
[root@node1 nginx-1.10.2]# make && make install
...
[root@node1 nginx-1.10.2]# ln -s /usr/local/nginx-1.10.2 /usr/local/nginx
[root@node1 nginx-1.10.2]# cd /usr/local/nginx/
[root@node1 nginx]# ls
conf  html  sbin
[root@node1 nginx]# ls conf
fastcgi.conf          fastcgi_params          koi-utf  mime.types          nginx.conf          scgi_params          uwsgi_params          win-utf
fastcgi.conf.default  fastcgi_params.default  koi-win  mime.types.default  nginx.conf.default  scgi_params.default  uwsgi_params.default
[root@node1 nginx]# ls sbin
nginx    #主程序
[root@node1 nginx]# ls html/
50x.html  index.html
[root@node1 nginx]# vim /etc/profile.d/nginx.sh

export PATH=$PATH:/usr/local/nginx/sbin
[root@node1 nginx]# source !$
[root@node1 nginx]# ln -s /usr/local/nginx/conf /etc/nginx/conf
[root@node1 nginx]# vim /etc/rc.d/init.d/nginx
...
[root@node1 nginx]# chmod +x !$
chmod +x /etc/rc.d/init.d/nginx
[root@node1 nginx]# chkconfig --add nginx
[root@node1 nginx]# chkconfig nginx on
[root@node1 nginx]# service nginx start
Starting nginx:                            [  OK  ]
[root@node1 nginx]# ss -tnl
State       Recv-Q Send-Q                Local Address:Port             Peer Address:Port 
...
LISTEN      0      128                   *:80                 *:*
[root@node1 nginx]# nginx -v
nginx version: nginx/1.10.2