介绍

Nginx是俄罗斯程序员Igor Sysoev使用C语言开发的一个基于事件模型的开源免费Web Server,可以用做反向代理,负载均衡以及HTTP缓存等,最早发布于2004年。Nginx以性能为主要追求目标,随着互联网的规模越来越大,用户越来越多,高并发的场景也越来越常见,对服务的性能要求随之越来越高,在这种情景下,Nginx自然获得了大多数公司的青睐。

Nginx主要有以下几个特点:

  • 高性能,无论是单次请求还是在高并发场景下,比其他的Web Server响应更快。
  • 高扩展性,Nginx的功能高度模块化,耦合度低,极具扩展性。
  • 高可靠性,采用Master-Worker的架构设计,每个Worker独立,Master守护每个Worker的运行。
  • 低内存消耗,1w个非活跃的HTTP的Keep-Alive连接在Nginx仅消耗2.5MB的内存。

直接安装

以Debian系统为例。

$ ape-get install nginx

源码安装

以Debian系统为例。

准备

  • 编译工具

    $ apt-get install gcc g++ make
    
  • 主要依赖库

    • PCRE:全称Perl Compatible Regular Expressions,一个正则表达式库,用于支持Nginx中的正则解析。

      $ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.40.tar.gz
      $ tar zxf pcre-8.40.tar.gz
      
    • zlib:用于对HTTP包做gzip格式的压缩的库。

      $ wget http://zlib.net/zlib-1.2.11.tar.gz
      $ tar zxf zlib-1.2.11.tar.gz
      
    • OpenSSL:支持SSL协议的库。

      $ wget http://www.openssl.org/source/openssl-1.0.2f.tar.gz
      $ tar zxf openssl-1.0.2f.tar.gz
      # OpenSSL是一个很常用的工具,如果之前没有安装的话,这里可以执行
      $ ./Configure linux-x86_64 && make && sudo make install
      # 安装OpenSSL
      
  • 获取Nginx源码

    $ wget http://nginx.org/download/nginx-1.11.9.tar.gz
    $ tar zxf nginx-1.11.9.tar.gz
    $ cd nginx-1.11.9
    

目录介绍

进入Nginx源码目录之后可以看到下面的文件和文件夹:

CHANGES     # Nginx版本发布日志,可以看到从0.1.0开始完整的Nginx特性变更
CHANGES.ru  # Nginx版本发布日志俄语版
LICENSE     # 软件发布协议
README      # 说明,这里没有,都在官网http://nginx.org
auto/       # Nginx安装时用到的脚本文件,具体使用在configure文件安中体现
conf/       # Nginx自带的默认配置,安装之后会copy一份到安装目录
configure*  # 编译前的配置文件,根据配置时的参数,定义一些编译参数,调用auto目录中的脚本,然后生成Makefile文件
contrib/    # 一些转换脚本以及Nginx配置文件的Vim语法高亮,在里面的README文件中有说明
html/       # Nginx自带的HTML文件,简单的首页以及错误页面,用于测试,安装之后会copy一份到安装目录
man/        # man手册
src/        # Nginx源码

编译配置

执行./configure --help可以查看所有支持的编译配置选项,其中默认安装的会用--without前缀,默认不安装的会用--with前缀。

路径配置参数
--prefix=PATH            # 安装后的根目录,默认在/usr/local/nginx
--sbin-path=PATH         # 安装后nginx可执行文件位置,默认在<prefix>/sbin
--modules-path=PATH      # 模块文件位置
--conf-path=PATH         # 配置文件位置,默认在<prefix>/conf/nginx.conf
--error-log-path=PATH    # error日志位置,默认在<prefix>/logs/error.log
--pid-path=PATH          # PID文件位置,存放master进程ID,默认在<prefix>/logs/nginx.pid
--lock-path=PATH         # lock文件位置,默认在<prefix>/logs/nginx.lock

--build=NAME             # 二进制文件名
--builddir=DIR           # 编译产生临时文件位置,包括Makefile,C的源文件目标文件以及最后生成的nginx可执行文件

--http-log-path=PATH     # HTTP访问结束时记录的日志文件位置,默认在<prefix>/logs/access.log

--http-client-body-temp-path=PATH # 处理HTTP请求包时如果需要暂时临时存到磁盘文件的话存放在这个位置,默认在<prefix>/client_body_temp
--http-proxy-temp-path=PATH       # 做HTTP反向代理时,上游服务器产生的HTTP包需要临时存到磁盘文件的话存放到这个位置,默认在<prefix>/proxy_temp
--http-fastcgi-temp-path=PATH     # FastCGI所使用的临时文件放置目录,默认在<prefix>/fastcgi_temp
--http-uwsgi-temp-path=PATH       # uWSGI所使用的临时文件放置目录,默认在<prefix>/uwsgi_temp
--http-scgi-temp-path=PATH        # SCGI所使用的临时文件放置目录,默认在<prefix>/scgi_temp
编译配置参数
--with-cc=PATH                     # C编译器路径
--with-cpp=PATH                    # C预编译器路径
--with-cc-opt=OPTIONS              # C编译选项
--with-ld-opt=OPTIONS              # 链接选项
--with-cpu-opt=CPU                 # CPU型号,支持pentium, pentiumpro, pentium3, pentium4, athlon, opteron, sparc32, sparc64, ppc64
依赖配置参数
--without-pcre                    # 不安装PCRE,如果在nginx配置文件中没有使用正则就可以不用安装PCRE
--with-pcre                       # 强制使用PCRE
--with-pcre=DIR                   # 指定PCRE源码位置,编译Nginx时会进入该目录编译
--with-pcre-opt=OPTIONS           # PCRE源码编译选项,一般没有
--with-pcre-jit                   # 编译PCRE时使用Just-in-time优化选项。参考https://www.pcre.org/original/doc/html/pcrejit.html

--with-zlib=DIR                   # 指定zlib源码位置,编译Nginx时会进入该目录编译
--with-zlib-opt=OPTIONS           # zlib源码编译选项,一般没有
--with-zlib-asm=CPU               # 编译zlib时针对特定CPU型号进行优化,有:pentium, pentiumpro

--with-libatomic                  # 强制使用libatomic库,atomic库是CPU架构独立的一种原子操作的实现
--with-libatomic=DIR              # 指定libatomic库源码位置,编译Nginx时会进入该目录编译

--with-openssl=DIR                # 指定OpenSSL源码位置,编译Nginx是会进入该目录编译
--with-openssl-opt=OPTIONS        # OpenSSL编译选项,指定CPU架构,可以在OpenSSL源码目录中执行./Configure --help得到,常用的有针对Linux系统的linux-x86_64,针对MacOS的darwin64-x86_64-cc,Nginx编译的时候一般不用加。
模块配置参数以及模块的简单的介绍

Ngixn的设计是不同的功能是由不同的模块提供,除了核心模块之外,用户可以自己根据自己的使用将相关的模块编译进Nginx的可执行文件。Ngixn的模块主要有以下几个部分。

  • 事件驱动模块

    Ngixn支持的事件驱动模型有select、poll、epoll、rtsig、kqueue、/dev/poll、eventport等。

    • select:Linux和Windows都支持,接口定义也基本相同。
    • poll:Kernel 2.1.23中引入,是select库的优化实现。
    • epoll:Kernel 2.5.44中引入,是poll库的一个变种,是Linux平台上最高效的事件驱动模型。
    • rtsig:即Real-Time Signal实时信号,并不是一个严格意义上的事件驱动模型,Nginx中与其他的事件驱动模型并列使用。
    • kequeue:BSD平台上的高效事件驱动模型,是poll的一个变种,与epoll的处理方式相似,Nginx中的aio模块对应这个模型,是BSD平台上的首选。
    • /dev/poll:Unix衍生版上的高效事件驱动模型,也是这些平台上的首选。
    • eventport:Solaris 10+平台上的高效事件驱动模型。
    # 以下模块默认不安装,Linux平台默认使用epoll事件驱动模型
    --with-select_module                          # select事件驱动模型
    --with-poll_module                            # poll事件驱动模型
    --with-rtsig_module                           # rtsig事件驱动模型
    --with-aio_module                             # kqueue事件驱动模型
    
  • HTTP模块

    # 以下是默认不加入编译的HTTP模块
    --with-http_ssl_module                       # 支持SSL协议,依赖OpenSSL
    --with-http_v2_module                        # 支持HTTPv2协议
    --with-http_realip_module                    # 从客户端请求的Header信息中获取真正的客户端IP
    --with-http_addition_module                  # 返回客户端的HTTP包头部或者尾部增加内容
    --with-http_xslt_module                      # 使XML格式的数据在返回客户端前加入XSL渲染,依赖libxml2与libxslt库
    --with-http_xslt_module=dynamic
    --with-http_image_filter_module              # 将符合配置的图片实时压缩为指定大小的缩略图给客户端,支持JPG,PNG,GIF,WebP格式,依赖libgd库
    --with-http_image_filter_module=dynamic
    --with-http_geoip_module                     # 根据MaxMind GeoIP数据库对应的客户端IP从而得到地理位置信息,依赖MaxMind数据库
    --with-http_geoip_module=dynamic
    --with-http_sub_module                       # 替换Nginx返回客户端的HTTP包中指定的字符串为自己需要的字符串
    --with-http_dav_module                       # 支持Webdav协议
    --with-http_flv_module                       # 对FLV格式的文件在Header头做处理,让用户能够观看,拖动等
    --with-http_mp4_module                       # 对MP4格式的文件提供支持
    --with-http_gunzip_module                    # 对于不支持gzip编码方法的客户端,使用“Content-Encoding:gzip”解压缩响应
    --with-http_gzip_static_module               # 在gzip压缩前,先查看相同位置是否已经有gzip压缩的.gz文件,有的话直接返回。可以直接在服务端预先压缩文件,避免CPU资源占用
    --with-http_auth_request_module              # 根据子请求的结果实现客户端验证
    --with-http_random_index_module              # 客户端访问某个目录时随机返回该目录下的任意文件
    --with-http_secure_link_module               # 提供验证请求是否有效的一种机制
    --with-http_degradation_module               # 对一些特殊的系统调用做优化,目前不支持Linux
    --with-http_slice_module                     # 将请求拆分为子请求,每个请求返回一定范围的响应。该模块提供了更有效的大响应缓存
    --with-http_stub_status_module               # 提供基本的Nginx性能统计页面
    # 以下是默认加入编译的HTTP模块
    --without-http_charset_module                # 将服务器发出的HTTP响应重编码
    --without-http_gzip_module                   # 在服务器发出的HTTP响应包中,按配置文件指定的Content-Type对特定大小的HTTP响应包体进行gzip压缩
    --without-http_ssi_module                    # 在想用户返回的HTTP响应包体中加入特定内容
    --without-http_userid_module                 # 通过HTTP请求头部信息中的一些认证信息,确定请求是否合法
    --without-http_access_module                 # 根据IP地址限制访问服务器的客户端
    --without-http_auth_basic_module             # 提供最简单的用户名密码验证机制
    --without-http_autoindex_module              # 提供简单的目录浏览功能
    --without-http_geo_module                    # 关联客户端IP与定义好的变量,这样可以针对不同地区的客户端返回特定的结果
    --without-http_map_module                    # 建立Key-Value映射,处理不同的URL
    --without-http_split_clients_module          # 根据客户端的信息进行区分处理,主要用于A/B测试
    --without-http_referer_module                # 根据请求中的referer字段拒绝请求
    --without-http_rewrite_module                # HTTP请求内部重定向功能,依赖PCRE
    --without-http_proxy_module                  # HTTP反向代理
    --without-http_fastcgi_module                # FastCGI功能
    --without-http_uwsgi_module                  # uWSGI功能
    --without-http_scgi_module                   # SCGI功能
    --without-http_memcached_module              # 让Nginx直接读取上游的Memcached数据,然后通过HTTP返回给客户端
    --without-http_limit_conn_module             # 针对某个IP地址限制并发连接数
    --without-http_limit_req_module              # 针对某个IP地址限制并发请求数
    --without-http_empty_gif_module              # Nginx收到无效请求时返回内存中1*1像素的GIF图片,使无效请求不浪费服务器资源
    --without-http_browser_module                # 根据User-Agent字段识别浏览器
    --without-http_upstream_hash_module          # 提供根据hash运算实现的均衡功能
    --without-http_upstream_ip_hash_module       # Nginx与后端Server连接时根据IP的hash运算来决定连哪个Server,实现简单的负载均衡
    --without-http_upstream_least_conn_module    # 提供根据最少连接实现的负载均衡功能
    --without-http_upstream_keepalive_module     # Nginx与后端Server连接缓存
    --without-http_upstream_zone_module          # 将上游群组的运行时状态存储在共享内存区域中
      
    --without-http                               # 禁止HTTP Server功能
    --without-http-cache                         # 禁止HTTP缓存功能
    
  • 邮件代理模块

    --with-mail                                   # 使用支持POP3/IMAP4/SMTP协议的邮件代理模块
    --with-mail=dynamic
    --with-mail_ssl_module                        # 为邮件代理模块提供SSL协议支持,依赖OpenSSL库
    # 以下是启用mail模块默认安装的功能
    --without-mail_pop3_module                    # POP3协议
    --without-mail_imap_module                    # IMAP协议
    --without-mail_smtp_module                    # SMTP协议
    
  • TCP/UDP代理以及负载均衡模块

    --with-stream                                # 使用通用的TCP/UDP代理和负载平衡功能
    --with-stream=dynamic
    --with-stream_ssl_module                     # 为steam模块提供SSL协议支持,依赖OpenSSL库
    --with-stream_realip_module                  # 将客户端地址更改为Proxy协议header中发送的地址
    --with-stream_geoip_module                   # 根据MaxMind GeoIP数据库对应的客户端IP从而得到地理位置信息,依赖MaxMind数据库
    --with-stream_geoip_module=dynamic
    --with-stream_ssl_preread_module             # 允许不终止SSL/TLS情况下从ClientHello消息中提取信息
    # 以下是启用stream模块默认安装的功能
    --without-stream_limit_conn_module           # 限制客户端的连接数
    --without-stream_access_module               # 限制客户端的请求数
    --without-stream_geo_module                  # 关联客户端IP与定义好的变量,这样可以针对不同地区的客户端返回特定的结果
    --without-stream_map_module                  # 建立Key-Value映射,处理不同的URL
    --without-stream_split_clients_module        # 根据客户端的信息进行区分处理,主要用于A/B测试
    --without-stream_return_module               # 发送指定值给客户端然后关闭连接
    --without-stream_upstream_hash_module        # 提供根据hash运算实现的均衡功能
    --without-stream_upstream_least_conn_module  # 提供根据最少连接实现的负载均衡功能
    --without-stream_upstream_zone_module        # 将上游群组的运行时状态存储在共享内存区域中
    
其他配置参数
--user=USER                                # 指定Nginx Worker进程运行时所属用户,最好不要设置为root,否则会导致Master进程无法管理Worker进程
--group=GROUP                              # 指定Nginx Worker进程运行时所属用户组
--with-threads                             # 启用线程池
--with-file-aio                            # 启用文件的异步I/O功能处理磁盘文件,针对Linux与FreeBSD平台
--with-google_perftools_module             # 使用谷歌提供的性能测试工具来测试Nginx Worker进程,针对Nginx开发者
--with-cpp_test_module                     # C++测试工具
--add-module=PATH                          # 添加第三方模块
--add-dynamic-module=PATH
--with-compat                              # 启用动态模块兼容
--with-debug                               # 启用Nginx调试功能,对定位问题非常有帮助

生成中间文件

接下来就可以执行configure文件了,按照上面的介绍配置好参数:

./configure \
  --with-pcre=../pcre-8.40 \
  --with-zlib=../zlib-1.2.11 \
  --with-openssl=../openssl-1.0.2f \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_realip_module \
  --with-http_addition_module \
  --with-http_sub_module \
  --with-http_gunzip_module \
  --with-http_gzip_static_module \
  --with-http_auth_request_module \
  --with-http_random_index_module \
  --with-http_secure_link_module \
  --with-http_degradation_module \
  --with-http_slice_module \
  --with-http_stub_status_module \
  --with-mail \
  --with-mail_ssl_module \
  --with-stream \
  --with-stream_ssl_module \
  --with-stream_realip_module \
  --with-threads \
  --with-file-aio \
  --with-debug

然后提示一下算是配置通过:

...
Configuration summary
  + using threads
  + using PCRE library: ../pcre-8.40
  + using OpenSSL library: ../openssl-1.0.2f
  + using zlib library: ../zlib-1.2.11

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

同时在./objs目录中生成了中间文件:

Makefile                # 用于编译Nginx源码的组织文件
autoconf.err            # 保存configure执行过程中产生的信息
ngx_auto_config.h       # 保存一些宏
ngx_auto_headers.h      # 保存一些宏
ngx_modules.c           # 定义了Nginx需要编译的模块,非常关键
src/                    # 用户存放编译C时的产生的中间文件,暂时只有文件夹,没有内容

其中ngx_modules.c这个文件中的ngx_modules十一个非常关键的数组,它指明了每个模块在 N g i n x中的优先级 ,当一个请求同时符合多个模块的处理规则时 ,将按照它们在数组中的顺序选择最靠前的模块优先处理 。对于HTTP过滤模块则是相反的 ,因为HTTP框架在初始化时 ,会在数组中将过滤模块按先后顺序向过滤链表中添加 ,但每次都是添加到链表的表头 ,因此 ,数组中越是靠后的模块反而会首先处理HTTP响应。

编译安装

执行make进行编译,编译完成之后可以看到在./objs目录下生成了Nginx的二进制文件。如果要升级旧的Nginx可以直接将这个生成的Nginx二进制文件拿去升级,如果要安装的话,执行sudo make install安装,生成的二进制文件会被复制到默认的位置:/usr/local/nginx

$ tree /usr/local/nginx
/usr/local/nginx
|-- conf
|   |-- fastcgi.conf
|   |-- fastcgi.conf.default
|   |-- fastcgi_params
|   |-- fastcgi_params.default
|   |-- koi-utf
|   |-- koi-win
|   |-- mime.types
|   |-- mime.types.default
|   |-- nginx.conf
|   |-- nginx.conf.default
|   |-- scgi_params
|   |-- scgi_params.default
|   |-- uwsgi_params
|   |-- uwsgi_params.default
|   `-- win-utf
|-- html
|   |-- 50x.html
|   `-- index.html
|-- logs
`-- sbin
    `-- nginx

参考资料