登入帳戶  | 訂單查詢  | 購物車/收銀台(0) | 在線留言板  | 付款方式  | 聯絡我們  | 運費計算  | 幫助中心 |  加入書簽
會員登入   新用戶註冊
HOME新書上架暢銷書架好書推介特價區會員書架精選月讀2023年度TOP分類閱讀雜誌 香港/國際用戶
最新/最熱/最齊全的簡體書網 品種:超過100萬種書,正品正价,放心網購,悭钱省心 送貨:速遞 / 物流,時效:出貨後2-4日

2024年10月出版新書

2024年09月出版新書

2024年08月出版新書

2024年07月出版新書

2024年06月出版新書

2024年05月出版新書

2024年04月出版新書

2024年03月出版新書

2024年02月出版新書

2024年01月出版新書

2023年12月出版新書

2023年11月出版新書

2023年10月出版新書

2023年09月出版新書

『簡體書』《深入理解Nginx:模块开发与架构解析》(阿里巴巴资深Nginx专家撰写,透彻解析Nginx架构,详解Nginx模块开发方法和技巧)

書城自編碼: 2042421
分類: 簡體書→大陸圖書→計算機/網絡網絡與數據通信
作者: 陶辉
國際書號(ISBN): 9787111414780
出版社: 机械工业出版社
出版日期: 2013-04-01
版次: 1 印次: 1
頁數/字數: 565/
書度/開本: 16开 釘裝: 平装

售價:NT$ 828

我要買

share:

** 我創建的書架 **
未登入.



新書推薦:
石油帝国的兴衰:英国的工业化与去工业化
《 石油帝国的兴衰:英国的工业化与去工业化 》

售價:NT$ 445.0
古典的回響:溪客舊廬藏明清文人繪畫
《 古典的回響:溪客舊廬藏明清文人繪畫 》

售價:NT$ 1990.0
根源、制度和秩序:从老子到黄老学(王中江著作系列)
《 根源、制度和秩序:从老子到黄老学(王中江著作系列) 》

售價:NT$ 550.0
索恩丛书·北宋政治与保守主义:司马光的从政与思想(1019~1086)
《 索恩丛书·北宋政治与保守主义:司马光的从政与思想(1019~1086) 》

售價:NT$ 345.0
掌故家的心事
《 掌故家的心事 》

售價:NT$ 390.0
农为邦本——农业历史与传统中国
《 农为邦本——农业历史与传统中国 》

售價:NT$ 340.0
小麦文明:“黄金石油”争夺战
《 小麦文明:“黄金石油”争夺战 》

售價:NT$ 445.0
悬壶杂记全集:老中医多年临证经验总结(套装3册) 中医医案诊疗思路和处方药应用
《 悬壶杂记全集:老中医多年临证经验总结(套装3册) 中医医案诊疗思路和处方药应用 》

售價:NT$ 614.0

建議一齊購買:

+

NT$ 711
《 大型分布式网站架构设计与实践 》
+

NT$ 549
《 Nginx高性能Web服务器详解 》
+

NT$ 549
《 大规模分布式存储系统:原理解析与架构实战(阿里巴巴高级技术专家撰写,系统讲解构建大规模存储系统的核心技术和原理,详细分析Google、Amazon、Microsoft和阿里巴巴的大规模分布式存储系统的原理。) 》
+

NT$ 363
《 Redis入门指南 》
編輯推薦:
阿里巴巴资深Nginx专家撰写,透彻解析Nginx架构,详解Nginx模块开发方法和技巧。
內容簡介:
《深入理解Nginx:模块开发与架构解析》是阿里巴巴资深Nginx技术专家呕心沥血之作,是作者多年的经验结晶,也是目前市场上唯一一本通过还原Nginx设计思想,剖析Nginx架构来帮助读者快速高效开发HTTP模块的图书。
《深入理解Nginx:模块开发与架构解析》首先通过介绍官方Nginx的基本用法和配置规则,帮助读者了解一般Nginx模块的用法,然后重点介绍如何开发HTTP模块(含HTTP过滤模块)来得到定制的Nginx,其中包括开发一个功能复杂的模块所需要了解的各种知识,如Nginx的基础数据结构、配置项的解析、记录日志的工具以及upstream、subrequest的使用方法等。在此基础上,综合Nginx框架代码分析Nginx的架构,介绍其设计理念和技巧,进一步帮助读者自由、有效地开发出功能丰富、性能一流的Nginx模块。
關於作者:
陶辉,思科后台工程师,从事服务端开发近十年,擅长Linux分布式架构下的海量数据处理,擅长CC++开发的高性能高吞吐量网络服务,曾任思科DMS后台架构设计工作,曾在腾讯QQ空间后台个人信息中心、个人档、漂流瓶、空间日志、花藤、好友买卖等项目中担任服务器设计与开发工作,曾在华为中央软件部综合网管平台担任北向接口设计开发工作。拥有丰富的Linux高性能服务器开发经验,丰富的云存储系统开发经验,目前关注云文档管理系统和Nginx的再开发。
目錄
前 言
第一部分 Nginx能帮我们做什么
第1章 研究Nginx前的准备工作
1.1 Nginx是什么
1.2 为什么选择Nginx
1.3 准备工作
1.3.1 Linux操作系统
1.3.2 使用Nginx的必备软件
1.3.3 磁盘目录
1.3.4 Linux内核参数的优化
1.3.5 获取Nginx源码
1.4 编译安装Nginx
1.5 configure详解
1.5.1 configure的命令参数
1.5.2 configure执行流程
1.5.3 configure生成的文件
1.6 Nginx的命令行控制
1.7 小结
第2章 Nginx的配置
2.1 运行中的Nginx进程间的关系
2.2 Nginx配置的通用语法
2.2.1 块配置项
2.2.2 配置项的语法格式
2.2.3 配置项的注释
2.2.4 配置项的单位
2.2.5 在配置中使用变量
2.3 Nginx服务的基本配置
2.3.1 用于调试进程和定位问题的配置项
2.3.2 正常运行的配置项
2.3.3 优化性能的配置项
2.3.4 事件类配置项
2.4 用HTTP核心模块配置一个静态Web服务器
2.4.1 虚拟主机与请求的分发
2.4.2 文件路径的定义
2.4.3 内存及磁盘资源的分配
2.4.4 网络连接的设置
2.4.5 MIME类型的设置
2.4.6 对客户端请求的限制
2.4.7 文件操作的优化
2.4.8 对客户端请求的特殊处理
2.4.9 ngx_http_core_module模块提供的变量
2.5 用HTTP proxy module配置一个反向代理服务器
2.5.1 负载均衡的基本配置
2.5.2 反向代理的基本配置
2.6 小结
第二部分 如何编写HTTP模块
第3章 开发一个简单的HTTP模块
3.1 如何调用HTTP模块
3.2 准备工作
3.2.1 整型的封装
3.2.2 ngx_str_t数据结构
3.2.3 ngx_list_t数据结构
3.2.4 ngx_table_elt_t数据结构
3.2.5 ngx_buf_t数据结构
3.2.6 ngx_chain_t数据结构
3.3 如何将自己的HTTP模块编译进Nginx
3.3.1 config文件的写法
3.3.2 利用configure脚本将定制的模块加入到Nginx中
3.3.3 直接修改Makefile文件
3.4 HTTP模块的数据结构
3.5 定义自己的HTTP模块
3.6 处理用户请求
3.6.1 处理方法的返回值
3.6.2 获取URI和参数
3.6.3 获取HTTP头部
3.6.4 获取HTTP包体
3.7 发送响应
3.7.1 发送HTTP头部
3.7.2 将内存中的字符串作为包体发送
3.7.3 经典的“Hello World”示例
3.8 将磁盘文件作为包体发送
3.8.1 如何发送磁盘中的文件
3.8.2 清理文件句柄
3.8.3 支持用户多线程下载和断点续传
3.9 用C++语言编写HTTP模块
3.9.1 编译方式的修改
3.9.2 程序中的符号转换
3.10 小结
第4章 配置、error日志和请求上下文
4.1 http配置项的使用场景
4.2 怎样使用http配置
4.2.1 分配用于保存配置参数的数据结构
4.2.2 设定配置项的解析方式
4.2.3 使用14种预设方法解析配置项
4.2.4 自定义配置项处理方法
4.2.5 合并配置项
4.3 HTTP配置模型
4.3.1 解析HTTP配置的流程
4.3.2 HTTP配置模型的内存布局
4.3.3 如何合并配置项
4.3.4 预设配置项处理方法的工作原理
4.4 error日志的用法
4.5 请求的上下文
4.5.1 上下文与全异步Web服务器的关系
4.5.2 如何使用HTTP上下文
4.5.3 HTTP框架如何维护上下文结构
4.6 小结
第5章 访问第三方服务
5.1 upstream的使用方式
5.1.1 ngx_http_upstream_t结构体
5.1.2 设置upstream的限制性参数
5.1.3 设置需要访问的第三方服务器地址
5.1.4 设置回调方法
5.1.5 如何启动upstream机制
5.2 回调方法的执行场景
5.2.1 create_request回调方法
5.2.2 reinit_request回调方法
5.2.3 finalize_request回调方法
5.2.4 process_header回调方法
5.2.5 rewrite_redirect回调方法
5.2.6 input_filter_init与input_filter回调方法
5.3 使用upstream的示例
5.3.1 upstream的各种配置参数
5.3.2 请求上下文
5.3.3 在create_request方法中构造请求
5.3.4 在process_header方法中解析包头
5.3.5 在finalize_request方法中释放资源
5.3.6 在ngx_http_mytest_handler方法中启动upstream
5.4 subrequest的使用方式
5.4.1 配置子请求的处理方式
5.4.2 实现子请求处理完毕时的回调方法
5.4.3 处理父请求被重新激活后的回调方法
5.4.4 启动subrequest子请求
5.5 subrequest执行过程中的主要场景
5.5.1 如何启动subrequest
5.5.2 如何转发多个子请求的响应包体
5.5.3 子请求如何激活父请求
5.6 subrequest使用的例子
5.6.1 配置文件中子请求的设置
5.6.2 请求上下文
5.6.3 子请求结束时的处理方法
5.6.4 父请求的回调方法
5.6.5 启动subrequest
5.7 小结
第6章 开发一个简单的HTTP过滤模块
6.1 过滤模块的意义
6.2 过滤模块的调用顺序
6.2.1 过滤链表是如何构成的
6.2.2 过滤链表的顺序
6.2.3 官方默认HTTP过滤模块的功能简介
6.3 HTTP过滤模块的开发步骤
6.4 HTTP过滤模块的简单例子
6.4.1 如何编写config文件
6.4.2 配置项和上下文
6.4.3 定义HTTP过滤模块
6.4.4 初始化HTTP过滤模块
6.4.5 处理请求中的HTTP头部
6.4.6 处理请求中的HTTP包体
6.5 小结
第7章 Nginx提供的高级数据结构
7.1 Nginx提供的高级数据结构概述
7.2 ngx_queue_t双向链表
7.2.1 为什么设计ngx_queue_t双向链表
7.2.2 双向链表的使用方法
7.2.3 使用双向链表排序的例子
7.2.4 双向链表是如何实现的
7.3 ngx_array_t动态数组
7.3.1 为什么设计ngx_array_t动态数组
7.3.2 动态数组的使用方法
7.3.3  使用动态数组的例子
7.3.4 动态数组的扩容方式
7.4 ngx_list_t单向链表
7.5 ngx_rbtree_t红黑树
7.5.1 为什么设计ngx_rbtree_t红黑树
7.5.2 红黑树的特性
7.5.3 红黑树的使用方法
7.5.4 使用红黑树的简单例子
7.5.5 如何自定义添加成员方法
7.6 ngx_radix_tree_t基数树
7.6.1 ngx_radix_tree_t基数树的原理
7.6.2 基数树的使用方法
7.6.3 使用基数树的例子
7.7 支持通配符的散列表
7.7.1 ngx_hash_t基本散列表
7.7.2 支持通配符的散列表
7.7.3 带通配符散列表的使用例子
7.8 小结
第三部分 深入Nginx
第8章 Nginx基础架构
8.1 Web服务器设计中的关键约束
8.2 Nginx的架构设计
8.2.1 优秀的模块化设计
8.2.2 事件驱动架构
8.2.3 请求的多阶段异步处理
8.2.4 管理进程、多工作进程设计
8.2.5 平台无关的代码实现
8.2.6 内存池的设计
8.2.7 使用统一管道过滤器模式的HTTP过滤模块
8.2.8 其他一些用户模块
8.3 Nginx框架中的核心结构体ngx_cycle_t
8.3.1 ngx_listening_t结构体
8.3.2 ngx_cycle_t结构体
8.3.3 ngx_cycle_t支持的方法
8.4 Nginx启动时框架的处理流程
8.5 worker进程是如何工作的
8.6 master进程是如何工作的
8.7 小结
第9章 事件模块
9.1 事件处理框架概述
9.2 Nginx事件的定义
9.3 Nginx连接的定义
9.3.1 被动连接
9.3.2 主动连接
9.3.3 ngx_connection_t连接池
9.4 ngx_events_module核心模块
9.4.1 如何管理所有事件模块的配置项
9.4.2 管理事件模块
9.5 ngx_event_core_module事件模块
9.6 epoll事件驱动模块
9.6.1 epoll的原理和用法
9.6.2 如何使用epoll
9.6.3 ngx_epoll_module模块的实现
9.7 定时器事件
9.7.1 缓存时间的管理
9.7.2 缓存时间的精度
9.7.3 定时器的实现
9.8 事件驱动框架的处理流程
9.8.1 如何建立新连接
9.8.2 如何解决“惊群”问题
9.8.3 如何实现负载均衡
9.8.4 post事件队列
9.8.5 ngx_process_events_and_timers流程
9.9 文件的异步IO
9.9.1 Linux内核提供的文件异步IO
9.9.2 ngx_epoll_module模块中实现的针对文件的异步IO
9.10 小结
第10章 HTTP框架的初始化
10.1 HTTP框架概述
10.2 管理HTTP模块的配置项
10.2.1 管理main级别下的配置项
10.2.2 管理server级别下的配置项
10.2.3 管理location级别下的配置项
10.2.4 不同级别配置项的合并
10.3 监听端口的管理
10.4 server的快速检索
10.5 location的快速检索
10.6 HTTP请求的11个处理阶段
10.6.1 HTTP处理阶段的普适规则
10.6.2 NGX_HTTP_POST_READ_PHASE阶段
10.6.3 NGX_HTTP_SERVER_REWRITE_PHASE阶段
10.6.4 NGX_HTTP_FIND_CONFIG_PHASE阶段
10.6.5 NGX_HTTP_REWRITE_PHASE阶段
10.6.6 NGX_HTTP_POST_REWRITE_PHASE阶段
10.6.7 NGX_HTTP_PREACCESS_PHASE阶段
10.6.8 NGX_HTTP_ACCESS_PHASE阶段
10.6.9 NGX_HTTP_POST_ACCESS_PHASE阶段
10.6.10 NGX_HTTP_TRY_FILES_PHASE阶段
10.6.11 NGX_HTTP_CONTENT_PHASE阶段
10.6.12 NGX_HTTP_LOG_PHASE阶段
10.7 HTTP框架的初始化流程
10.8 小结
第11章 HTTP框架的执行流程
11.1 HTTP框架执行流程概述
11.2 新连接建立时的行为
11.3 第一次可读事件的处理
11.4 接收HTTP请求行
11.5 接收HTTP头部
11.6 处理HTTP请求
11.6.1 ngx_http_core_generic_phase
11.6.2 ngx_http_core_rewrite_phase
11.6.3 ngx_http_core_access_phase
11.6.4 ngx_http_core_content_phase
11.7 subrequest与post请求
11.8 处理HTTP包体
11.8.1 接收包体
11.8.2 放弃接收包体
11.9 发送HTTP响应
11.9.1 ngx_http_send_header
11.9.2 ngx_http_output_filter
11.9.3 ngx_http_writer
11.10 结束HTTP请求
11.10.1 ngx_http_close_connection
11.10.2 ngx_http_free_request
11.10.3 ngx_http_close_request
11.10.4 ngx_http_finalize_connection
11.10.5 ngx_http_terminate_request
11.10.6 ngx_http_finalize_request
11.11 小结
第12章 upstream机制的设计与实现
12.1 upstream机制概述
12.1.1 设计目的
12.1.2 ngx_http_upstream_t数据结构的意义
12.1.3 ngx_http_upstream_conf_t配置结构体
12.2 启动upstream
12.3 与上游服务器建立连接
12.4 发送请求到上游服务器
12.5 接收上游服务器的响应头部
12.5.1 应用层协议的两段划分方式
12.5.2 处理包体的3种方式
12.5.3 接收响应头部的流程
12.6 不转发响应时的处理流程
12.6.1 input_filter方法的设计
12.6.2 默认的input_filter方法
12.6.3 接收包体的流程
12.7 以下游网速优先来转发响应
12.7.1 转发响应的包头
12.7.2 转发响应的包体
12.8 以上游网速优先来转发响应
12.8.1 ngx_event_pipe_t结构体的意义
12.8.2 转发响应的包头
12.8.3 转发响应的包体
12.8.4 ngx_event_pipe_read_upstream方法
12.8.5 ngx_event_pipe_write_to_downstream方法
12.9 结束upstream请求
12.10 小结
第13章 邮件代理模块
13.1 邮件代理服务器的功能
13.2 邮件模块的处理框架
13.2.1 一个请求的8个独立处理阶段
13.2.2 邮件类模块的定义
13.2.3 邮件框架的初始化
13.3 初始化请求
13.3.1 描述邮件请求的ngx_mail_session_t结构体
13.3.2 初始化邮件请求的流程
13.4 接收并解析客户端请求
13.5 邮件认证
13.5.1 ngx_mail_auth_http_ctx_t结构体
13.5.2 与认证服务器建立连接
13.5.3 发送请求到认证服务器
13.5.4 接收并解析响应
13.6 与上游邮件服务器间的认证交互
13.6.1 ngx_mail_proxy_ctx_t结构体
13.6.2 向上游邮件服务器发起连接
13.6.3 与邮件服务器认证交互的过程
13.7 透传上游邮件服务器与客户端间的流
13.8 小结
第14章 进程间的通信机制
14.1 概述
14.2 共享内存
14.3 原子操作
14.3.1 不支持原子库下的原子操作
14.3.2 x86架构下的原子操作
14.3.3 自旋锁
14.4 Nginx频道
14.5 信号
14.6 信号量
14.7 文件锁
14.8 互斥锁
14.8.1 文件锁实现的ngx_shmtx_t锁
14.8.2 原子变量实现的ngx_shmtx_t锁
14.9 小结
內容試閱
第一部分
Nginx能帮我们做什么
本部分内容
第1章 研究Nginx前的准备工作
第2章 Nginx的配置

第1章 研究Nginx前的准备工作
2012年,Nginx荣获年度云计算开发奖(2012 Cloud Award for Developer of the
Year),并成长为世界第二大Web服务器。全世界流量最高的前1000名网站中,超过25%都使用Nginx来处理海量的互联网请求。Nginx已经成为业界高性能Web服务器的代名词。
那么,什么是Nginx?它有哪些特点?我们选择Nginx的理由是什么?如何编译安装Nginx?这种安装方式背后隐藏的又是什么样的思想呢?本章将会回答上述问题。
1.1 Nginx是什么
人们在了解新事物时,往往习惯通过类比来帮助自己理解事物的概貌。那么,我们在学习Nginx时也采用同样的方式,先来看看Nginx的竞争对手—Apache、Lighttpd、Tomcat、Jetty、IIS,它们都是Web服务器,或者叫做WWW(World
Wide Web)服务器,相应地也都具备Web服务器的基本功能:基于REST架构风格,以统一资源描述符(Uniform
Resource Identifier,URI)或者统一资源定位符(Uniform Resource
Locator,URL)作为沟通依据,通过HTTP为浏览器等客户端程序提供各种网络服务。然而,由于这些Web服务器在设计阶段就受到许多局限,例如当时的互联网用户规模、网络带宽、产品特点等局限,并且各自的定位与发展方向都不尽相同,使得每一款Web服务器的特点与应用场合都很鲜明。
Tomcat和Jetty面向Java语言,先天就是重量级的Web服务器,它的性能与Nginx没有可比性,这里略过。
IIS只能在Windows操作系统上运行。Windows作为服务器在稳定性与其他一些性能上都不如类UNIX操作系统,因此,在需要高性能Web服务器的场合下,IIS可能会被“冷落”。
Apache的发展时期很长,而且是目前毫无争议的世界第一大Web服务器,图1-1中是12年来(2010~2012年)世界Web服务器的使用排名情况。
从图1-1中可以看出,Apache目前处于领先地位。
Apache有许多优点,如稳定、开源、跨平台等,但它出现的时间太长了,在它兴起的年代,互联网的产业规模远远比不上今天,所以它被设计成了一个重量级的、不支持高并发的Web服务器。在Apache服务器上,如果有数以万计的并发HTTP请求同时访问,就会导致服务器上消耗大量内存,操作系统内核对成百上千的Apache进程做进程间切换也会消耗大量CPU资源,并导致HTTP请求的平均响应速度降低,这些都决定了Apache不可能成为高性能Web服务器,这也促使了Lighttpd和Nginx的出现。观察图1-1中Nginx成长的曲线,体会一下Nginx抢占市场时的“咄咄逼人”吧。

图1-1 Netcraft对于644 275
754个站点31.4M个域名Web服务器使用情况的调查结果(2012年3月)
Lighttpd和Nginx一样,都是轻量级、高性能的Web服务器,欧美的业界开发者比较钟爱Lighttpd,而国内的公司更青睐Nginx,Lighttpd使用得比较少。
在了解了Nginx的竞争对手之后,相信大家对Nginx也有了直观感受,下面让我们来正式地认识一下Nginx吧。
提示 Nginx发音:engine [''nd3In] X。
来自俄罗斯的Igor Sysoev在为Rambler
Media(http:www.rambler.ru)工作期间,使用C语言开发了Nginx。Nginx作为Web服务器,一直为俄罗斯著名的门户网站Rambler
Media提供着出色、稳定的服务。
Igor Sysoev将Nginx的代码开源,并且赋予其最自由的2-clause BSD-like
license许可证。由于Nginx使用基于事件驱动的架构能够并发处理百万级别的TCP连接,高度模块化的设计和自由的许可证使得扩展Nginx功能的第三方模块层出不穷,而且优秀的设计带来了极佳的稳定性,因此其作为Web服务器被广泛应用到大流量的网站上,包括腾讯、新浪、网易、淘宝等访问量巨大的网站。
2012年2月和3月Netcraft对Web服务器的调查如表1-1所示,可以看出,Nginx的市场份额越来越大。
表1-1 Netcraft对于Web服务器市场占有率前4位软件的调查(2012年2月和3月)
Web服务器 2012年2月
市场占有率 2012年3月
市场占有率 占有率变化
Apache 106 664 061
57.45% 108 035 584
57.46% 0.01
Nginx 23 590 737
12.71% 24 011 199
12.77% 0.06
Microsoft IIS 22 363 730
12.05% 22 537 872
11.99% –0.06
Google Web Server 14 316 485
7.71% 14 438 358
7.68% –0.03

Nginx是一个跨平台的Web服务器,可运行在Linux、FreeBSD、Solaris、AIX、Mac
OS、Windows等操作系统上,并且它还可以使用当前操作系统特有的一些高效API来提高自己的性能。
例如,对于高效处理大规模并发连接,它支持Linux上的epoll(epoll是Linux上处理大并发网络连接的利器,9.6.1节中将会详细说明epoll的工作原理)、Solaris上的event
ports和FreeBSD上的kqueue等。
又如,对于Linux,Nginx支持其独有的
sendfile系统调用,这个系统调用可以高效地把硬盘中的数据发送到网络上(不需要先把硬盘数据复制到用户态内存上再发送),这极大地减少了内核态与用户态数据间的复制动作。
种种迹象都表明,Nginx以性能为王。
2011年7月,Nginx正式成立公司,由Igor Sysoev担任CTO,立足于提供商业级的Web服务器。
1.2 为什么选择Nginx
为什么选择Nginx?因为它具有以下特点:
(1)更快
这表现在两个方面:一方面,在正常情况下,单次请求会得到更快的响应;另一方面,在高峰期(如有数以万计的并发请求),Nginx可以比其他Web服务器更快地响应请求。
实际上,本书第三部分中大量的篇幅都是在说明Nginx是如何做到这两点的。
(2)高扩展性
Nginx的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。因此,当对某一个模块修复Bug或进行升级时,可以专注于模块自身,无须在意其他。而且在HTTP模块中,还设计了HTTP过滤器模块:一个正常的HTTP模块在处理完请求后,会有一串HTTP过滤器模块对请求的结果进行再处理。这样,当我们开发一个新的HTTP模块时,不但可以使用诸如HTTP核心模块、events模块、log模块等不同层次或者不同类型的模块,还可以原封不动地复用大量已有的HTTP过滤器模块。这种低耦合度的优秀设计,造就了Nginx庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样容易使用。
Nginx的模块都是嵌入到二进制文件中执行的,无论官方发布的模块还是第三方模块都是如此。这使得第三方模块一样具备极其优秀的性能,充分利用Nginx的高并发特性,因此,许多高流量的网站都倾向于开发符合自己业务特性的定制模块。
(3)高可靠性
高可靠性是我们选择Nginx的最基本条件,因为Nginx的可靠性是大家有目共睹的,很多家高流量网站都在核心服务器上大规模使用Nginx。Nginx的高可靠性来自于其核心框架代码的优秀设计、模块设计的简单性;另外,官方提供的常用模块都非常稳定,每个worker进程相对独立,master进程在1个worker进程出错时可以快速“拉起”新的worker子进程提供服务。
(4)低内存消耗
一般情况下,10 000个非活跃的HTTP
Keep-Alive连接在Nginx中仅消耗2.5MB的内存,这是Nginx支持高并发连接的基础。
从第3章开始,我们会接触到Nginx在内存中为了维护一个HTTP连接所分配的对象,届时将会看到,实际上Nginx一直在为用户考虑(尤其是在高并发时)如何使得内存的消耗更少。
(5)单机支持10万以上的并发连接
这是一个非常重要的特性!随着互联网的迅猛发展和互联网用户数量的成倍增长,各大公司、网站都需要应付海量并发请求,一个能够在峰值期顶住10万以上并发请求的Server,无疑会得到大家的青睐。理论上,Nginx支持的并发连接上限取决于内存,10万远未封顶。当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的,本书第8~11章将会详细说明如何实现这个特点。
(6)热部署
master管理进程与worker工作进程的分离设计,使得Nginx能够提供热部署功能,即可以在7×24小时不间断服务的前提下,升级Nginx的可执行文件。当然,它也支持不停止服务就更新配置项、更换日志文件等功能。
(7)最自由的BSD许可协议
这是Nginx可以快速发展的强大动力。BSD许可协议不只是允许用户免费使用Nginx,它还允许用户在自己的项目中直接使用或修改Nginx源码,然后发布。这吸引了无数开发者继续为Nginx贡献自己的智慧。
以上7个特点当然不是Nginx的全部,拥有无数个官方功能模块、第三方功能模块使得Nginx能够满足绝大部分应用场景,这些功能模块间可以叠加以实现更加强大、复杂的功能,有些模块还支持Nginx与Perl、Lua等脚本语言集成工作,大大提高了开发效率。这些特点促使用户在寻找一个Web服务器时更多考虑Nginx。
当然,选择Nginx的核心理由还是它能在支持高并发请求的同时保持高效的服务。
如果Web服务器的业务访问量巨大,就需要保证在数以百万计的请求同时访问服务时,用户可以获得良好的体验,不会出现并发访问量达到一个数字后,新的用户无法获取服务,或者虽然成功地建立起了TCP连接,但大部分请求却得不到响应的情况。
通常,高峰期服务器的访问量可能是正常情况下的许多倍,若有热点事件的发生,可能会导致正常情况下非常顺畅的服务器直接“挂死”。然而,如果在部署服务器时,就预先针对这种情况进行扩容,又会使得正常情况下所有服务器的负载过低,这会造成大量的资源浪费。因此,我们会希望在这之间取得平衡,也就是说,在低并发压力下,用户可以获得高速体验,而在高并发压力下,更多的用户都能接入,可能访问速度会下降,但这只应受制于带宽和处理器的速度,而不应该是服务器设计导致的软件瓶颈。
事实上,由于中国互联网用户群体的数量巨大,致使对Web服务器的设计往往要比欧美公司更加困难。例如,对于全球性的一些网站而言,欧美用户分布在两个半球,欧洲用户活跃时,美洲用户通常在休息,反之亦然。而国内巨大的用户群体则对业界的程序员提出更高的挑战,早上9点和晚上20点到24点这些时间段的并发请求压力是非常巨大的。尤其节假日、寒暑假到来之时,更会对服务器提出极高的要求。
另外,国内业务上的特性,也会引导用户在同一时间大并发地访问服务器。例如,许多SNS网页游戏会在固定的时间点刷新游戏资源或者允许“偷菜”等好友互动操作。这些会导致服务器处理高并发请求的压力增大。
上述情形都对我们的互联网服务在大并发压力下是否还能够给予用户良好的体验提出了更高的要求。若要提供更好的服务,那么可以从多方面入手,例如,修改业务特性、引导用户从高峰期分流或者把服务分层分级、对于不同并发压力给用户提供不同级别的服务等。但最根本的是,Web服务器要能支持大并发压力下的正常服务,这才是关键。
快速增长的互联网用户群以及业内所有互联网服务提供商越来越好的用户体验,都促使我们在大流量服务中用Nginx取代其他Web服务器。Nginx先天的事件驱动型设计、全异步的网络IO处理机制、极少的进程间切换以及许多优化设计,都使得Nginx天生善于处理高并发压力下的互联网请求,同时Nginx降低了资源消耗,可以把服务器硬件资源“压榨”到极致。
1.3 准备工作
由于Linux具有免费、使用广泛、商业支持越来越完善等特点,本书将主要针对Linux上运行的Nginx来进行介绍。需要说明的是,本书不是使用手册,而是介绍Nginx作为Web服务器的设计思想,以及如何更有效地使用Nginx达成目的,而这些内容在各操作系统上基本是相通的(除了第9章关于事件驱动方式以及第14章的进程间同步方式在类UNIX操作系统上略有不同以外)。
1.3.1 Linux操作系统
首先我们需要一个内核为Linux 2.6及以上版本的操作系统,因为Linux
2.6及以上内核才支持epoll,而在Linux上使用select或poll来解决事件的多路复用,是无法解决高并发压力问题的。
我们可以使用uname -a命令来查询Linux内核版本,例如:
:wehf2wng001:root uname -a
Linux wehf2wng001 2.6.18-128.el5 #1 SMP Wed Jan 21 10:41:14 EST
2009 x86_64 x86_64 x86_64 GNULinux
执行结果表明内核版本是2.6.18,符合我们的要求。
1.3.2 使用Nginx的必备软件
如果要使用Nginx的常用功能,那么首先需要确保该操作系统上至少安装了如下软件。
(1)GCC编译器
GCC(GNU Compiler
Collection)可用来编译C语言程序。Nginx不会直接提供二进制可执行程序(1.2.x版本中已经开始提供某些操作系统上的二进制安装包了,不过,本书探讨如何开发Nginx模块是必须通过直接编译源代码进行的),这有许多原因,本章后面会详述。我们可以使用最简单的yum方式安装GCC,例如:
yum install -y gcc
GCC是必需的编译工具。在第3章会提到如何使用C++来编写Nginx
HTTP模块,这时就需要用到G++编译器了。G++编译器也可以用yum安装,例如:
yum install -y gcc-c++
Linux上有许多软件安装方式,yum只是其中比较方便的一种,其他方式这里不再赘述。
(2)PCRE库
PCRE(Perl Compatible Regular Expressions,Perl兼容正则表达式)是由Philip
Hazel开发的函数库,目前为很多软件所使用,该库支持正则表达式。它由RegEx演化而来,实际上,Perl正则表达式也是源自于Henry
Spencer写的RegEx。
如果我们在配置文件nginx.conf里使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx,因为Nginx的HTTP模块要靠它来解析正则表达式。当然,如果你确认不会使用正则表达式,就不必安装它。其yum安装方式如下:
yum install -y pcre pcre-devel
pcre-devel是使用PCRE做二次开发时所需要的开发库,包括头文件等,这也是编译Nginx所必须使用的。
(3)zlib库
zlib库用于对HTTP包的内容做gzip格式的压缩,如果我们在nginx.conf里配置了gzip
on,并指定对于某些类型(content-type)的HTTP响应使用gzip来进行压缩以减少网络传输量,那么,在编译时就必须把zlib编译进Nginx。其yum安装方式如下:
yum install -y zlib zlib-devel
同理,zlib是直接使用的库,zlib-devel是二次开发所需要的库。
(4)OpenSSL开发库
如果我们的服务器不只是要支持HTTP,还需要在更安全的SSL协议上传输HTTP,那么就需要拥有OpenSSL了。另外,如果我们想使用MD5、SHA1等散列函数,那么也需要安装它。其yum安装方式如下:
yum install -y openssl openssl-devel
上面所列的4个库只是完成Web服务器最基本功能所必需的。
Nginx是高度自由化的Web服务器,它的功能是由许多模块来支持的。而这些模块可根据我们的使用需求来定制,如果某些模块不需要使用则完全不必理会它。同样,如果使用了某个模块,而这个模块使用了一些类似zlib或OpenSSL等的第三方库,那么就必须先安装这些软件。
1.3.3 磁盘目录
要使用Nginx,还需要在Linux文件系统上准备以下目录。
(1)Nginx源代码存放目录
该目录用于放置从官网上下载的Nginx源码文件,以及第三方或我们自己所写的模块源代码文件。
(2)Nginx编译阶段产生的中间文件存放目录
该目录用于放置在configure命令执行后所生成的源文件及目录,以及make命令执行后生成的目标文件和最终连接成功的二进制文件。默认情况下,configure命令会将该目录命名为objs,并放在Nginx源代码目录下。
(3)部署目录
该目录存放实际Nginx服务运行期间所需要的二进制文件、配置文件等。默认情况下,该目录为usrlocalnginx。
(4)日志文件存放目录
日志文件通常会比较大,当研究Nginx的底层架构时,需要打开debug级别的日志,这个级别的日志非常详细,会导致日志文件的大小增长得极快,需要预先分配一个拥有更大磁盘空间的目录。
1.3.4 Linux内核参数的优化
由于默认的Linux内核参数考虑的是最通用的场景,这明显不符合用于支持高并发访问的Web服务器的定义,所以需要修改Linux内核参数,使得Nginx可以拥有更高的性能。
在优化内核时,可以做的事情很多,不过,我们通常会根据业务特点来进行调整,当Nginx作为静态Web内容服务器、反向代理服务器或是提供图片缩略图功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使Nginx支持更多并发请求的TCP网络参数做简单说明。
首先,需要修改etcsysctl.conf来更改内核参数。例如,最常用的配置:
fs.file-max = 999999
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.ip_local_port_range = 1024 61000
net.ipv4.tcp_rmem = 4096 32768 262142
net.ipv4.tcp_wmem = 4096 32768 262142
net.core.netdev_max_backlog = 8096
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 2097152
net.core.wmem_max = 2097152
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn.backlog=1024
然后执行sysctl -p命令,使上述修改生效。
上面的参数意义解释如下:
file-max:这个参数表示进程(比如一个worker进程)可以同时打开的最大句柄数,这个参数直接限制最大并发连接数,需根据实际情况配置。
tcp_tw_reuse:这个参数设置为1,表示允许将TIME-WAIT状态的socket重新用于新的TCP连接,这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT状态的连接。
tcp_keepalive_time:这个参数表示当keepalive启用时,TCP发送keepalive消息的频度。默认是2小时,若将其设置得小一些,可以更快地清理无效的连接。
tcp_fin_timeout:这个参数表示当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间。
tcp_max_tw_buckets:这个参数表示操作系统允许TIME_WAIT套接字数量的最大值,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。该参数默认为180
000,过多的TIME_WAIT套接字会使Web服务器变慢。
tcp_max_syn_backlog:这个参数表示TCP三次握手建立阶段接收SYN请求队列的最大长度,默认为1024,将其设置得大一些可以使出现Nginx繁忙来不及accept新连接的情况时,Linux不至于丢失客户端发起的连接请求。
ip_local_port_range:这个参数定义了在UDP和TCP连接中本地(不包括连接的远端)端口的取值范围。
net.ipv4.tcp_rmem:这个参数定义了TCP接收缓存(用于TCP接收滑动窗口)的最小值、默认值、最大值。
net.ipv4.tcp_wmem:这个参数定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值。
netdev_max_backlog:当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。这个参数表示该队列的最大值。
rmem_default:这个参数表示内核套接字接收缓存区默认的大小。
wmem_default:这个参数表示内核套接字发送缓存区默认的大小。
rmem_max:这个参数表示内核套接字接收缓存区的最大大小。
wmem_max:这个参数表示内核套接字发送缓存区的最大大小。
注意 滑动窗口的大小与套接字缓存区会在一定程度上影响并发连接的数目。每个TCP连接都会为维护TCP滑动窗口而消耗内存,这个窗口会根据服务器的处理速度收缩或扩张。
参数wmem_max的设置,需要平衡物理内存的总大小、Nginx并发处理的最大连接数量(由nginx.conf中的worker_processes和worker_connections参数决定)而确定。当然,如果仅仅为了提高并发量使服务器不出现Out
Of
Memory问题而去降低滑动窗口大小,那么并不合适,因为滑动窗口过小会影响大数据量的传输速度。rmem_default、wmem_default、rmem_max、wmem_max这4个参数的设置需要根据我们的业务特性以及实际的硬件成本来综合考虑。
tcp_syncookies:该参数与性能无关,用于解决TCP的SYN攻击。
1.3.5 获取Nginx源码
可以在Nginx官方网站(http:nginx.orgendownload.html)获取Nginx源码包。将下载的nginx-1.0.14.tar.gz源码压缩包放置到准备好的Nginx源代码目录中,然后解压。例如:
tar -zxvf nginx-1.0.14.tar.gz
本书编写时的Nginx最新稳定版本为1.0.14(如图1-2所示),本书后续部分都将以此版本作为基准。当然,本书将要说明的Nginx核心代码一般不会有改动(否则大量第三方模块的功能就无法保证了),即使下载其他版本的Nginx源码包也不会影响阅读本书。

图1-2 Nginx的不同版本
1.4 编译安装Nginx
安装Nginx最简单的方式是,进入nginx-1.0.14目录后执行以下3行命令:
.configure
make
make install
configure命令做了大量的“幕后”工作,包括检测操作系统内核和已经安装的软件,参数的解析,中间目录的生成以及根据各种参数生成一些C源码文件、Makefile文件等。
make命令根据configure命令生成的Makefile文件编译Nginx工程,并生成目标文件、最终的二进制文件。
make
install命令根据configure执行时的参数将Nginx部署到指定的安装目录,包括相关目录的建立和二进制文件、配置文件的复制。
1.5 configure详解
可以看出,configure命令至关重要,下文将详细介绍如何使用configure命令,并分析configure到底是如何工作的,从中我们也可以看出Nginx的一些设计思想。
1.5.1 configure的命令参数
使用help命令可以查看configure包含的参数。
.configure --help
这里不一一列出help的结果,只是把它的参数分为了四大类型,下面将会详述各类型下所有参数的用法和意义。
1. 路径相关的参数
表1-2列出了Nginx在编译期、运行期中与路径相关的各种参数。
表1-2 configure支持的路径相关参数
参数名称 意 义 默 认 值
--prefix=PATH Nginx安装部署后的根目录
默认为usrlocalnginx目录。注意:这个目标的设置会影响其他参数中的相对目录。例如,如果设置了--sbin-path=sbinnginx,那么实际上可执行文件会被放到usrlocalnginxsbinnginx中
--sbin-path=PATH 可执行文件的放置路径
sbinnginx
--conf-path=PATH 配置文件的放置路径
confnginx.conf
--error-log-path=PATH
error日志文件的放置路径。error日志用于定位问题,可输出多种级别(包括debug调试级别)的日志。它的配置非常灵活,可以在nginx.conf里配置为不同请求的日志并输出到不同的log文件中。这里是默认的Nginx核心日志路径
logserror.log
--pid-path=PATH pid文件的存放路径。这个文件里仅以ASC
II码存放着Nginx master的进程ID,有了这个进程ID,在使用命令行(例如nginx -s
reload)通过读取master进程ID向master进程发送信号时,才能对运行中的Nginx服务产生作用
logsnginx.pid
--lock-path=PATH lock文件的放置路径
logsnginx.lock
--builddir=DIR
configure执行时与编译期间产生的临时文件放置的目录,包括产生的Makefile、C源文件、目标文件、可执行文件等
objs
--with-perl_modules_path=PATH perl
module放置的路径。只有使用了第三方的perl module,才需要配置这个路径

--with-perl=PATH perl
binary放置的路径。如果配置的Nginx会执行Perl脚本,那么就必须要设置此路径

--http-log-path=PATH
access日志放置的位置。每一个HTTP请求在结束时都会记录的访问日志
logsaccess.log
--http-client-body-temp-path=PATH
处理HTTP请求时如果请求的包体需要暂时存放到临时磁盘文件中,则把这样的临时文件放置到该路径下
client_body_temp
--http-proxy-temp-path=PATH
Nginx作为HTTP反向代理服务器时,上游服务器产生的HTTP包体在需要临时存放到磁盘文件时(详见12.8节),这样的临时文件将放到该路径下
proxy_temp
--http-fastcgi-temp-path=PATH
Fastcgi所使用临时文件的放置目录 fastcgi_temp
--http-uwsgi-temp-path=PATH
uWSGI所使用临时文件的放置目录 uwsgi_temp
--http-scgi-temp-path=PATH
SCGI所使用临时文件的放置目录 scgi_temp

2. 编译相关的参数
表1-3列出了编译Nginx时与编译器相关的参数。
表1-3 configure支持的编译相关参数
编译参数 意 义
--with-cc=PATH C编译器的路径
--with-cpp=PATH C预编译器的路径
--with-cc-opt=OPTIONS
如果希望在Nginx编译期间指定加入一些编译选项,如指定宏或者使用-I加入某些需要包含的目录,这时可以使用该参数达成目的
--with-ld-opt=OPTIONS
最终的二进制可执行文件是由编译后生成的目标文件与一些第三方库链接生成的,在执行链接操作时可能会需要指定链接参数,--with-ld-opt就是用于加入链接时的参数。例如,如果我们希望将某个库链接到Nginx程序中,需要在这里加入--with-ld-opt=-llibraryName
-LlibraryPath,其中libraryName是目标库的名称,libraryPath则是目标库所在的路径
--with-cpu-opt=CPU
指定CPU处理器架构,只能从以下取值中选择:pentium、pentiumpro、pentium3、pentium4、athlon、opteron、sparc32、sparc64、ppc64

3. 依赖软件的相关参数
表1-4~表1-8列出了Nginx依赖的常用软件支持的参数。
表1-4 PCRE的设置参数
PCRE库的设置参数 意 义
--without-pcre
如果确认Nginx不用解析正则表达式,也就是说,nginx.conf配置文件中不会出现正则表达式,那么可以使用这个参数
--with-pcre 强制使用PCRE库
--with-pcre=DIR
指定PCRE库的源码位置,在编译Nginx时会进入该目录编译PCRE源码
--with-pcre-opt=OPTIONS
编译PCRE源码时希望加入的编译选项


表1-5 OpenSSL的设置参数
OpenSSL库的设置参数 意 义
--with-openssl=DIR
指定OpenSSL库的源码位置,在编译Nginx时会进入该目录编译OpenSSL源码
注意:如果Web服务器支持HTTPS,也就是SSL协议,Nginx要求必须使用OpenSSL。可以访问http:www.openssl.org免费下载
--with-openssl-opt=OPTIONS
编译OpenSSL源码时希望加入的编译选项

表1-6 原子库的设置参数
atomic(原子)库的设置参数 意 义
--with-libatomic
强制使用atomic库。atomic库是CPU架构独立的一种原子操作的实现。它支持以下体系架构:x86(包括i386和x86_64)、PPC64、Sparc64(v9或更高版本)或者安装了GCC
4.1.0及更高版本的架构。14.3节介绍了原子操作在Nginx中的实现
--with-libatomic=DIR atomic库所在的位置

表1-7 散列函数库的设置参数
散列函数库的设置参数 意义
--with-MD5=DIR
指定MD5库的源码位置,在编译Nginx时会进入该目录编译MD5源码
注意:Nginx源码中已经有了MD5算法的实现,如果没有特殊需求,那么完全可以使用Nginx自身实现的MD5算法
--with-MD5-opt=OPTIONS 编译MD5源码时希望加入的编译选项
---with-MD5-asm 使用MD5的汇编源码
--with-SHA1=DIR
指定SHA1库的源码位置,在编译Nginx时会进入该目录编译SHA1源码。
注意:OpenSSL中已经有了SHA1算法的实现。如果已经安装了OpenSSL,那么完全可以使用OpenSSL实现的SHA1算法
--with-SHA1-opt=OPTIONS
编译SHA1源码时希望加入的编译选项
--with-SHA1-asm 使用SHA1的汇编源码

表1-8 zlib库的设置参数
zlib库的设置参数 意 义
--with-zlib=DIR
指定zlib库的源码位置,在编译Nginx时会进入该目录编译zlib源码。如果使用了gzip压缩功能,就需要zlib库的支持
--with-zlib-opt=OPTIONS
编译zlib源码时希望加入的编译选项
--with-zlib-asm=CPU
指定对特定的CPU使用zlib库的汇编优化功能,目前仅支持两种架构:pentium和pentiumpro

4. 模块相关的参数
除了少量核心代码外,Nginx完全是由各种功能模块组成的。这些模块会根据配置参数决定自己的行为,因此,正确地使用各个模块非常关键。在configure的参数中,我们把它们分为五大类。
事件模块。
默认即编译进入Nginx的HTTP模块。
默认不会编译进入Nginx的HTTP模块。
邮件代理服务器相关的mail 模块。
其他模块。
(1)事件模块
表1-9中列出了Nginx可以选择哪些事件模块编译到产品中。
表1-9 configure支持的事件模块参数
编译参数 意 义
--with-rtsig_module 使用rtsig module处理事件驱动
默认情况下,Nginx是不安装rtsig module的,即不会把rtsig
module编译进最终的Nginx二进制程序中
--with-select_module 使用select
module处理事件驱动
select是Linux提供的一种多路复用机制,在epoll调用没有诞生前,例如在Linux
2.4及其之前的内核中,select用于支持服务器提供高并发连接
默认情况下,Nginx是不安装select module的,但如果没有找到其他更好的事件模块,该模块将会被安装
--without-select_module 不安装select module
--with-poll_module 使用poll module处理事件驱动
poll的性能与select类似,在大量并发连接下性能都远不如epoll。默认情况下,Nginx是不安装poll
module的
--without-poll_module 不安装poll module
--with-aio_module 使用AIO方式处理事件驱动
注意:这里的aio module只能与FreeBSD操作系统上的kqueue事件处理机制合作,Linux上无法使用
默认情况下是不安装aio module的

(2)默认即编译进入Nginx的HTTP模块
表1-10列出了默认就会编译进Nginx的核心HTTP模块,以及如何把这些HTTP模块从产品中去除。
表1-10 configure中默认编译到Nginx中的HTTP模块参数
默认安装的HTTP 模块 意 义
--without-http_charset_module 不安装http charset
module。这个模块可以将服务器发出的HTTP响应重编码
--without-http_gzip_module 不安装http gzip
module。在服务器发出的HTTP响应包中,这个模块可以按照配置文件指定的content-type对特定大小的HTTP响应包体执行gzip压缩
--without-http_ssi_module 不安装http ssi
module。该模块可以在向用户返回的HTTP响应包体中加入特定的内容,如HTML文件中固定的页头和页尾
--without-http_userid_module 不安装http userid
module。这个模块可以通过HTTP请求头部信息里的一些字段认证用户信息,以确定请求是否合法
--without-http_access_module 不安装http access
module。这个模块可以根据IP地址限制能够访问服务器的客户端
--without-http_auth_basic_module 不安装http auth
basic module。这个模块可以提供最简单的用户名密码认证
--without-http_autoindex_module 不安装http
autoindex module。该模块提供简单的目录浏览功能
--without-http_geo_module 不安装http geo
module。这个模块可以定义一些变量,这些变量的值将与客户端IP地址关联,这样Nginx针对不同的地区的客户端(根据IP地址判断)返回不一样的结果,例如不同地区显示不同语言的网页
--without-http_map_module 不安装http map
module。这个模块可以建立一个keyvalue映射表,不同的key得到相应的value,这样可以针对不同的URL做特殊处理。例如,返回302重定向响应时,可以期望URL不同时返回的Location字段也不一样
--without-http_split_clients_module 不安装http
split client module。该模块会根据客户端的信息,例如IP地址、header头、cookie等,来区分处理
--without-http_referer_module 不安装http referer
module。该模块可以根据请求中的referer字段来拒绝请求
--without-http_rewrite_module 不安装http rewrite
module。该模块提供HTTP请求在Nginx服务内部的重定向功能,依赖PCRE库
--without-http_proxy_module 不安装http proxy
module。该模块提供基本的HTTP反向代理功能
--without-http_fastcgi_module 不安装http fastcgi
module。该模块提供FastCGI功能
--without-http_uwsgi_module 不安装http uwsgi
module。该模块提供uWSGI功能
--without-http_scgi_module 不安装http scgi
module。该模块提供SCGI功能
--without-http_memcached_module 不安装http
memcached
module。该模块可以使得Nginx直接由上游的memcached服务读取数据,并简单地适配成HTTP响应返回给客户端
--without-http_limit_zone_module 不安装http limit
zone module。该模块针对某个IP地址限制并发连接数。例如,使Nginx对一个IP地址仅允许一个连接
--without-http_limit_req_module 不安装http limit
req module。该模块针对某个IP地址限制并发请求数
--without-http_empty_gif_module 不安装http empty
gif
module。该模块可以使得Nginx在收到无效请求时,立刻返回内存中的1×1像素的GIF图片。这种好处在于,对于明显的无效请求不会去试图浪费服务器资源
--without-http_browser_module 不安装http browser
module。该模块会根据HTTP请求中的user-agent字段(该字段通常由浏览器填写)来识别浏览器
--without-http_upstream_ip_hash_module 不安装http
upstream ip hash
module。该模块提供当Nginx与后端server建立连接时,会根据IP做散列运算来决定与后端哪台server通信,这样可以实现负载均衡

(3)默认不会编译进入Nginx的HTTP模块
表1-11列出了默认不会编译至Nginx中的HTTP模块以及把它们加入产品中的方法。


表1-11 configure中默认不会编译到Nginx中的HTTP模块参数
可选的HTTP 模块 意 义
--with-http_ssl_module 安装http ssl
module。该模块使Nginx支持SSL协议,提供HTTPS服务。
注意:该模块的安装依赖于OpenSSL开源软件,即首先应确保已经在之前的参数中配置了OpenSSL
--with-http_realip_module 安装http realip
module。该模块可以从客户端请求里的header信息(如X-Real-IP或者X-Forwarded-For)中获取真正的客户端IP地址
--with-http_addition_module 安装http addtion
module。该模块可以在返回客户端的HTTP包体头部或者尾部增加内容
--with-http_xslt_module 安装http xslt
module。这个模块可以使XML格式的数据在发给客户端前加入XSL渲染
注意:这个模块依赖于libxml2和libxslt库,安装它前首先确保上述两个软件已经安装
--with-http_image_filter_module 安装http
image_filter
module。这个模块将符合配置的图片实时压缩为指定大小(width*height)的缩略图再发送给用户,目前支持JPEG、PNG、GIF格式。
注意:这个模块依赖于开源的libgd库,在安装前确保操作系统已经安装了libgd
--with-http_geoip_module 安装http geoip
module。该模块可以依据MaxMind GeoIP的IP地址数据库对客户端的IP地址得到实际的地理位置信息
注意:该库依赖于MaxMind
GeoIP的库文件,可访问http:geolite.maxmind.comdownloadgeoipdatabaseGeoLiteCity.dat.gz获取
--with-http_sub_module 安装http sub
module。该模块可以在Nginx返回客户端的HTTP响应包中将指定的字符串替换为自己需要的字符串
例如,在HTML的返回中,将替换为
--with-http_dav_module 安装http dav
module。这个模块可以让Nginx支持Webdav标准,如支持Webdav协议中的PUT、DELETE、COPY、MOVE、MKCOL等请求
--with-http_flv_module 安装http flv
module。这个模块可以在向客户端返回响应时,对FLV格式的视频文件在header头做一些处理,使得客户端可以观看、拖动FLV视频
--with-http_mp4_module 安装http mp4
module。该模块使客户端可以观看、拖动MP4视频
--with-http_gzip_static_module 安装http gzip
static
module。如果采用gzip模块把一些文档进行gzip格式压缩后再返回给客户端,那么对同一个文件每次都会重新压缩,这是比较消耗服务器CPU资源的。gzip
static模块可以在做gzip压缩前,先查看相同位置是否有已经做过gzip压缩的.gz文件,如果有,就直接返回。这样就可以预先在服务器上做好文档的压缩,给CPU减负
--with-http_random_index_module 安装http random
index module。该模块在客户端访问某个目录时,随机返回该目录下的任意文件
--with-http_secure_link_module 安装http secure
link
module。该模块提供一种验证请求是否有效的机制。例如,它会验证URL中需要加入的token参数是否属于特定客户端发来的,以及检查时间戳是否过期
--with-http_degradation_module 安装http
degradation
module。该模块针对一些特殊的系统调用(如sbrk)做一些优化,如直接返回HTTP响应码为204或者444。目前不支持Linux系统
--with-http_stub_status_module 安装http stub
status
module。该模块可以让运行中的Nginx提供性能统计页面,获取相关的并发连接、请求的信息(14.2.1节中简单介绍了该模块的原理)
--with-google_perftools_module 安装google
perftools module。该模块提供Google的性能测试工具

(4)邮件代理服务器相关的mail模块
表1-12列出了把邮件模块编译到产品中的参数。
表1-12 configure提供的邮件模块参数
可选的mail 模块 意 义
--with-mail
安装邮件服务器反向代理模块,使Nginx可以反向代理IMAP、POP3、SMTP等协议。该模块默认不安装
--with-mail_ssl_module 安装mail ssl
module。该模块可以使IMAP、POP3、SMTP等协议基于SSLTLS协议之上使用。该模块默认不安装并依赖于OpenSSL库
--without-mail_pop3_module 不安装mail pop3
module。在使用--with-mail参数后,pop3 module是默认安装的,以使Nginx支持POP3协议
--without-mail_imap_module 不安装mail imap
module。在使用--with-mail参数后,imap module是默认安装的,以使Nginx支持IMAP
--without-mail_smtp_module 不安装mail smtp
module。在使用--with-mail参数后,smtp module是默认安装的,以使Nginx支持SMTP

5.其他参数
configure还接收一些其他参数,表1-13中列出了相关参数的说明。
表1-13 configure提供的其他参数
其他一些参数 意 义
--with-debug
将Nginx需要打印debug调试级别日志的代码编译进Nginx。这样可以在Nginx运行时通过修改配置文件来使其打印调试日志,这对于研究、定位Nginx问题非常有帮助
--add-module=PATH
当在Nginx里加入第三方模块时,通过这个参数指定第三方模块的路径。这个参数将在下文如何开发HTTP模块时使用到
--without-http 禁用HTTP服务器
--without-http-cache 禁用HTTP服务器里的缓存Cache特性
--with-file-aio
启用文件的异步IO功能来处理磁盘文件,这需要Linux内核支持原生的异步IO
--with-ipv6 使Nginx支持IPv6
--user=USER 指定Nginx worker进程运行时所属的用户
注意:不要将启动worker进程的用户设为root,在worker进程出问题时master进程要具备停止启动worker进程的能力
--group=GROUP 指定Nginx worker进程运行时所属的组

1.5.2 configure执行流程
我们看到configure命令支持非常多的参数,读者可能会好奇它在执行时到底做了哪些事情,本节将通过解析configure源码来对它有一个感性的认识。configure由Shell脚本编写,中间会调用auto目录下的脚本。这里将只对configure脚本本身做分析,对于它所调用的auto目录下的其他工具脚本则只做功能性的说明。
configure脚本的内容如下:
#!binsh

# Copyright C Igor Sysoev
# Copyright C Nginx, Inc.

#autooptions脚本处理configure命令的参数。例如,如果参数是--help,那么显示支持的所有参数格式。options脚本会定义后续工作将要用到的变量,然后根据本次参数以及默认值设置这些变量
. autooptions

#autoinit脚本初始化后续将产生的文件路径。例如,Makefile、ngx_modules.c等文件默认情况下将会在objs
. autoinit

#autosources脚本将分析Nginx的源码结构,这样才能构造后续的Makefile文件
. autosources

#编译过程中所有目标文件生成的路径由—builddir=DIR参数指定,默认情况下为objs,此时这个目录将会被创建
test -d $NGX_OBJS || mkdir $NGX_OBJS

#开始准备建立ngx_auto_headers.h、autoconf.err等必要的编译文件
echo $NGX_AUTO_HEADERS_H
echo $NGX_AUTOCONF_ERR

#向objsngx_auto_config.h写入命令行带的参数
echo "#define NGX_CONFIGURE \"$NGX_CONFIGURE\""
$NGX_AUTO_CONFIG_H

#判断DEBUG标志,如果有,那么在objsngx_auto_config.h文件中写入DEBUG宏
if [ $NGX_DEBUG = YES ]; then
have=NGX_DEBUG . autohave
fi

#现在开始检查操作系统参数是否支持后续编译
if test -z "$NGX_PLATFORM"; then
echo "checking for OS"

NGX_SYSTEM=`uname -s 2devnull`
NGX_RELEASE=`uname -r 2devnull`
NGX_MACHINE=`uname -m 2devnull`

#屏幕上输出OS名称、内核版本、32位64位内核
echo " + $NGX_SYSTEM $NGX_RELEASE
$NGX_MACHINE"


NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE";

case "$NGX_SYSTEM" in
MINGW32_*

NGX_PLATFORM=win32
;;
esac

else
echo "building for $NGX_PLATFORM"
NGX_SYSTEM=$NGX_PLATFORM
fi

#检查并设置编译器,如GCC是否安装、GCC版本是否支持后续编译nginx
. autoccconf

#对非Windows操作系统定义一些必要的头文件,并检查其是否存在,以此决定configure后续步骤是否可以成功
if [ "$NGX_PLATFORM" != win32 ]; then
. autoheaders
fi

#对于当前操作系统,定义一些特定的操作系统相关的方法并检查当前环境是否支持。例如,对于Linux,在这里使用sched_setaffinity设置进程优先级,使用Linux特有的sendfile系统调用来加速向网络中发送文件块
. autoosconf

#定义类UNIX 操作系统中通用的头文件和系统调用等,并检查当前环境是否支持
if [ "$NGX_PLATFORM" != win32 ]; then
. autounix
fi

#最核心的构造运行期modules的脚本。它将会生成ngx_modules.c文件,这个文件会被编译进Nginx中,其中它所做的唯一的事情就是定义了ngx_modules数组。ngx_modules指明Nginx运行期间有哪些模块会参与到请求的处理中,包括HTTP请求可能会使用哪些模块处理,因此,它对数组元素的顺序非常敏感,也就是说,绝大部分模块在ngx_modules数组中的顺序其实是固定的。例如,一个请求必须先执行ngx_http_gzip_filter_module模块重新修改HTTP响应中的头部后,才能使用ngx_http_header_filter模块按照headers_in结构体里的成员构造出以TCP流形式发送给客户端的HTTP响应头部。注意,我们在--add-module=参数里加入的第三方模块也在此步骤写入到ngx_modules.c文件中了
. automodules

#conf脚本用来检查Nginx在链接期间需要链接的第三方静态库、动态库或者目标文件是否存在
. autolibconf

#处理Nginx安装后的路径
case ".$NGX_PREFIX" in
.

NGX_PREFIX=${NGX_PREFIX:-usrlocalnginx}
have=NGX_PREFIX
value="\"$NGX_PREFIX\"" . autodefine
;;

.!
NGX_PREFIX=
;;

*
have=NGX_PREFIX
value="\"$NGX_PREFIX\"" . autodefine
;;
esac

#处理Nginx安装后conf文件的路径
if [ ".$NGX_CONF_PREFIX" != "." ]; then
have=NGX_CONF_PREFIX
value="\"$NGX_CONF_PREFIX\"" . autodefine
fi

#处理Nginx安装后,二进制文件、pid、lock等其他文件的路径可参见configure参数中路径类选项的说明
have=NGX_SBIN_PATH value="\"$NGX_SBIN_PATH\"" . autodefine
have=NGX_CONF_PATH value="\"$NGX_CONF_PATH\"" . autodefine
have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . autodefine
have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . autodefine
have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" .
autodefine


have=NGX_HTTP_LOG_PATH value="\"$NGX_HTTP_LOG_PATH\"" .
autodefine
have=NGX_HTTP_CLIENT_TEMP_PATH
value="\"$NGX_HTTP_CLIENT_TEMP_PATH\"" . autodefine
have=NGX_HTTP_PROXY_TEMP_PATH
value="\"$NGX_HTTP_PROXY_TEMP_PATH\"" . autodefine
have=NGX_HTTP_FASTCGI_TEMP_PATH
value="\"$NGX_HTTP_FASTCGI_TEMP_PATH\"" . autodefine
have=NGX_HTTP_UWSGI_TEMP_PATH
value="\"$NGX_HTTP_UWSGI_TEMP_PATH\"" . autodefine
have=NGX_HTTP_SCGI_TEMP_PATH value="\"$NGX_HTTP_SCGI_TEMP_PATH\""
. autodefine

#创建编译时使用的objsMakefile文件
. automake

#为objsMakefile加入需要连接的第三方静态库、动态库或者目标文件
. autolibmake

#为objsMakefile加入install功能,当执行make
install时将编译生成的必要文件复制到安装路径,建立必要的目录
. autoinstall

# 在ngx_auto_config.h文件中加入NGX_SUPPRESS_WARN宏、NGX_SMP宏
. autostubs

#在ngx_auto_config.h文件中指定NGX_USER和NGX_GROUP宏,如果执行configure时没有参数指定,默认两者皆为nobody(也就是默认以nobody用户运行进程)
have=NGX_USER value="\"$NGX_USER\"" . autodefine
have=NGX_GROUP value="\"$NGX_GROUP\"" . autodefine

#显示configure执行的结果,如果失败,则给出原因
. autosummary

1.5.3 configure生成的文件
当configure执行成功时会生成objs目录,并在该目录下产生以下目录和文件:
|---ngx_auto_headers.h
|---autoconf.err
|---ngx_auto_config.h
|---ngx_modules.c
|---src
| |---core
| |---event
| | |---modules
| |---os
| | |---unix
| | |---win32
| |---http
| | |---modules
| |
| |---perl
| |---mail
| |---misc
|---Makefile
上述目录和文件介绍如下。
1)src目录用于存放编译时产生的目标文件。
2)Makefile文件用于编译Nginx工程以及在加入install参数后安装Nginx。
3)autoconf.err保存configure执行过程中产生的结果。
4)ngx_auto_headers.h和ngx_auto_config.h保存了一些宏,这两个头文件会被srccorengx_config.h及srcosunixngx_linux_config.h文件(可将“linux”替换为其他UNIX操作系统)引用。
5)ngx_modules.c是一个关键文件,我们需要看看它的内部结构。一个默认配置下生成的ngx_modules.c文件内容如下:
#include
#include



ngx_module_t *ngx_modules[] = {
ngx_core_module,
ngx_errlog_module,
ngx_conf_module,
ngx_events_module,
ngx_event_core_module,
ngx_epoll_module,
ngx_http_module,
ngx_http_core_module,
ngx_http_log_module,
ngx_http_upstream_module,
ngx_http_static_module,
ngx_http_autoindex_module,
ngx_http_index_module,
ngx_http_auth_basic_module,
ngx_http_access_module,
ngx_http_limit_zone_module,
ngx_http_limit_req_module,
ngx_http_geo_module,
ngx_http_map_module,
ngx_http_split_clients_module,
ngx_http_referer_module,
ngx_http_rewrite_module,
ngx_http_proxy_module,
ngx_http_fastcgi_module,
ngx_http_uwsgi_module,
ngx_http_scgi_module,
ngx_http_memcached_module,
ngx_http_empty_gif_module,
ngx_http_browser_module,
ngx_http_upstream_ip_hash_module,
ngx_http_write_filter_module,
ngx_http_header_filter_module,
ngx_http_chunked_filter_module,

ngx_http_range_header_filter_module,
ngx_http_gzip_filter_module,
ngx_http_postpone_filter_module,
ngx_http_ssi_filter_module,
ngx_http_charset_filter_module,
ngx_http_userid_filter_module,
ngx_http_headers_filter_module,
ngx_http_copy_filter_module,
ngx_http_range_body_filter_module,

ngx_http_not_modified_filter_module,
NULL
};
ngx_modules.c文件就是用来定义ngx_modules数组的。
ngx_modules是非常关键的数组,它指明了每个模块在Nginx中的优先级,当一个请求同时符合多个模块的处理规则时,将按照它们在ngx_modules数组中的顺序选择最靠前的模块优先处理。对于HTTP过滤模块而言则是相反的,因为HTTP框架在初始化时,会在ngx_modules数组中将过滤模块按先后顺序向过滤链表中添加,但每次都是添加到链表的表头,因此,对HTTP过滤模块而言,在ngx_modules数组中越是靠后的模块反而会首先处理HTTP响应(参见第6章及第11章的11.9节)。
因此,ngx_modules中模块的先后顺序非常重要,不正确的顺序会导致Nginx无法工作,这是automodules脚本执行后的结果。读者可以体会一下上面的ngx_modules中同一种类型下(第8章会介绍模块类型,第10章、第11章将介绍的HTTP框架对HTTP模块的顺序是最敏感的)各个模块的顺序以及这种顺序带来的意义。
可以看出,在安装过程中,configure做了大量的幕后工作,我们需要关注在这个过程中Nginx做了哪些事情。configure除了寻找依赖的软件外,还针对不同的UNIX操作系统做了许多优化工作。这是Nginx跨平台的一种具体实现,也体现了Nginx追求高性能的一贯风格。
configure除了生成Makefile外,还生成了ngx_modules.c文件,它决定了运行时所有模块的优先级(在编译过程中而不是编码过程中)。对于不需要的模块,既不会加入ngx_modules数组,也不会编译进Nginx产品中,这也体现了轻量级的概念。
1.6 Nginx的命令行控制
在Linux中,需要使用命令行来控制Nginx服务器的启动与停止、重载配置文件、回滚日志文件、平滑升级等行为。默认情况下,Nginx被安装在目录usrlocalnginx中,其二进制文件路径为usrlocalngincsbinnginx,配置文件路径为usrlocalnginxconfnginx.conf。当然,在configure执行时是可以指定把它们安装在不同目录的。为了简单起见,本节只说明默认安装情况下的命令行的使用情况,如果读者安装的目录发生了变化,那么替换一下即可。
(1)默认方式启动
直接执行Nginx二进制程序。例如:
usrlocalnginxsbinnginx
这时,会读取默认路径下的配置文件:usrlocalnginxconfnginx.conf。
实际上,在没有显式指定nginx.conf配置文件路径时,将打开在configure命令执行时使用--conf-path=PATH指定的nginx.conf文件(参见1.5.1节)。
(2)另行指定配置文件的启动方式
使用-c参数指定配置文件。例如:
usrlocalnginxsbinnginx -c tmpnginx.conf
这时,会读取-c参数后指定的nginx.conf配置文件来启动Nginx。
(3)另行指定安装目录的启动方式
使用-p参数指定Nginx的安装目录。例如:
usrlocalnginxsbinnginx -p usrlocalnginx
(4)另行指定全局配置项的启动方式
可以通过-g参数临时指定一些全局配置项,以使新的配置项生效。例如:
usrlocalnginxsbinnginx -g "pid varnginxtest.pid;"
上面这行命令意味着会把pid文件写到varnginxtest.pid中。
-g参数的约束条件是指定的配置项不能与默认路径下的nginx.conf中的配置项相冲突,否则无法启动。就像上例那样,类似这样的配置项:pid
logsnginx.pid,是不能存在于默认的nginx.conf中的。
另一个约束条件是,以-g方式启动的Nginx服务执行其他命令行时,需要把-g参数也带上,否则可能出现配置项不匹配的情形。例如,如果要停止Nginx服务,那么需要执行下面代码:
usrlocalnginxsbinnginx -g "pid varnginxtest.pid;" -s
stop
如果不带上-g "pid
varnginxtest.pid;",那么找不到pid文件,也会出现无法停止服务的情况。
(5)测试配置信息是否有错误
在不启动Nginx的情况下,使用-t参数仅测试配置文件是否有错误。例如:
usrlocalnginxsbinnginx -t
执行结果中显示配置是否正确。
(6)在测试配置阶段不输出信息
测试配置选项时,使用-q参数可以不把error级别以下的信息输出到屏幕。例如:
usrlocalnginxsbinnginx -t -q
(7)显示版本信息
使用-v参数显示Nginx的版本信息。例如:
usrlocalnginxsbinnginx -v
(8)显示编译阶段的参数
使用-V参数除了可以显示Nginx的版本信息外,还可以显示配置编译阶段的信息,如GCC编译器的版本、操作系统的版本、执行configure时的参数等。例如:
usrlocalnginxsbinnginx -V
(9)快速地停止服务
使用-s
stop可以强制停止Nginx服务。-s参数其实是告诉Nginx程序向正在运行的Nginx服务发送信号量,Nginx程序通过nginx.pid文件中得到master进程的进程ID,再向运行中的master进程发送TERM信号来快速地关闭Nginx服务。例如:
usrlocalnginxsbinnginx -s stop
实际上,如果通过kill命令直接向nginx
master进程发送TERM或者INT信号,效果是一样的。例如,先通过ps命令来查看nginx master的进程ID:
:ahf5wapi001:root ps -ef | grep nginx
root 10800
1 0 02:27 ?
00:00:00 nginx: master process .nginx
root 10801 10800 0 02:27
? 00:00:00 nginx: worker
process
接下来直接通过kill命令来发送信号:
kill -s SIGTERM 10800
或者:
kill -s SIGINT 10800
上述两条命令的效果与执行usrlocalnginxsbinnginx -s stop是完全一样的。
(10)“优雅”地停止服务
如果希望Nginx服务可以正常地处理完当前所有请求再停止服务,那么可以使用-s quit参数来停止服务。例如:
usrlocalnginxsbinnginx -s quit
该命令与快速停止Nginx服务是有区别的。当快速停止服务时,worker进程与master进程在收到信号后会立刻跳出循环,退出进程。而“优雅”地停止服务时,首先会关闭监听端口,停止接收新的连接,然后把当前正在处理的连接全部处理完,最后再退出进程。
与快速停止服务相似,可以直接发送QUIT信号给master进程来停止服务,其效果与执行-s
quit命令是一样的。例如:
kill -s SIGQUIT
如果希望“优雅”地停止某个worker进程,那么可以通过向该进程发送WINCH信号来停止服务。例如:
kill -s SIGWINCH
(11)使运行中的Nginx重读配置项并生效
使用-s reload参数可以使运行中的Nginx服务重新加载nginx.conf文件。例如:
usrlocalnginxsbinnginx -s reload
事实上,Nginx会先检查新的配置项是否有误,如果全部正确就以“优雅”的方式关闭,再重新启动Nginx来实现这个目的。类似的,-s是发送信号,仍然可以用kill命令发送HUP信号来达到相同的效果。
kill -s SIGHUP

(12)日志文件回滚
使用-s
reopen参数可以重新打开日志文件,这样可以先把当前日志文件改名或转移到其他目录中进行备份,再重新打开时就会生成新的日志文件。这个功能使得日志文件不至于过大。例如:
usrlocalnginxsbinnginx -s reopen
当然,这与使用kill命令发送USR1信号效果相同。
kill -s SIGUSR1
(13)平滑升级Nginx
当Nginx服务升级到新的版本时,必须要将旧的二进制文件Nginx替换掉,通常情况下这是需要重启服务的,但Nginx支持不重启服务来完成新版本的平滑升级。
升级时包括以下步骤:
1)通知正在运行的旧版本Nginx准备升级。通过向master进程发送USR2信号可达到目的。例如:
kill -s SIGUSR2
这时,运行中的Nginx会将pid文件重命名,如将usrlocalnginxlogsnginx.pid重命名为usrlocalnginxlogsnginx.pid.oldbin,这样新的Nginx才有可能启动成功。
2)启动新版本的Nginx,可以使用以上介绍过的任意一种启动方法。这时通过ps命令可以发现新旧版本的Nginx在同时运行。
3)通过kill命令向旧版本的master进程发送SIGQUIT信号,以“优雅”的方式关闭旧版本的Nginx。随后将只有新版本的Nginx服务运行,此时平滑升级完毕。
(14)显示命令行帮助
使用-h或者-?参数会显示支持的所有命令行参数。
1.7 小结
本章介绍了Nginx的特点以及在什么场景下需要使用Nginx,同时介绍了如何获取Nginx以及如何配置、编译、安装运行Nginx。本章还深入介绍了最为复杂的configure过程,这部分内容是学习本书第二部分和第三部分的基础。


第2章 Nginx的配置
Nginx拥有大量官方发布的模块和第三方模块,这些已有的模块可以帮助我们实现Web服务器上很多的功能。使用这些模块时,仅仅需要增加、修改一些配置项即可。因此,本章的目的是熟悉Nginx的配置文件,包括配置文件的语法格式、运行所有Nginx服务必须具备的基础配置以及使用HTTP核心模块配置静态Web服务器的方法,最后还会介绍反向代理服务器。
通过本章的学习,读者可以:熟练地配置一个静态Web服务器;对影响Web服务器性能的各个配置项有深入的理解;对配置语法有全面的了解。通过互联网或其他途径得到任意模块的配置说明,然后可通过修改nginx.conf文件来使用这些模块的功能。
2.1 运行中的Nginx进程间的关系
在正式提供服务的产品环境下,部署Nginx时都是使用一个master进程来管理多个worker进程,一般情况下,worker进程的数量与服务器上的CPU核心数相等。每一个worker进程都是繁忙的,它们在真正地提供互联网服务,master进程则很“清闲”,只负责监控管理worker进程。worker进程之间通过共享内存、原子操作等一些进程间通信机制来实现负载均衡等功能(第9章将会介绍负载均衡机制,第14章将会介绍负载均衡锁的实现)。
部署后Nginx进程间的关系如图2-1所示。
Nginx是支持单进程(master进程)提供服务的,那么为什么产品环境下要按照master-worker方式配置同时启动多个进程呢?这样做的好处主要有以下两点:
由于master进程不会对用户请求提供服务,只用于管理真正提供服务的worker进程,所以master进程可以是唯一的,它仅专注于自己的纯管理工作,为管理员提供命令行服务,包括诸如启动服务、停止服务、重载配置文件、平滑升级程序等。master进程需要拥有较大的权限,例如,通常会利用root用户启动master进程。worker进程的权限要小于或等于master进程,这样master进程才可以完全地管理worker进程。当任意一个worker进程出现错误从而导致coredump时,master进程会立刻启动新的worker进程继续服务。
多个worker进程处理互联网请求不但可以提高服务的健壮性(一个worker进程出错后,其他worker进程仍然可以正常提供服务),最重要的是,这样可以充分利用现在常见的SMP多核架构,从而实现微观上真正的多核并发处理。因此,用一个进程(master进程)来处理互联网请求肯定是不合适的。另外,为什么要把worker进程数量设置得与CPU核心数量一致呢?这正是Nginx与Apache服务器的不同之处。在Apache上每个进程在一个时刻只处理一个请求,因此,如果希望Web服务器拥有并发处理的请求数更多,就要把Apache的进程或线程数设置得更多,通常会达到一台服务器拥有几百个工作进程,这样大量的进程间切换将带来无谓的系统资源消耗。而Nginx则不然,一个worker进程可以同时处理的请求数只受限于内存大小,而且在架构设计上,不同的worker进程之间处理并发请求时几乎没有同步锁的限制,worker进程通常不会进入睡眠状态,因此,当Nginx上的进程数与CPU核心数相等时(最好每一个worker进程都绑定特定的CPU核心),进程间切换的代价是最小的。

图2-1 部署后Nginx进程间的关系
举例来说,如果产品中的服务器CPU核心数为8,那么就需要配置8个worker进程(见图2-2)。
如果对路径部分都使用默认配置,那么Nginx运行目录为usrlocalnginx,其目录结构如下。
|---sbin
| |---nginx
|---conf
| |---koi-win
| |---koi-utf
| |---win-utf
| |---mime.types
| |---mime.types.default
| |---fastcgi_params
| |---fastcgi_params.default
| |---fastcgi.conf
| |---fastcgi.conf.default
| |---uwsgi_params
| |---uwsgi_params.default
| |---scgi_params
| |---scgi_params.default
| |---nginx.conf
| |---nginx.conf.default
|---logs
| |---error.log
| |---access.log
| |---nginx.pid
|---html
| |---50x.html
| |---index.html
|---client_body_temp
|---proxy_temp
|---fastcgi_temp
|---uwsgi_temp
|---scgi_temp

图2-2 worker进程的数量尽量与CPU核心数相等
2.2 Nginx配置的通用语法
Nginx的配置文件其实是一个普通的文本文件。下面来看一个简单的例子。
user nobody;

worker_processes 8;
error_log varlognginxerror.log error;

#pid
logsnginx.pid;

events {
use epoll;
worker_connections 50000;
}

http {
include
mime.types;
default_type
applicationoctet-stream;

log_format main ''$remote_addr
[$time_local] "$request" ''

''$status $bytes_sent "$http_referer" ''

''"$http_user_agent" "$http_x_forwarded_for"'';

access_log logsaccess.log main
buffer=32k;



在这段简短的配置代码中,每一行配置项的语法格式都将在2.2.2节介绍,出现的events和http块配置项将在2.2.1节介绍,以#符号开头的注释将在2.2.3节介绍,类似“buffer=32k”这样的配置项的单位将在2.2.4节介绍。
2.2.1 块配置项
块配置项由一个块配置项名和一对大括号组成。具体示例如下:
events {

}

http {
upstream backend {
server
127.0.0.1:8080;
}

gzip on;
server {

location webstatic
{

gzip off;
}
}
}
上面代码段中的events、http、server、location、upstream等都是块配置项,块配置项之后是否如“location
webstatic
{...}”那样在后面加上参数,取决于解析这个块配置项的模块,不能一概而论,但块配置项一定会用大括号把一系列所属的配置项全包含进来,表示大括号内的配置项同时生效。所有的事件类配置都要在events块中,http、server等配置也遵循这个规定。
块配置项可以嵌套。内层块直接继承外层块,例如,上例中,server块里的任意配置都是基于http块里的已有配置的。当内外层块中的配置发生冲突时,究竟是以内层块还是外层块的配置为准,取决于解析这个配置项的模块,第4章将会介绍http块内配置项冲突的处理方法。例如,上例在http模块中已经打开了“gzip
on;”,但其下的locationwebstatic又把gzip关闭了:gzip
off;,最终,在webstatic的处理模块中,gzip模块是按照gzip off来处理请求的。
2.2.2 配置项的语法格式
从上文的示例可以看出,最基本的配置项语法格式如下:
配置项名 配置项值1 配置项值2 … ;
下面解释一下配置项的构成部分。
首先,在行首的是配置项名,这些配置项名必须是Nginx的某一个模块想要处理的,否则Nginx会认为配置文件出现了非法的配置项名。配置项名输入结束后,将以空格作为分隔符。
其次是配置项值,它可以是数字或字符串(当然也包括正则表达式)。针对一个配置项,既可以只有一个值,也可以包含多个值,配置项值之间仍然由空格符来分隔。当然,一个配置项对应的值究竟有多少个,取决于解析这个配置项的模块。我们必须根据某个Nginx
模块对一个配置项的约定来更改配置项,第4章将会介绍模块是如何约定一个配置项的格式。
最后,每行配置的结尾需要加上分号。
注意 如果配置项值中包括语法符号,比如空格符,那么需要使用单引号或双引号括住配置项值,否则Nginx会报语法错误。例如:
log_format main ''$remote_addr - $remote_user
[$time_local] "$request" '';

2.2.3 配置项的注释
如果有一个配置项暂时需要注释掉,那么可以加“#”注释掉这一行配置。例如:
#pid
logsnginx.pid;
2.2.4 配置项的单位
大部分模块遵循一些通用的规定,如指定空间大小时不用每次都定义到字节、指定时间时不用精确到毫秒。
当指定空间大小时,可以使用的单位包括:
K或者k千字节(KiloByte,KB)。
M或者m兆字节(MegaByte,MB)。
例如:
gzip_buffers 4 8k;
client_max_body_size 64M;
当指定时间时,可以使用的单位包括:
ms(毫秒),s(秒),m(分钟),h(小时),d(天),w(周,包含7天),M(月,包含30天),y(年,包含365天)。
例如:
expires 10y;
proxy_read_timeout 600;
client_body_timeout 2m;
注意 配置项后的值究竟是否可以使用这些单位,取决于解析该配置项的模块。如果这个模块使用了Nginx框架提供的相应解析配置项方法,那么配置项值才可以携带单位。第4章中详细描述了Nginx框架提供的14种预设解析方法,其中一些方法将可以解析以上列出的单位。
2.2.5 在配置中使用变量
有些模块允许在配置项中使用变量,如在日志记录部分,具体示例如下。
log_format main ''$remote_addr - $remote_user
[$time_local] "$request" ''

''$status $bytes_sent "$http_referer" ''

''"$http_user_agent" "$http_x_forwarded_for"'';
其中,remote_addr是一个变量,使用它的时候前面要加上$符号。需要注意的是,这种变量只有少数模块支持,并不是通用的。
许多模块在解析请求时都会提供多个变量(如本章后面提到的http core module、http proxy
module、http upstream
module等),以使其他模块的配置可以即时使用。我们在学习某个模块提供的配置说明时可以关注它是否提供变量。
提示 在执行configure命令时,我们已经把许多模块编译进Nginx中,但是否启用这些模块,一般取决于配置文件中相应的配置项。换句话说,每个Nginx
模块都有自己感兴趣的配置项,大部分模块都必须在nginx.conf中读取某个配置项后才会在运行时启用。例如,只有当配置http
{...}这个配置项时,ngx_http_module模块才会在Nginx中启用,其他依赖ngx_http_module的模块也才能正常使用。
2.3 Nginx服务的基本配置
Nginx在运行时,至少必须加载几个核心模块和一个事件类模块。这些模块运行时所支持的配置项称为基本配置—所有其他模块执行时都依赖的配置项。
下面详述基本配置项的用法。由于配置项较多,所以把它们按照用户使用时的预期功能分成了以下4类:
用于调试、定位问题的配置项。
正常运行的必备配置项。
优化性能的配置项。
事件类配置项(有些事件类配置项归纳到优化性能类,这是因为它们虽然也属于events {}块,但作用是优化性能)。
有这么一些配置项,即使没有显式地进行配置,它们也会有

 

 

書城介紹  | 合作申請 | 索要書目  | 新手入門 | 聯絡方式  | 幫助中心 | 找書說明  | 送貨方式 | 付款方式 台灣用户 | 香港/海外用户
megBook.com.tw
Copyright (C) 2013 - 2024 (香港)大書城有限公司 All Rights Reserved.