目　录

完整诠释Nginx

分享Nginx的实战经验

不可多得的Nginx一手资料

联系博文视点

序言

第1部分　基础篇

第1章　Nginx简介

1.1　常用的Web服务器简介

1.2　Nginx的发展

1.3　选择Nginx的理由

1.4　Nginx与Apache、Lighttpd的综合对比

第2章　Nginx服务器的安装与配置

2.1　安装Nginx服务器所需要的系统资源

2.2　Nginx的下载

2.3　Nginx的安装

2.4　Nginx的启动、停止、平滑重启

2.5　Nginx的平滑重启

2.6　Nginx的信号控制

2.7　Nginx的平滑升级

第2部分　进阶篇

第3章　Nginx的基本配置与优化

3.1　Nginx的完整配置示例

3.2　Nginx的虚拟主机配置

3.3　Nginx的日志文件配置与切割

3.4　Nginx的压缩输出配置

3.5　Nginx的自动列目录配置

3.6　Nginx的浏览器本地缓存设置

第4章　Nginx与PHP（FastCGI）的安装、配置与优化

4.1　获取相关开源程序

4.2　安装PHP 5.2.10（FastCGI模式）

4.3　安装Nginx 0.8.15

4.4　配置开机自动启动Nginx+PHP

4.5　优化Linux内核参数

4.6　在不停止Nginx服务的情况下平滑变更Nginx配置

4.7　编写每天定时切割Nginx日志的脚本

第5章　Nginx与JSP、ASP.NET、Perl的安装与配置

5.1　Nginx与JSP（Tomcat）在Linux上的安装、配置

5.2　Nginx与ASP.NET（Mono+FastCGI）在Linux上的安装、配置

5.3　Nginx与Perl（FastCGI）在Linux上的安装、配置

第6章　Nginx HTTP负载均衡和反向代理的配置与优化

6.1　什么是负载均衡和反向代理

6.2　常见的Web负载均衡方法

6.3　Nginx负载均衡与反向代理的配置实例

6.4　Nginx负载均衡的HTTP Upstream模块

6.5　Nginx负载均衡服务器的双机高可用

第7章　Nginx的Rewrite规则与实例

7.1　什么是Nginx的Rewrite规则

7.2　Nginx Rewrite规则相关指令

7.3　PCRE正则表达式语法

7.4　Nginx的Rewrite规则编写实例

7.5　Nginx与Apache的Rewrite规则实例对比

第8章　Nginx模块开发

8.1　Nginx模块概述

8.2　Nginx模块编写实践

第9章　Nginx的Web缓存服务与新浪网的开源NCACHE模块

9.1　什么是Web缓存

9.2　Nginx的Web缓存服务

9.3　新浪网开源软件项目——基于Nginx的NCACHE网页缓存系统

第3部分　实战篇

第10章　Nginx在国内知名网站中的应用案例

10.1　Nginx反向代理与负载均衡类网站应用案例

10.2　Nginx＋PHP类网站应用案例

10.3　Nginx视频点播类网站应用案例

第11章　Nginx的非典型应用实例

11.1　用HTTPS（SSL）构建一个安全的Nginx Web服务器

11.2　采用Nginx搭建FLV视频服务器

11.3　Nginx＋PHP＋MySQL在小内存VPS服务器上的优化

11.4　采用Nginx搭建正向代理服务器

第4部分　模块篇

第12章　Nginx的核心模块

12.1　主模块指令

12.2　主模块变量

12.3　事件模块指令

第13章　Nginx的标准HTTP模块

13.1　HTTP的核心模块

13.2　HTTP Upstream模块

13.3　HTTP Access模块

13.4　HTTP Auth Basic模块

13.5　HTTP Autoindex模块

13.6　HTTP Browser模块

13.7　HTTP Charset模块

13.8　HTTP Empty Gif模块

13.9　HTTP Fcgi模块

13.10　geo模块

13.11　Gzip模块

13.12　HTTP Headers模块

13.13　HTTP Index模块

13.14　HTTP Referer模块

13.15　HTTP Limit Zone模块

13.16　HTTP Limit Req模块

13.17　HTTP Log模块

13.18　HTTP Map模块

13.19　HTTP Memcached模块

13.20　HTTP Proxy模块

13.21　HTTP Rewrite模块

13.22　HTTP SSI模块

13.23　HTTP Userid模块

第14章　Nginx的其他HTTP模块

14.1　HTTP Addition模块

14.2　Embedded Perl模块

14.3　Flv Stream模块

14.4　HTTP Gzip Static模块

14.5　HTTP Random Index模块

14.6　HTTP Geo IP模块

14.7　HTTP RealIp模块

14.8　HTTP SSL模块

14.9　HTTP Stub Status模块

14.9.1　stub_status指令

14.10　HTTP Sub模块

14.11　HTTP Dav模块

14.12　Google Perftools模块

14.13　HTTP XSLT模块

14.14　HTTP Secure Link模块

14.15　HTTP Image Filter模块

第15章　Nginx的邮件模块

15.1　Nginx邮件核心模块

15.2　Nginx邮件认证模块

15.3　Nginx邮件代理模块

15.4　Nginx邮件SSL模块

15.5　Nginx邮件模块配置实例

索引

参考资料

编辑手记

《实战Nginx：取代Apache的高性能Web服务器》读者交流区

勃勃生机，潇洒开源

反侵权盗版声明

实战Nginx：取代Apache的高性能Web服务器

张宴

就职于北京金山软件公司，系金山游戏官方网站——逍遥网（xoyo.com）系统架构师，技术支持部平台组组长。曾在新浪网、赶集网等公司任系统工程师、系统架构师，工作内容主要涉及：服务器系统架构设计与部署、系统运维与调优、网络故障解决、网站后端及接口类PHP程序开发、Unix开源软件二次开发、服务器监控系统开发、系统运维与平台研发团队管理。

博文视点　与您分享思考的乐趣，共同成长。

Broadview®

www.broadview.com.cn

专业的心　体贴的心

实战Nginx：

取代Apache的高性能Web服务器

张宴　著

電子工業出版社

Publishing House of Electronics Industry

北京·BEIJING

内容简介

Nginx是俄罗斯人Igor Sysoev编写的一款高性能的HTTP和反向代理服务器。Nginx选择了epoll和kqueue作为网络I/O模型，在高连接并发的情况下，内存、CPU等系统资源消耗非常低，运行稳定。

本书系统介绍了Nginx与PHP、Ruby、Python结合的使用方法，Nginx作为反向代理与负载均衡的配置与优化，以及Nginx模块的开发方法，并给出了新浪播客、搜狐博客、六间房、Discuz！官方论坛、迅雷在线、赶集网使用Nginx的应用示例。最后全面分析了Nginx的核心模块。

本书适合Nginx的初学者，以及有一定基础，希望深入掌握Nginx的网站架构师和Web开发人员。

未经许可，不得以任何方式复制或抄袭本书之部分或全部内容。

版权所有，侵权必究。

图书在版编目（CIP）数据

实战Nginx：取代Apache的高性能Web服务器／张宴著．—北京：电子工业出版社，2010.3

ISBN 978-7-121-10247-9

Ⅰ．实…　Ⅱ．张…　Ⅲ．网络服务器　Ⅳ．TP368.5

中国版本图书馆CIP数据核字（2010）第010245号

策划编辑：徐定翔

责任编辑：周　筠

出版发行：电子工业出版社

北京市海淀区万寿路173信箱　　邮编　100036

开　　本：787×980　1/16　　印张：22　　字数：430千字

印　　次：2011年12月第4次印刷

印　　数：2000册　　　　　定价：55.00元

凡所购买电子工业出版社图书有缺损问题，请向购买书店调换。若书店售缺，请与本社发行部联系，联系及邮购

电话：（010）88254888。

质量投诉请发邮件至zlts@phei.com.cn，盗版侵权举报请发邮件至dbqq@phei.com.cn。

服务热线：（010）88258888。

完整诠释Nginx

Nginx（“engine x”）是一款高性能的HTTP和反向代理服务器，它因极高的执行效率及简单灵活的配置，被越来越多互联网企业所青睐。在短短的两三年时间内，Nginx快速地传遍了国内Web开发领域，本书作者张宴在其中起了重要的推动作用。

两年前，张宴作为新浪播客的系统工程师，开始测试应用由Lgor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的Nginx。在新浪播客每天数亿访问量的网站上，张宴进行了半年多的测试，Nginx数倍于Apache的并发支持，以及高效快捷的反应能力，让我们对它有了百分之一万的信心。因此在新浪内部大规模推广应用，在小的IDC节点做软F5七层交换，替代Apache作高性能Web服务器，使用Ncache替代Squid，等等，做了一系列尝试和推广，取得了非常好的成绩，为公司节约了大量的服务器等系统运维开销。我作为该项目的负责人，作为张宴的领路人，对这个刚毕业不久的工程师所取得的成就不得不刮目相看。

张宴用在新浪一年多的工作时间，通过反复内部测试，以及在新浪播客、博客等海量访问网站平台上的实际应用测试，熟练掌握了Nginx的配置、优化、开发方面的经验。并且通过他的个人博客（http://blog.s135.com）予以发布，用通俗易懂的文档与Nginx爱好者及业内专家进行交流沟通，积累了众多的解决方案和经验，可谓是业界Nginx应用的集大成。据了解网易目前采用了大量由张宴总结的Nginx解决方案。

《实战Nginx：取代Apache的高性能Web服务器》一书，可谓张宴对Nginx应用的经验和方案的总结，他用通俗易懂的例子，向读者完整诠释Nginx作为高性能服务器和反向代理服务器的用法。本书提供多种海量访问的解决方案，可以让读者少走弯路，帮企业节省服务器等硬件开支，是大型网站必备工具书，也是中小网站开发者必备的学习书籍。

我作为10多年互联网的资深从业者，向读者郑重推荐此书！

余建煊

原新浪播客高级技术经理

第九城市平台总监

2009年12月于上海

分享Nginx的实战经验

在国内谈到Nginx不得不说一下本书作者张宴，初期Nginx的相关资料并不是很多，且Nginx在国内的应用基本为零。张宴经过自己的摸索、学习、测试且结合实际的效果，归纳并总结了相关经验，在自己的博客（http://blog.s135.com）上与大家分享、交流。随着大家对Nginx逐渐了解，Nginx也越来越被大家重视，目前国内已有众多大型网站使用该项技术，如新浪、网易、搜狐、校内、开心、金山逍遥等。张宴为Nginx在国内的推广及应用起到了极其重要的作用，被业内称为“国内Nginx第一人”。

2008年年底张宴加入了金山逍遥网，作为逍遥网技术部平台组组长，张宴带领组员重新设计了逍遥网的系统架构并加以实施。新系统架构用Nginx替换了原来所有的Apache服务器，既减少了服务器数量和带宽，又提高了整个平台的性能及易维护性。逍遥网全新的系统架构，充分展现了Nginx处理高并发的能力和易维护等特性。而且由于Nginx的开放性，根据实际的工作需要，逍遥网以Nginx扩展方式开发了很多底层功能，实现了业务需求。

《实战Nginx：取代Apache的高性能Web服务器》是一本难得的Nginx图书，无论你是一名系统工程师、系统架构师还是一名LAMP架构下的技术人员，该书都是不可多得的一手资料。书中凝聚了张宴工作中总结出来的实战经验，并以真实解决方案为例，配备了大量的实例代码和丰富的注释。

最后，本人作为张宴的同事、朋友，作为一个在一线奋斗了多年的技术人员，向大家郑重推荐此书！

张鹏翼

金山逍遥网技术部经理

2010年1月于北京

不可多得的Nginx一手资料

2008年正值赶集网高速发展阶段，用户量直线上升，原先构建的Apache服务器集群经常遇到访问瓶颈。张宴加入赶集网后，带来了他之前在新浪使用Nginx的经验和测试数据，使我们对Nginx充满期待，决定把服务器移植到Nginx平台。原来Apache使用的上百行rewrite规则，非常方便地修改为Nginx支持的代码。加上前端完善的squid平台支持，效果非常明显，系统平台迅速稳定下来。移植过程前后，也出现了很多意想不到的问题，当初互联网上Nginx资料非常稀缺，张宴以他对Nginx孜孜不倦的钻研，逐个攻关解决，为公司节约了大量的系统运维开支。看到系统的变化，我作为负责人和见证者，对他是由衷的赞赏。

张宴通过在赶集网主站平台使用Nginx，非常熟练掌握了Nginx的配置、优化，以及常见问题的解决办法，并积累了众多的经验和解决方案。他撰写了几十篇关于Nginx配置优化及常见问题的博客文章，现已经成为网上流传最广的技术资料之一，提起Nginx，几乎无人不知道张宴的大名。现正值Nginx在中国风靡之时，这本《实战Nginx：取代Apache的高性能Web服务器》，正是众多Nginx爱好者、使用者梦寐以求之作。据我所知，国内目前使用Nginx的知名网站有：六间房、Discuz！、互联星空播客、水木社区、网易新闻、酷6网、豆瓣网、新华网RSS订阅频道、迅雷安全中心、腾讯3G下载，等等。

作为张宴的同事和朋友，抢先拜读《实战Nginx：取代Apache的高性能Web服务器》后非常欣喜，书中总结了大量Nginx应用的经验和方案，包括赶集网全部线上解决方案，是不可多得的一手资料。阅读本书，能让你少走弯路，迅速成长为高级Nginx系统管理人员，同时本书也是广大Nginx爱好者及系统管理人员的必备工具书。

强烈推荐工作在一线的Linux系统管理人员和即将加入系统管理大军的有志之士阅读此书，让你的职业之路更上一层楼。

李　静

原赶集网技术总监

互动在线运维经理

2010年1月于北京

联系博文视点

您可以通过如下方式与本书的出版方取得联系。

读者信箱：reader@broadview.com.cn

投稿信箱：bvtougao@gmail.com

北京博文视点资讯有限公司（武汉分部）

湖北省　武汉市　洪山区　吴家湾　邮科院路特1号　湖北信息产业科技大厦1402室

邮政编码：430074

电　　话：027-87690813

传　　真：027-87690595

欢迎您访问博文视点官方博客：http://blog.csdn.net/bvbook

序　言

我的网站系统架构之路

我最早接触计算机是在1995年，上小学四年级的时候。当时父亲单位买了一台386计算机（DOS操作系统+UCDOS汉字环境+WPS文字处理软件），用于打字和打印文件。我每天课余时间都会抽空去玩这台计算机，利用DOS中自带的QBASIC语言编写非常简单的小程序，从那时起我就对计算机产生了浓厚的兴趣。之后的几年内，先后接触了Windows95/98/2000操作系统，并在Windows 98上搭建了PWS个人网站服务器，在Windows 2000上搭建了ⅡS网站服务器。2000年，初三毕业的那个暑假，我第一次接触互联网，做了自己的第一个纯静态HTML个人主页。高一时，我利用网上提供的免费主页空间，做了一个本地的门户网站。2003年高考结束后的那个假期，我花65元购买了国际域名s135.com、150元购买虚拟主机，创办了一个采用ASP语言开发的国际经济贸易资讯类网站——商资网（现在已关闭）。

2003年，我进入中南民族大学学习。由于高中我学的是文科，填志愿时不能选择计算机类专业，于是我选择了经济学院的国际经济与贸易专业。尽管如此，我对计算机和网络的兴趣依旧不减，开始学习Linux系统和PHP语言。由于具有一些网站制作知识，我进入了经济学院学生会的信息部，开发维护所在院系的网站。之后，又进入了学校党委宣传部下属的网络媒体“民大在线”，从事网站PHP开发与系统运维工作。后来，基于Linux+Apache+MySQL+PHP平台为学校招生就业工作处开发了“就业信息网”，并接触到了IBM高端服务器。接下来的日子，我为学校的多个部门开发、维护网站，为了便于演示网站，我编写了一键搭建Apache+PHP+MySQL服务器平台的软件“APMServ”。最后，我为学校网络中心兼职维护学校的主Web服务器，开发虚拟主机管理平台，接触到了HP刀片服务器和磁盘阵列。学校的兼职工作为我日后工作打下了比较扎实的基础。

2007年1月，大四下学期为实习阶段，我进入新浪网互动社区事业部播客产品部工作。新浪播客于2006年12月20日刚上线，我加入播客团队的时候，它正处于高速发展时期，网站PV快速增长，Apache+PHP动态应用服务器的负载日益增大。而在Web服务器的负载均衡方面，由于一对F5 BIG-IP硬件负载均衡交换机要服务新浪网的多个产品，七层交换须要耗费F5 BIG-IP不少的CPU资源，而F5 BIG-IP四层交换有专门的硬件芯片来处理，耗费的资源较少，所以，在新浪，F5 BIG-IP一般只用四层负载均衡。但是，URL过滤、转发、重定向及添加x-forwarded-for头等功能，只有七层负载均衡才能实现。在这种背景下，我测试了来自俄罗斯的开源Nginx服务器，其并发支持能力高于Apache数倍，处理速度高效快捷、稳定性也极高，于是，在领导的支持下，逐步采用了Nginx+PHP（FastCGI）取代了Apache+PHP服务器，采用Nginx负载均衡代替F5 BIG-IP进行软七层负载均衡，为公司节约了大量的服务器及系统运维开销。我2007年9月开始撰写的《Nginx+PHP（FastCGI）搭建胜过Apache十倍的Web服务器》系列文章，作为国内最早详细介绍Nginx+PHP安装、配置、使用的资料之一，为推动Nginx在国内的发展起到了积极作用。2008年4月～10月在赶集网工作期间，完成赶集网主站所有Web服务器从Apache+PHP到Nginx+PHP的迁移，单台服务器的CPU平均占用率由70％～80％降低到30％～40％，系统负载由11～16降低到2～5。2008年11月至今，我在金山软件网游公司逍遥网担任架构师期间，将Web负载均衡服务器、Web缓存服务器、PHP动态应用服务器集群、Flash FLV视频播放服务器等，全面采用Nginx。2009年9月3日14:30，金山软件刚公测不久的大型3D武侠网游《剑侠情缘网络版叁》临时维护，暂停服务1小时，大量玩家上游戏官网，论坛、评论、客服等动态应用Nginx服务器集群，访问人数比平时峰值激增数倍，每台服务器的Nginx活动连接数达到2.8万，仍然能够正常提供服务，这也是我至今遇到的Nginx生产环境最高并发值。目前，Nginx已经在新浪、搜狐、网易、腾讯等门户网站，以及豆瓣、六间房、酷6网、开心网、人人网、YUPOO相册、迅雷看看、金山逍遥网、金山爱词霸等Web 2.0网站得到广泛应用，越来越受到大家的喜爱。

撰写本书的背景

近期，新浪、搜狐、网易、腾讯、金山、TOM、中华网、赛尔网络、上海九城等知名互联网公司的系统工程师、网络工程师招聘信息中，都加上了一条对Nginx配置管理经验的要求。Nginx作为新兴的Web服务器，目前的发展势头迅猛，已经在众多知名网站的各项产品中取代Apache。但是，Nginx相关的中文资料却比较欠缺，目前还没有关于Nginx服务器的任何书籍，这也使得一些朋友对于是否采用Nginx取代Apache犹豫不决。本书就是为对Nginx服务器实践应用感兴趣的读者准备的，适用于以前没有接触过Nginx，或者对Nginx有一些了解并希望能够进一步深入，以及对Nginx有较多研究，希望共同探讨的专业系统工程师、个人网站站长及一切Linux/Unix从业人员。

本书的主要内容

Nginx（“engine x”）是俄罗斯人Igor Sysoev编写的一款高性能的HTTP和反向代理服务器。Nginx选择了epoll和kqueue作为网络I/O模型，在高连接并发的情况下，Nginx是Apache服务器不错的替代品，它能够支持高达50000个并发连接数的响应，运行稳定，且内存、CPU等系统资源消耗非常低。

本书主要分为4个部分，第1部分为基础篇，介绍了Nginx服务器的安装与配置方法；第2部分为进阶篇，重点介绍了Nginx的配置优化方法、Nginx与PHP/JSP/ASP.NET/Perl的结合配置方法、Nginx HTTP反向代理与负载均衡的配置与优化、Nginx的Rewrite规则、Nginx的Web缓存服务、Nginx模块开发等，最后还分析了新浪的开源软件项目——基于Nginx的NCACHE网页缓存系统；第3部分为实战篇，分析了Nginx在国内知名网站（如新浪播客、金山逍遥网等）中的应用案例，以及Nginx在Flash FLV视频点播、小内存VPS服务器上的优化等内容；第4部分为模块篇，对Nginx的各项模块进行了集中介绍，可以作为参考手册来翻阅。

致谢

在本书的编写过程中，得到了家人、同事和朋友的大力支持，在此我表示由衷的感谢。感谢老婆对我的支持与鼓励，感谢余建煊、李静、张鹏翼等朋友为本书作序，以及给予的帮助。感谢前新浪播客刘博、郑宇、姜源、李雅敏、宋健等朋友，以及现在金山逍遥网技术支持部所有同事在研究Nginx及日常工作中给我的支持与帮助。此外，还要感谢吴捷（第九城市）及不知名的网友给予的意见和建议。

最后，要感谢在本书的编写过程中，博文视点的徐定翔、白爱萍、陈元玉等编辑给予的帮助与支持。

示例代码下载

如果您需要书中的示例代码，请移步至：

http://blog.s135.com/book/nginx/code/

作者联系方式

由于自身能力有限，书中难免存在错误与疏漏，如果读者发现哪儿存在错误，或者有什么想法和意见想交流，可以通过E-mail或在我博客留言，与我联系。

个人博客：http://blog.s135.com

E-mail：net@s135.com

张　宴

北京金山软件　金山游戏（KSG）-逍遥网　系统架构师

2010年1月

第1部分

基础篇

第1章

Nginx简介

1.1　常用的Web服务器简介

Web服务器也称为WWW（WORLD WIDE WEB）服务器、HTTP服务器，其主要功能是提供网上信息浏览服务。

Unix和Linux平台下的常用Web服务器有Apache、Nginx、Lighttpd、Tomcat、IBM WebSphere等，其中应用最广泛的是Apache。而Windows NT/2000/2003平台下最常用的服务器则是微软公司的IIS（Internet Information Server）。

1.1.1　Apache服务器

Apache仍然是世界上用得最多的Web服务器，市场占有率达60％左右。它源于NCSAhttpd服务器，在NCSA WWW服务器项目停止后，那些使用NCSA WWW服务器的人们开始交换用于此服务器的补丁，这也是Apache名称的由来（pache补丁）。世界上很多著名的网站都是Apache的用户，它的优势主要在于源代码开放、有一支开放的开发队伍、支持跨平台的应用（可以运行在几乎所有的Unix、Windows、Linux系统平台上），以及其可移植性等。Apache的模块支持非常丰富，虽在速度、性能上不及其他轻量级Web服务器，但是属于重量级产品，所消耗的内存也比其他Web服务器要高。

官方网站：http://httpd.apache.org/。

1.1.2　Lighttpd服务器

Lighttpd是由一个德国人写的开源软件，其目标是提供一个专门针对高性能网站，安全、快速、兼容性好并且灵活的Web Server环境。它具有内存开销低、CPU占用率低、效能好，以及模块丰富等特点。支持FastCGI、CGI、Auth、输出压缩（output compress）、URL重写及Alias等重要功能。Lighttpd跟Nginx一样，也是一款轻量级Web服务器，是Nginx的竞争对手之一。

官方网站：http://www.lighttpd.net/。

1.1.3　Tomcat服务器

Tomcat是一个开放源代码、运行servlet和JSP Web应用软件的基于Java的Web应用软件容器。Tomcat Server是根据servlet和JSP规范执行的，因此也可以说Tomcat Server实行了Apache-Jakarta规范，且比绝大多数商业应用软件服务器要好。但是，Tomcat对静态文件、高并发的处理比较弱。

官方网站：http://tomcat.apache.org。

1.1.4　IBM WebSphere服务器

WebSphere Application Server是一种功能完善、开放的Web应用程序服务器，是IBM电子商务计划的核心部分，它基于Java的应用环境，建立、部署和管理Internet和Intranet Web应用程序。这一整套产品目前已进行了扩展，以适应Web应用程序服务器的需要，范围从简单到高级，直到企业级。据IBM官方网站介绍，有10000多个企业正在使用IBM WebSphere，相对于其他流行的Web服务器而言，应用的数量很少。

官方网站：http://www.ibm.com/developerworks/cn/websphere/。

1.1.5　Microsoft IIS

Microsoft的Web服务器产品为Internet Information Server（IIS），IIS是允许在公共Intranet或Internet上发布信息的Web服务器。它是目前最流行的Web服务器产品，很多著名的网站都是建立在IIS平台上的。IIS提供了一个图形界面的管理工具，称为Internet服务管理器，可用于监视配置和控制Internet服务。

IIS是一种Web服务组件，其中包括Web服务器、FTP服务器、NNTP服务器和SMTP服务器，分别用于网页浏览、文件传输、新闻服务和邮件发送等方面，它使得在网络（包括互联网和局域网）上发布信息成了一件很容易的事。它提供ISAPI（Intranet Server API）作为扩展Web服务器功能的编程接口；同时，它还提供一个Internet数据库连接器，可以实现对数据库的查询和更新。

IIS只能运行在Microsoft Windows平台、Linux/Unix平台上，因此须要购买商业的Windows Server操作系统。

1.2　Nginx的发展

Nginx（“engine x”）是俄罗斯人Igor Sysoev（伊戈尔·塞索耶夫）编写的一款高性能的HTTP和反向代理服务器。Nginx能够选择高效的epoll（Linux 2.6内核）、kqueue（FreeBSD）、eventport（Solaris 10）作为网络I/O模型，在高连接并发的情况下，Nginx是Apache服务器不错的替代品，它能够支持高达50000个并发连接数的响应，而内存、CPU等系统资源消耗却非常低，运行非常稳定。

Nginx已经在俄罗斯最大的门户网站——Rambler Media（www.rambler.ru）上运行了3年时间，同时俄罗斯超过20％的虚拟主机平台采用Nginx作为反向代理服务器。

在国内，已经有新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz！官方论坛、水木社区、豆瓣、YUPOO相册、海内SNS、迅雷在线等多家网站使用Nginx作为Web服务器或反向代理服务器。

图1-1是Netcraft公司统计的从1995年8月至2009年1月各Web服务器的市场占有率曲线图。

图1-1　Web服务器的市场占有率曲线图

2009年1月，对185497213个网站进行了抽样调查，发现除去Google自己开发的仅供自己使用的GWS、GFE服务器外，排在前两位的分别是Apache、Microsoft IIS，而Nginx已经超过Lighttpd，位居第三，详见表1-1。

表1-1　Nginx的市场占有率排名

1.3　选择Nginx的理由

选择Nginx有如下一些理由。

1.3.1　它可以高并发连接

官方测试Nginx能够支撑5万并发连接，在实际生产环境中可支撑2～4万并发连接数。这得益于Nginx使用了最新的epoll（Linux 2.6内核）和kqueue（freebsd）网络I/O模型，而Apache使用的则是传统的select模型，其比较稳定的Prefork模式为多进程模式，需要经常派生子进程，所消耗的CPU等服务器资源要比Nginx高得多。

笔者曾完成6台Web Server从Apache到Nginx服务器的迁移（这6台Web Server搭建的是一个日均2500万PV的分类信息网站，迁移前每台服务器的平均系统负载为50～60、CPU使用率为70％～90％，迁移后平均系统负载为1～4，CPU使用率为20％～40％，见图1-2。

图1-2　迁移到Nginx后的系统负载与CPU使用率图

由此可见，处理大量连接的读写，Apache所采用的select网络I/O模型非常低效。

Libevent（一个事件触发的网络库，适用于Windows、Linux、bsd等多种平台，内部使用select、epoll、kqueue等系统调用管理事件机制）的一张测试结果图，对select、epoll、kqueue等作了清晰的对比，结果自然是epoll（Linux 2.6内核）和kqueue（freebsd）胜出，见图1-3。

图1-3　epoll、kqueue、select等网络I/O模型性能测试对比图

图1-4显示了在实际的生产环境中，Nginx支撑高达28000的活动并发连接数。

图1-4　生产环境下的Nginx活动并发连接数据统计图

1.3.2　内存消耗少

Nginx＋PHP（FastCGI）服务器在3万并发连接下，开启的10个Nginx进程消耗150MB内存（15MB×10＝150MB），开启的64个php-cgi进程消耗1280MB内存（20MB×64＝1280MB），加上系统自身消耗的内存，总共消耗不到2GB的内存。如果服务器内存较小，完全可以只开启25个php-cgi进程，这样php-cgi消耗的总内存数才500MB。用Webbench做压力测试，在3万并发连接下，访问Nginx＋PHP（FastCGI）服务器的PHP程序，运行速度仍然飞快。

在实际的生产环境下，两台Nginx＋PHP5（FastCGI）服务器运行多个复杂性一般的纯PHP动态程序，从Nginx的日志可以统计出，单台Nginx＋PHP5（FastCGI）服务器处理PHP动态程序的能力已经超过“700次请求／秒”（见图1-5），相当于每天可以承受6000万（700×60×60×24＝60480000）的访问量，而服务器的系统负载也不算高（见图1-6）。

图1-5　生产环境下的Nginx＋PHP动态程序处理速度统计图

图1-6　生产环境下的Nginx＋PHP系统负载与CPU使用率图

以下是这两台服务器的配置清单及运行的程序说明：

服务器①：DELL PowerEdge 1950（两个Intel（R）Xeon（R）双核CPU 5120 ＠ 1.86GHz，4GB内存）。

服务器②：DELL PowerEdge 1950（一个Intel（R）Xeon（R）双核CPU 5140 ＠ 2.33GHz，4GB内存）。

Web服务器：CentOS Linux 4.4＋Nginx 0.5.35＋PHP 5.2.6RC2（300 FastCGI Procees，unix-domain socket，with XCache）。

PHP程序内容：大量Memcached读写操作，少量MySQL读操作，大量文件队列写操作。

请求数统计方式：从Nginx访问日志中，统计每分钟的第15秒共有多少条日志记录。

同等硬件环境下，Nginx的处理能力相当于Apache的5～10倍。

1.3.3　成本低廉

购买F5 BIG-IP、NetScaler等硬件负载均衡交换机需要十多万甚至几十万人民币。而Nginx为开源软件，采用的是2-clause BSD-like协议，可以免费使用，并且可用于商业用途。

BSD开源协议是一个给使用者很大自由的协议。协议指出可以自由使用、修改源代码，也可以将修改后的代码作为开源或专有软件再发布。当你发布使用了BSD协议的代码，或者以BSD协议代码为基础做二次开发时，须满足三个条件：

（1）如果再发布的产品中包含源代码，则源代码中必须带有原来代码中的BSD协议。

（2）如果再发布的是二进制类库／软件，则需要在类库／软件的文档和版权声明中包含原来代码中的BSD协议。

（3）不可以用开源代码的作者／机构名字和原来产品的名字做市场推广。

BSD代码鼓励代码共享，但须尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码，也允许使用或在BSD代码上开发商业软件，并进行发布和销售，因此它是对商业集成很友好的协议。很多的公司、企业在选用开源产品的时候都会首选BSD协议，因为可以完全控制这些第三方的代码，在必要的时候可以修改或二次开发。

Nginx所采用的2-clause BSD-like license衍生自BSD协议，也就是删掉了BSD协议的第3个条件——“不可以用开源代码的作者／机构名字和原来产品的名字做市场推广”。

1.3.4　其他理由

配置文件非常简单

网络跟程序一样通俗易懂，即使非专业系统管理员也能看懂。

支持Rewrite重写规则

能够根据域名、URL的不同，将HTTP请求分到不同的后端服务器群组。

内置的健康检查功能

如果Nginx Proxy后端的某台Web服务器宕机了，不会影响前端访问。

节省带宽

支持GZIP压缩，可以添加浏览器本地缓存的Header头。

稳定性高

用于反向代理，宕机的概率微乎其微。

支持热部署

Nginx支持热部署。它的启动特别容易，并且几乎可以7天×24小时不间断地运行，即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下，对软件版本进行升级。

1.4　Nginx与Apache、Lighttpd的综合对比

表1-2是Nginx与Apache、Lighttpd的综合对比情况。

表1-2　Nginx与Apache、Lighttpd的综合对比

通过表1-2可以看出，Nginx在反向代理、Rewrite规则、稳定性、静态文件处理、内存消耗等方面，表现出了很强的优势，选用Nginx取代传统的Apache服务器，将会获得多方面的性能提升。

第2章

Nginx服务器的安装与配置

2.1　安装Nginx服务器所需要的系统资源

Nginx是开源软件，您可以从其官方网站（http://www.nginx.net/）下载最新版本。Nginx目前有3个版本：旧的稳定版（0.6.x）、最新的稳定版（0.7.x）和开发版（0.8.x）。0.8.x开发版分支刚发布不久，Bug会比较多，因此不建议用于生产环境。开发版一旦更新稳定下来，就会被加入稳定版分支。然而，新功能不一定会被加到旧的稳定版中去，所以，目前最合适使用的版本是0.7.x。

从0.7.52版本开始，Nginx官方网站开始提供Windows版本下载，Windows版本的Nginx使用比较简单，只须下载完成后，将其解压缩到一个不包含空格的路径中，执行nginx.exe即可。但是，Windows版本的Nginx性能要比Linux/Unix版本的Nginx差很多。本书重点介绍Linux环境下的Nginx编译安装。

一些Linux发行版和BSD的各个变种版本的安装包仓库中包含了编译后的二进制Nginx软件，很多预先编译好的安装包都比较陈旧，所以大多数情况下还是推荐直接从源码编译安装。

安装Nginx服务器之前，首先要安装一个Linux/Unix操作系统发行版，例如Redhat、CentOS、Debian、Fedora Core、Gentoo、SUSE、Ubuntu、FreeBSD等。

本书将以新浪、搜狐、网易、金山游戏官网等国内互联网公司最常用的Linux发行版——CentOS为例，介绍Nginx的安装与使用。CentOS是基于RedHat Enterprise Linux源代码重新编译、去除RedHat商标的产物，各种操作、使用和RedHat没有区别。CentOS完全免费，修正了RedHat的很多BUG，但CentOS不向用户提供技术支持，也不负任何商业责任。

编译Nginx的要求如下：

磁盘空间：需要保证有10MB以上的剩余磁盘空间。Nginx安装完毕后会占据4MB左右的磁盘空间，实际的磁盘空间需求会因编译设置和是否安装第三方模块而有所不同。

GCC编译器及相关工具：GCC全称为GNU Compiler Collection，是GNU社区推出的功能强大、性能优越的用于编程开发的自由编译器，是GNU的代表作品之一，目前可以编译的语言包括：C、C++、Objective-C、Fortran、Java等。您必须确保您的操作系统安装有GCC编译器。另外，您还必须安装Autoconf和Automake工具，它们用于自动创建功能完善的Makefile，当前大多数软件包都是用这一工具生成Makefile的，Nginx也不例外。在CentOS系统下，您可以使用yum命令安装GCC编译器及相关工具：

模块依赖性：Nginx的一些模块需要其他第三方库的支持，例如gzip模块需要zlib库，rewrite模块需要pcre库，ssl功能需要openssl库等。同样，如果是在CentOS系统下，我们可以使用yum命令安装或下载源码包编译安装这些模块依赖的库：

2.2　Nginx的下载

您可以访问http://www.nginx.net／网站，该网站中的以下三行内容分别提供了Nginx 0.6.x、0.7.x、0.8.x三个版本分支的源码包或Windows二进制文件下载。

The development stable versions are nginx-0.8.x, nginx/Windows-0.8.x, the change log

The latest stable versions are nginx-0.7.x, nginx/Windows-0.7.x, the change log

The latest legacy stable version is nginx-0.6.x, the change log

如果您希望在Windows上运行Nginx，你可以点击链接“nginx/Windows-0.8.x”或“nginx/Windows-0.7.x”下载Windows下的二进制版ZIP压缩包。如果您希望在Linux/Unix环境下运行Nginx，您可以点击链接“nginx-0.8.x”、“nginx-0.7.x”、“nginx-0.6.x”下载以tar.gz格式压缩源码包。

2.3　Nginx的安装

Nginx从0.7.52版本开始有了官方的Windows版本，所以这里分别介绍Nginx在Windows下和Linux下的安装步骤。

2.3.1　Nginx在Windows环境下的安装

Nginx在Windows下的安装比较简单，将下载下来的nginx-O.x.xx.zip文件解压缩到一个不包含空格的路径中，例如d:\nginx，然后在“开始”→“运行”→“cmd”中执行以下DOS命令即可启动Nginx：

如果要对启动的Nginx进程进行控制，可以使用DOS命令：

2.3.2　Nginx在Linux环境下的安装

Nginx在Linux环境下可以通过编译源码的方式来安装，最简单的安装命令如下：

按照以上命令，Nginx将被默认安装到/usr/local/nginx目录下。您可以通过./configure --help命令查看Nginx可选择的编译选项。

Nginx的configure脚本支持以下选项：

--prefix=<path>——Nginx安装路径。如果没有指定，默认为/usr/local/nginx。

--sbin-path=<path>——Nginx可执行文件安装路径。只能安装时指定，如果没有指定，默认为<prefix>/sbin/nginx。

--conf-path=<path>——在没有给定-c选项下默认的nginx.conf的路径。如果没有指定，默认为<prefix>/conf/nginx.conf。

--pid-path=<path>——在nginx.conf中没有指定pid指令的情况下，默认的Nginx.pid的路径。如果没有指定，默认为<prefix>/logs/nginx.pid。

--lock-path=<path>——nginx.lock文件的路径。

--error-log-path=<path>——在nginx.conf中没有指定error_log指令的情况下，默认的错误日志的路径。如果没有指定，默认为<prefix>/logs/error.log。

--http-log-path=<path>——在nginx.conf中没有指定access_log指令的情况下，默认的访问日志的路径。如果没有指定，默认为<prefix>/logs/access.log。

--user=<user>——在nginx.conf中没有指定user指令的情况下，默认的Nginx使用的用户。如果没有指定，默认为nobody。

--group=<group>——在nginx.conf中没有指定user指令的情况下，默认的Nginx使用的组。如果没有指定，默认为nobody。

--builddir=DIR——指定编译的目录。

--with-rtsig_module——启用rtsig模块。

--with-select_module（--without_select_module）——允许或不允许开启SELECT模式，如果configure没有找到更合适的模式，比如：kqueue（sun os）、epoll（linux kenel 2.6+）、rtsig（实时信号）或／dev/poll（一种类似select的模式，底层实现与SELECT基本相同，都是采用轮训方法），SELECT模式将是默认安装模式。

--with-poll_module（--without-poll_module）——允许或不允许开启POLL模式，如果没有更合适的模式，比如：kqueue（sun os）、epoll（linux kenel 2.6+），则可以开启。

--with-http_ssl_module——开启HTTP SSL模块，使Nginx可以支持HTTPS请求。这个模块需要已经安装OPENSSL，在DEBIAN上是libssl。

--with-http_realip_module——启用ngx_http_realip_module。

--with-http_addition_module——启用ngx_http_addition_module。

--with-http_sub_module——启用ngx_http_sub_module。

--with-http_dav_module——启用ngx_http_dav_module。

--with-http_flv_module——启用ngx_http_flv_module。

--with-http_stub_status_module——启用“server status”页。

--without-http_charset_module——禁用ngx_http_charset_module。

--without-http_gzip_module——禁用ngx_http_gzip_module。如果启用，需要zlib。

--without-http_ssi_module——禁用ngx_http_ssi_module。

--without-http_userid_module——禁用ngx_http_userid_module。

--without-http_access_module——禁用ngx_http_access_module。

--without-http_auth_basic_module——禁用ngx_http_auth_basic_module。

--without-http_autoindex_module——禁用ngx_http_autoindex_module。

--without-http_geo_module——禁用ngx_http_geo_module。

--without-http_map_module——禁用ngx_http_map_module。

--without-http_referer_module——禁用ngx_http_referer_module。

--without-http_rewrite_module——禁用ngx_http_rewrite_module。如果启用，需要PCRE。

--without-http_proxy_module——禁用ngx_http_proxy_module。

--without-http_fastcgi_module——禁用ngx_http_fastcgi_module。

--without-http_memcached_module——禁用ngx-http_memcached_module。

--without-http_limit_zone_module——禁用ngx_http_limit_zone_module。

--without-http_empty_gif_module——禁用ngx_http_empty_gif_module。

--without-http_browser_module——禁用ngx_http_browser_module。

--without-http_upstream_ip_hash_module——禁用ngx_http_upstream_ip_hash_module。

--with-http_perl_module——启用ngx_http_perl_module。

--with-perl_modules_path=PATH——指定perl模块的路径。

--with-perl=PATH——指定perl执行文件的路径。

--http-log-path=PATH——指定http默认访问日志的路径。

--http-client-body-temp-path=PATH——指定http客户端请求缓存文件存放目录的路径。

--http-proxy-temp-path=PATH——指定http反向代理缓存文件存放目录的路径。

--http-fastcgi-temp-path=PATH——指定http FastCGI缓存文件存放目录的路径。

--without-http——禁用HTTP server。

--with-mail——启用IMAP4/POP3/SMTP代理模块。

--with-mail_ssl_module——启用ngx_mail_ssl_module。

--with-cc=PATH——指定C编译器的路径。

--with-cpp=PATH——指定C预处理器的路径。

--with-cpu-opt=CPU——为特定的CPU编译，有效的值包括：pentium、pentiumpro、pentium3、pentium4、athlon、opteron、amd64、sparc32、sparc64、ppc64。

--without-pcre——禁止PCRE库的使用。同时也会禁止HTTP rewrite模块。在“location”配置指令中的正则表达式也需要PCRE。

--with-pcre=DIR——指定PCRE库的源代码的路径。

--with-pcre-opt=OPTIONS——设置PCRE的额外编译选项。

--with-md5=DIR——设置MD5库的源代码路径。

--with-md5-opt=OPTIONS——设置MD5库的额外编译选项。

--with-md5-asm——使用MD5汇编源码。

--with-sha=DIR——设置sha1库的源代码路径。

--with-sha1-opt=OPTIONS——设置sha1库的额外编译选项。

--with-sha1-asm——使用sha1汇编源码。

--with-zlib=DIR——设置zlib库的源代码路径。

--with-zlib-opt=OPTIONS——设置zlib库的额外编译选项。

--with-zlib-asm=CPU——zlib针对CPU的优化，合法的值是：pentium、pentiumpro。

--with-openssl=DIR——设置OpenSSL库的源代码路径。

--with-openssl-opt=OPTIONS——设置OpenSSL库的额外编译选项。

--with-debug——启用调试日志。

--add-module=PATH——添加一个在指定路径中能够找到的第三方模块。

在不同版本间，选项可能会有些许变化，请总是使用./configure--help命令来检查当前的选项列表。

一个自定义编译选项的示例如代码2-1所示：

代码2-1

2.4　Nginx的启动、停止、平滑重启

在Linux下，Nginx服务主要的操作就是启动、停止和平滑重启。

2.4.1　Nginx的启动

启动Nginx，可以执行以下命令。假设Nginx安装在/usr/local/nginx/目录中，那么启动Nginx的命令就是：

参数“-c”指定了配置文件的路径，如果不加“-c”参数，Nginx会默认加载其安装目录的conf子目录中的nginx.conf文件，在本例中即：/usr/local/nginx/sbin/nginx/conf/nginx.conf。

2.4.2　Nginx的停止

Nginx的停止方法有很多种，一般通过发送系统信号给Nginx主进程的方式来停止Nginx。

我们可以通过ps命令来查找Nginx的主进程号：

这时候屏幕会显示如图2-1所示的信息。

图2-1　查看Nginx进程ID

从图2-1中可以看到，1个Nginx进程的备注信息为“master process”，表示它为主进程，另外的4个进程备注信息为“worker process”，表示它们为子进程。28881为主进程号。

如果在nginx.conf配置文件中指定了pid文件存放的路径（例如：pid/usr/local/webserver/nginx/logs/nginx.pid；），该文件中存放的就是Nginx当前的主进程号。如果没有指定pid文件存放的路径，nginx.pid文件默认存放在Nginx安装目录的logs目录下。所以，我们可以直接通过以下命令来完成平滑重启，省下寻找Nginx主进程号的步骤：

（1）从容停止Nginx。

或

（2）快速停止Nginx。

或

（3）强制停止所有Nginx进程。

2.5　Nginx的平滑重启

如果改变了Nginx的配置文件（nginx.conf），想重启Nginx，同样可以通过发送系统信号给Nginx主进程的方式来进行。不过，重启之前，要确认Nginx配置文件（nginx.conf）的语法是正确的，否则Nginx将不会加载新的配置文件。通过以下命令可以判断Nginx配置文件是否正确：

如果配置文件不正确，屏幕将会提示配置文件的第几行出错：

[emerg]: unknown directive "abc" in/usr/local/webserver/nginx/conf/nginx.conf:55

configuration file/usr/local/webserver/nginx/conf/nginx.conf test failed

如果配置文件正确，屏幕将提示以下两行信息：

the configuration file/usr/local/webserver/nginx/conf/nginx.conf syntax is ok

configuration file/usr/local/webserver/nginx/conf/nginx.conf test is successful

这时候，就可以平滑重启Nginx了。

当Nginx接收到HUP信号时，它会尝试先解析配置文件（如果指定配置文件，就使用指定的，否则使用默认的），如果成功，就应用新的配置文件（例如，重新打开日志文件或监听的套接字）。之后，Nginx运行新的工作进程并从容关闭旧的工作进程。通知工作进程关闭监听套接字，但是继续为当前连接的客户提供服务。所有客户端的服务完成后，旧的工作进程被关闭。如果新的配置文件应用失败，Nginx将继续使用旧的配置进行工作。

2.6　Nginx的信号控制

在上一节中，我们使用了信号来控制Nginx停止、平滑重启，Nginx支持以下几种信号：

·　TERM，INT快速关闭；

·　QUIT从容关闭；

·　HUP平滑重启，重新加载配置文件；

·　USR1重新打开日志文件，在切割日志时用途较大；

·　USR2平滑升级可执行程序；

·　WINCH从容关闭工作进程。

2.7　Nginx的平滑升级

当需要将正在运行中的Nginx升级、添加／删除服务器模块时，可以在不中断服务的情况下，使用新版本、重编译的Nginx可执行程序替换旧版本的可执行程序。步骤如下：

（1）使用新的可执行程序替换旧的可执行程序，对于编译安装的Nginx，可以将新版本编译安装到旧版本的Nginx安装路径中。替换之前，您最好备份一下旧的可执行文件。

（2）发送以下指令：

（3）旧版本Nginx的主进程将重命名它的.pid文件为.oldbin（例如：/usr/local/webserver/nginx/logs/nginx.pid.oldbin），然后执行新版本的Nginx可执行程序，依次启动新的主进程和新的工作进程。

（4）此时，新、旧版本的Nginx实例会同时运行，共同处理输入的请求。要逐步停止旧版本的Nginx实例，你必须发送WINCH信号给旧的主进程，然后，它的工作进程就将开始从容关闭：

（5）一段时间后，旧的工作进程（worker process）处理了所有已连接的请求后退出，仅由新的工作进程来处理输入的请求了：

（6）这时候，我们可以决定是使用新版本，还是恢复到旧版本：

kill-HUP旧的主进程号：Nginx将在不重载配置文件的情况下启动它的工作进程；

kill-QUIT新的主进程号：从容关闭其工作进程（worker process）

kill-TERM新的主进程号：强制退出；

kill新的主进程号或旧的主进程号：如果因为某些原因新的工作进程不能退出，则向其发送kill信号。

新的主进程退出后，旧的主进程会移除.oldbin前缀，恢复为它的.pid文件，这样，一切就都恢复到升级之前了。如果尝试升级成功，而你也希望保留新的服务器时，可发送QUIT信号给旧的主进程，使其退出而只留下新的服务器运行：

第2部分

进阶篇

第3章

Nginx的基本配置与优化

3.1　Nginx的完整配置示例

Nginx的配置文件默认在Nginx程序安装目录的conf二级目录下，主配置文件为nginx.conf，假设您的Nginx安装在/usr/local/webserver/nginx/目录下，那么默认的主配置文件则为/usr/local/webserver/nginx/nginx.conf，代码3-1是Nginx作为Web Server的完整配置示例。

代码3-1

通过上面的nginx.conf配置文件示例，可以看出，nginx.conf的配置文件结构主要由以下几部分构成（见代码3-2）。

代码3-2

下一节笔者会详细介绍Nginx虚拟主机的配置。

3.2　Nginx的虚拟主机配置

3.2.1　什么是虚拟主机

虚拟主机使用的是特殊的软硬件技术，它把一台运行在因特网上的服务器主机分成一台台“虚拟”的主机，每台虚拟主机都可以是一个独立的网站，可以具有独立的域名，具有完整的Internet服务器功能（WWW、FTP、Email等），同一台主机上的虚拟主机之间是完全独立的。从网站访问者来看，每一台虚拟主机和一台独立的主机完全一样。

利用虚拟主机，不用为每个要运行的网站提供一台单独的Nginx服务器或单独运行一组Nginx进程。虚拟主机提供了在同一台服务器、同一组Nginx进程上运行多个网站的功能。

在Nginx配置文件（nginx.conf）中，一个最简化的虚拟主机配置如代码3-3所示。

代码3-3

跟Apache一样，Nginx也可以配置多种类型的虚拟主机：一是基于IP的虚拟主机，二是基于域名的虚拟主机，三是基于端口的虚拟主机。

3.2.2　配置基于IP的虚拟主机

Linux、FreeBSD操作系统都允许添加IP别名。IP别名背后的概念很简单：可以在一块物理网卡上绑定多个IP地址。这样就能够在使用单一网卡的同一个服务器上运行多个基于IP的虚拟主机。设置IP别名也非常容易，只须配置系统上的网络接口，让它监听额外的IP地址。在Linux系统上，可以使用标准的网络配置工具（比如ifconfig和route命令）添加IP别名。以下是添加IP别名的示例：

先用ifconfig命令查看该服务器的IP地址。下面这台服务器有一块物理网卡设备eth0和本地回环设备lo，eth0的IP地址为192.168.8.42，本地回环lo的IP地址为127.0.0.1。

本地回环代表设备的本地虚拟接口，所以默认被看作是永远不会宕掉的接口。它的主要作用有两个：一是测试本机的网络配置，能PING通127.0.0.1说明本机的网卡和IP协议安装都没有问题；另一个作用是某些SERVER/CLIENT的应用程序在运行时须调用服务器上的资源，一般要指定SERVER的IP地址，但当该程序要在同一台机器上运行且没有别的SERVER时，就可以把SERVER的资源装在本机上，SERVER的IP地址设为127.0.0.1也同样可以运行，如代码3-4所示。

代码3-4

如果要在eth0网卡设备上添加两个IP别名192.168.8.43和192.168.8.44，可以通过以下的ifconfig和route命令来进行：

这时，再执行ifconfig命令，就可以看到eth0网卡设备上绑定了两个IP别名，如代码3-5所示。

代码3-5

这时候，从另外一台服务器Ping 192.168.8.43和192.168.8.44两个IP，如果能够Ping通，则证明配置无误。但是，通过ifconfig和route配置的IP别名在服务器重启后会消失，不过可以将这两条ifconfig和route命令添加到/etc/rc.local文件中，让系统开机时自动运行，以下是相关命令：

在文件末尾增加以下内容，然后保存即可：

下面开始配置基于IP的虚拟主机。无论是通过IP别名在一台服务器上配置多个IP地址，还是通过多块网卡在服务器上配置多个IP地址，在Nginx中都能将其配置成为基于IP的虚拟主机。

接下来在Nginx配置文件（nginx.conf）中，分别对192.168.8.43、192.168.8.44、192.168.8.45三个IP配置三个纯静态HTML支持的虚拟主机，如代码3-6所示。

代码3-6

从上面的配置文件中可以看出，一段server{......}就是一个虚拟主机，如果要配置多个虚拟主机，建立多段server{}配置即可，非常方便。监听的IP和端口也可以不写IP地址，只写端口，把它配置成“listen80”，则表示监听该服务器上所有IP的80端口，可通过server_name区分不同的虚拟主机。

3.2.3　配置基于域名的虚拟主机

基于域名的虚拟主机是最常见的一种虚拟主机。只需配置你的DNS服务器，将每个主机名映射到正确的IP地址，然后配置Nginx服务器，令其识别不同的主机名就可以了。这种虚拟主机技术，使很多虚拟主机可以共享同一个IP地址，有效解决了IP地址不足的问题。所以，如果没有特殊要求使你必须用一个基于IP的虚拟主机，最好还是使用基于域名的虚拟主机。

接下来配置基于域名的虚拟主机。在以下的示例中，配置了三个虚拟主机，第一个虚拟主机表示所有对域名aaa.domain.com的访问都由它来处理，第二个虚拟主机表示所有对域名bbb.otherdomain.com的访问都由它来处理，第三个虚拟主机表示对域名www.domain.com、domain.com，以及除了aaa.domain.com之外的所有*.domain.com二级域名的访问都由它来处理。每个虚拟主机的网页文件分别存放在了不同的目录中，每个虚拟主机使用了不同的日志文件来记录访问日志，如代码3-7所示。

代码3-7

3.3　Nginx的日志文件配置与切割

在上一节的Nginx虚拟主机配置中，已经使用access_log进行了日志记录，这一节中，笔者将详细介绍Nginx访问日志文件的配置。

与Nginx日志相关的指令主要有两条，一条是log_format，用来设置日志的格式，另外一条是access_log，用来指定日志文件的存放路径、格式和缓存大小。两条指令在Nginx配置文件中的位置可以在http{......}之间，也可以在虚拟主机之间，即server{......}两个大括号之间。

3.3.1　用log_format指令设置日志格式

log_format指令用来设置日志的记录格式，它的语法如下：

其中name表示定义的格式名称，format表示定义的格式样式。log_format有一个默认的、无须设置的combined日志格式设置，相当于Apache的combined日志格式，其具体参数如下：

您也可以自定义一份日志的记录格式，不过要注意，log_format指令设置的name名称在Nginx配置文件中是不能重复的。

假设将Nginx服务器作为Web服务器，位于负载均衡设备、Squid、Nginx反向代理之后，就不能获取到客户端的真实IP地址了。原因是经过反向代理后，由于在客户端和Web服务器之间增加了中间层，因此Web服务器无法直接拿到客户端的IP，通过$remote_addr变量拿到的将是反向代理服务器的IP地址。但是，反向代理服务器在转发请求的HTTP头信息中，可以增加X-Forwarded-For信息，用以记录原有的客户端IP地址和原来客户端请求的服务器地址。

这时候，就要用log_format指令来设置日志格式，让日志记录X-Forwarded-For信息中的IP地址，即客户的真实IP。例如，创建一个名为mylogformat的日志格式，再用$http_x_forwarded_for变量记录用户的X-Forwarded-For IP地址：

在日志格式样式中，变量$remote_addr和$http_x_forwarded_for用于记录IP地址；$remote_user用于记录远程客户端用户名称；$time_local用于记录访问时间与时区；$request用于记录请求URL与HTTP协议；$status用于记录请求状态，例如成功时状态为200，页面找到时状态为404；$body_bytes_sent用于记录发送给客户端的文件主体内容大小；$http_referer用于记录是从哪个页面链接访问过来的；$http_user_agent用于记录客户端浏览器的相关信息。

采用日志格式combined记录的日志格式如代码3-8所示。

代码3-8

3.3.2　用access_log指令指定日志文件存放路径

用log_format指令设置了日志格式之后，需要用access_log指令指定日志文件存放路径。access_log指令的语法如下：

其中path表示日志文件的存放路径，format表示使用log_format指令设置的日志格式的名称，buffer=size表示设置内存缓冲区的大小，例如可以设置buffer=32k。

（1）如果不想记录日志，可以使用以下指令关闭日志记录：

（2）如果想使用默认的combined格式的日志记录，可以使用以下示例：

或者

（3）如果想使用自定义格式的日志记录，可以使用以下示例，其中的mylogformat是日志格式名称：

（4）在Nginx0.7.4之后的版本中，access_log指令中的日志文件路径可以包含变量，例如：

假设server_name指令设置的虚拟主机名称为test.domain.com，那么access_log指令将把访问日志记录在/data1/logs/test.domain.com.log文件中。

如果日志文件路径中含有变量，将存在以下一些限制：

（1）Nginx进程设置的用户和组必须有对该路径创建文件的权限。假设Nginx的user指令设置的用户名和用户组都是www，而/data1/logs/目录的用户名和用户组为root，日志文件/data1/logs/test.domain.com.log将无法被Nginx创建；

（2）缓冲将不会被使用；

（3）对于每一条日志记录，日志文件都将先打开文件，再写入日志记录，然后马上关闭。为了提高包含变量的日志文件存放路径的性能，须要使用open_log_file_cache指令设置经常被使用的日志文件描述符缓存。

open_log_file_cache指令主要用来设置含有变量的日志路径的文件描述符缓存，它的语法如下：

该指令默认是禁止的，等同于：

open_log_file_cache指令的各项参数说明如下：

max：设置缓存中的最大文件描述符数量。如果超过设置的最大文件描述符数量，则采用LRU（Least Recently Used）算法清除“较不常使用的文件描述符”。LRU（Least Recently Used）算法的基本概念是：当内存缓冲区剩余的可用空间不够时，缓冲区尽可能地先保留使用者最常使用的数据，将最近未使用的数据移出内存，腾出空间来加载另外的数据。

inactive：设置一个时间，如果在设置的时间内没有使用此文件描述符，则自动删除此描述符。此参数为可选参数，默认的时间为10秒钟。

min_uses：在参数inactive指定的时间范围内，如果日志文件超过被使用的次数，则将该日志文件的描述符记入缓存。默认次数为1。

valid：设置多长时间检查一次，看一看变量指定的日志文件路径与文件名是否仍然存在。默认时间为60秒。

off：禁止使用缓存。

open_log_file_cache指令的设置示例如下：

3.3.3　Nginx日志文件的切割

生产环境中的服务器，由于访问日志文件增长速度非常快，日志太大会严重影响服务器效率。同时，为了方便对日志进行分析计算，须要对日志文件进行定时切割。定时切割的方式有按月切割、按天切割、按小时切割等。最常用的是按天切割。

Nginx不支持像Apache一样使用cronolog来轮转日志，但是可以采用以下方式来实现日志文件的切割：

首先通过mv命令将日志文件重命名为/data1/logs/20090318.log，然后发送kill-USR1信号给Nginx的主进程号，让Nginx重新生成一个新的日志文件/data1/logs/access.log。如果nginx.conf配置文件中使用了“pid/usr/local/webserver/nginx/nginx.pid；”指令，指定了pid文件的存放路径，我们可以通过cat这个pid文件获得Nginx的主进程号，命令如下：

如果想每天定时切割日志，还须要借助crontab。我们可以写一个按天切割的日志，按年、月份目录存放日志的shell脚本：

输入以下内容并保存（见代码3-9）：

代码3-9

另外，配置crontab每天凌晨00:00定时执行这个脚本：

输入以下内容并保存：

这个shell脚本和crontab配置主要实现的功能为：假设今天的日期为2009年5月19日，Nginx当前的日志文件为/data1/logs/access.log，2009年5月20日00:00会执行cut_nginx_log.sh脚本，cut_nginx_log.sh脚本首先创建一个目录/data1/logs/2009/05/，然后将/data1/logs/access.log文件移动并重命名为/data1/logs/2009/05/access_20090519.log，再发送kill-USR1信号给Nginx主进程号，告诉Nginx重新生成一个/data1/logs/access.log文件，2009年5月20日的日志记录在这个新生成的日志文件中。而/data1/logs/2009/05/access_20090519.log文件，就是2009年5月19日的日志文件。

3.4　Nginx的压缩输出配置

gzip（GNU-ZIP）是一种压缩技术。经过gzip压缩后页面大小可以变为原来的30％甚至更小。这样，用户浏览页面的时候速度会快得多。gzip的压缩页面需要浏览器和服务器双方都支持，实际上就是服务器端压缩，传到浏览器后浏览器解压并解析。浏览器那里不需要我们担心，因为IE、Firefox、Opera、谷歌Chrome等绝大多数浏览器都支持解析gzip过的页面。

Nginx的压缩输出由一组gzip压缩指令来实现。我们从示例入手，来学习gzip压缩输出。gzip压缩输出的相关指令位于http{......}两个大括号之间：

gzip各指令的语法和使用方法请查阅本书第13章第13.11节的gzip模块。

3.5　Nginx的自动列目录配置

我们经常会看到一些开源软件的下载页面是能够自动列目录的，这一功能Apache可以实现，Nginx同样可以实现，前提条件是当前目录下不存在用index指令设置的默认首页文件。如果须要在某一虚拟主机的location / {......}目录控制中配置自动列目录，只须加上如下代码：

另外，还有两项跟自动列目录相关的指令，分别为：

设定索引时文件大小的单位（B、KB、MB或GB）

开启以本地时间来显示文件时间的功能。默认为关（GMT时间）。

3.6　Nginx的浏览器本地缓存设置

浏览器缓存（Browser Caching）是为了加速浏览，浏览器在用户磁盘上对最近请求过的文档进行存储，当访问者再次请求这个页面时，浏览器就可以从本地磁盘显示文档，这样就可以加速页面的阅览。缓存的方式节约了网络的资源，提高了网络的效率。

浏览器缓存可以通过expires指令输出Header头来实现，expires指令的语法如下：

语法：expires [time|epoch|max|off]

默认值：expires off

作用域：http，server，location

用途：使用本指令可以控制HTTP应答中的“Expires”和“Cache-Control”的Header头信息（起到控制页面缓存的作用）。

可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的time值来获得。

epoch指定“Expires”的值为1 January，1970，00:00:01 GMT。

max指定“Expires”的值为31 December 2037 23:59:59 GMT，“Cache-Control”的值为10年。-1指定“Expires”的值为服务器当前时间-1s，即永远过期。

“Cache-Control”头标的值由您指定的时间来决定。

负数：Cache-Control: no-cache。

正数或零： Cache-Control: max-age=#，#为您指定时间的秒数。

“off”表示不修改“Expires”和“Cache-Control”的值。

假设一个HTML页面中会引用一些JavaScript文件、图片文件，而这些格式的文件很少会被修改，则可以通过expires设置浏览器缓存。

例：对常见格式的图片、Flash文件在浏览器本地缓存30天，对js、css文件在浏览器本地缓存1小时，如代码3-10所示。

代码3-10

第4章

Nginx与PHP（FastCGI）的安装、配置与优化

在互联网服务器架构中，我们经常可以听到LAMP（Linux+Apache+Mysql+Perl/PHP/Python）架构。LAMP这个特定名词最早出现在1998年。当时，Michael Kunze为德国计算机杂志《c't》写作的一篇关于自由软件如何成为商业软件替代品的文章时，创建了LAMP这个名词，用来指代Linux操作系统、Apache网络服务器、MySQL数据库和PHP（Perl或Python）脚本语言的组合（由4种技术开头的字母组成）。由于IT世界众所周知的对缩写的爱好，Michael Kunze提出的LAMP这一术语很快就被市场接受。O'Reilly和MySQL AB更是在英语人群中推广普及了这个术语。随之LAMP技术成了开源软件业的一盏真正的明灯。

虽然这些开放源代码程序本身并不是专门设计成同另外几个程序一起工作的，但由于它们都是影响较大的开源软件，拥有很多共同特点，这就导致了这些组件经常在一起使用。在过去的几年里，这些组件的兼容性不断完善，在一起应用的情形变得更加普遍。并且它们为了改善不同组件之间的协作，已经创建了某些扩展功能。目前，几乎在所有的Linux发布版中都默认包含了这些产品。Linux操作系统、Apache服务器、MySQL数据库和Perl、PHP或Python语言，这些产品共同组成了一个强大的Web应用程序平台。

现在，由于Nginx拥有超越Apache的卓越性能，LAMP架构正在逐渐被LNMP架构所取代。LNMP即为我们本章详细介绍的Linux+Nginx+Mysql+PHP架构。本章我们将一步步学习Nginx与PHP（FastCGI）的安装、配置与优化。

提高PHP（FastCGI），那么FastCGI是什么呢？

FastCGI是语言无关的、可伸缩架构的CGI开放扩展，其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知，CGI解释器的反复加载是CGI性能低下的主要原因，如果CGI解释器保持在内存中并接受FastCGI进程管理器调度，则可以提供良好的性能、伸缩性、Fail-Over特性等。

FastCGI的工作原理是：

（1）FastCGI进程管理器自身初始化，启动多个CGI解释器进程（多个php-cgi进程）并等待来自Web Server的连接。在本文中，采用PHP-FPM进程管理器启动多个php-cgi FastCGI进程。启动php-cgi FastCGI进程时，可以配置以TCP和UNIX套接字两种方式启动。

（2）当客户端请求到达Web服务器（Nginx）时，Web服务器将请求采用TCP协议或UNIX套接字方式转发到FastCGI主进程，FastCGI主进程选择并连接到一个CGI解释器（子进程）。Web服务器将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。

（3）FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web服务器（Nginx）。当FastCGI子进程关闭连接时，请求便告知处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器的下一个连接。而在一般的普通CGI模式中，php-cgi在此便退出了。

所以，你可以想象普通的CGI模式有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重新初始化全部数据结构。使用FastCGI，所有这些都只在进程启动时发生一次。一个额外的好处是，持续数据库连接（Persistent database connection）可以工作。

PHP FastCGI的优点：

（1）PHP脚本运行速度更快。PHP解释程序被载入内存而不用每次需要时从存储器读取，此举极大提升了依靠脚本运行站点的性能。

（2）须要使用的系统资源更少。由于服务器不用在每次需要时都载入PHP解释程序，你可以将站点的传输速度提升很多而不必增加CPU负担。

（3）不需要对现有的代码作任何改变。运行在Apache+PHP上的程序，无须修改即可适用于PHP的FastCGI。

接下来，我们开始安装、搭建LNMP（Linux+Nginx+Mysql+PHP）平台。本文中的操作系统环境为：CentOS Linux 5.3（Linux 2.6+内核），另在RedHat AS4上也可安装成功。

4.1　获取相关开源程序

1．【适用CentOS操作系统】

利用CentOS Linux系统自带的yum命令安装、升级所需的程序库（RedHat等其他Linux发行版可从安装光盘中找到这些程序库的RPM包，进行安装）：

2．【适用RedHat操作系统】

RedHat等其他Linux发行版可从安装光盘中找到这些程序库的RPM包（事先可通过类似“rpm-qa|grep libjpeg”的命令查看RPM包是否存在，但通常“xxx-devel”不存在，须要安装）。RedHat可以直接利用CentOS的RPM包安装，以下是RPM包的下载网址：

（1）RedHat AS4 & CentOS 4:

http://mirrors.163.com/centos/4/os/i386/CentOS/RPMS/

http://mirrors.163.com/centos/4/os/x86_64/CentOS/RPMS/

（2）RedHat AS5 & CentOS 5:

http://mirrors.163.com/centos/5/os/i386/CentOS/

http://mirrors.163.com/centos/5/os/x86_64/CentOS/

（3）RPM包搜索网站：

http://rpm.pbone.net/

http://www.rpmfind.net/

（4）RedHat AS4系统环境，通常情况下缺少包安装支持：

Ⅰ.i386系统如代码4-1：

代码4-1

Ⅱ.x86_64系统如代码4-2：

代码4-2

3．【适用CentOS、RedHat及其他Linux操作系统】

下载程序源码包：

本文中提到的所有开源软件为截止到2009年09月18日的最新稳定版。

（1）从软件的官方网站下载如代码4-3：

代码4-3

（2）从blog.s135.com下载（比较稳定，只允许在本站，或者在Linux/Unix下通过Wget、Curl等命令下载以下软件），如代码4-4：

代码4-4

4.2　安装PHP 5.2.10（FastCGI模式）

（1）编译安装PHP5.2.10所需的支持库，代码如4-5所示：

代码4-5

（2）编译安装MySQL5.1.38所需的代码如4-6所示：

代码4-6

如果你想在这台服务器上运行MySQL数据库，则执行以下几步。如果你只是希望让PHP支持MySQL扩展库，能够连接其他服务器上的MySQL数据库，那么，以下几步无须执行。

1）创建MySQL数据库存放目录：

2）以mysql用户账号的身份建立数据表：

3）创建my.cnf配置文件：

输入代码4-7的内容如下：

代码4-7

4）创建管理MySQL数据库的shell脚本：

输入代码4-8的内容（这里的用户名admin和密码12345678接下来的步骤会创建）如下：

代码4-8

5）赋予shell脚本可执行权限：

6）启动MySQL：

7）通过命令行登录管理MySQL服务器（提示输入密码时直接回车）：

8）输入以下SQL语句，创建一个具有root权限的用户（admin）和密码（12345678）：

9）（可选）停止MySQL：

（3）编译安装PHP（FastCGI模式），代码如4-9所示：

代码4-9

（4）编译安装PHP5扩展模块，如代码4-10所示：

代码4-10

（5）修改php.ini文件：

并在此行后增加以下几行，然后保存，如代码4-11所示：

代码4-11

自动修改：若嫌手工修改麻烦，可执行以下shell命令，自动完成对php.ini文件的修改，如代码4-12所示：

代码4-12

（6）配置eAccelerator加速PHP：

按shift+g键跳到配置文件的最末尾，加上以下配置信息，如代码4-13所示：

代码4-13

（7）创建www用户和组，以及供blog.domain.com和www.domain.com两个虚拟主机使用的目录，如代码4-14所示：

代码4-14

（8）创建php-fpm配置文件（php-fpm是为PHP打的一个FastCGI管理补丁，可以平滑变更php.ini配置而无须重启php-cgi）。

在/usr/local/webserver/php/etc/目录中创建php-fpm.conf文件：

输入以下内容（如果您安装Nginx+PHP用于程序调试，请将以下的<value name="display_errors">0</value>改为<value name="display_errors">1</value>，以便显示PHP错误信息，否则，Nginx会报状态为500的空白错误页），如代码4-15所示：

代码4-15

（9）启动php-cgi进程。

监听127.0.0.1的9000端口，进程数为200（如果服务器内存小于3GB，可以只开启64个进程），用户为www：

注：/usr/local/webserver/php/sbin/php-fpm还有其他参数，包括：start|stop|quit|restart|reload|logrotate，修改php.ini后不重启php-cgi，重新加载配置文件使用reload。

4.3　安装Nginx 0.8.15

（1）安装Nginx所需的pcre库：

（2）安装Nginx：

（3）创建Nginx日志目录：

（4）创建Nginx配置文件。

1）在/usr/local/webserver/nginx/conf/目录中创建nginx.conf文件：

输入以下内容，如代码4-16所示：

代码4-16

2）在/usr/local/webserver/nginx/conf/目录中创建fcgi.conf文件：

输入以下内容，如代码4-17所示：

代码4-17

（5）启动Nginx：

4.4　配置开机自动启动Nginx+PHP

用vi编辑器打开文件/etc/rc.local：

在末尾增加以下内容：

4.5　优化Linux内核参数

用vi编辑器打开文件/etc/sysctl.conf：

在末尾增加以下内容，如代码4-18所示：

代码4-18

使配置立即生效：

4.6　在不停止Nginx服务的情况下平滑变更Nginx配置

（1）修改/usr/local/webserver/nginx/conf/nginx.conf配置文件后，请执行以下命令检查配置文件是否正确：

如果屏幕显示以下两行信息，说明配置文件正确：

（2）这时，输入以下命令查看Nginx主进程号：

屏幕显示的即为Nginx主进程号，例如：

这时，执行以下命令即可使修改过的Nginx配置文件生效：

或者无须这么麻烦，找到Nginx的pid文件：

4.7　编写每天定时切割Nginx日志的脚本

（1）创建脚本usr/local/webserver/nginx/sbin/cut_nginx_log.sh：

输入以下内容，如代码4-19所示：

代码4-19

（2）设置crontab，每天凌晨00:00切割nginx访问日志：

输入以下内容：

第5章

Nginx与JSP、ASP.NET、Perl的安装与配置

在上一章，我们已经介绍了Nginx与PHP（FastCGI）的安装、配置与优化。Nginx除了可以与PHP语言配合外，还可以和其他的一些编程语言配合。本章将介绍Nginx与常用的JSP（Tomcat）、ASP.NET（Mono+FastCGI）、Perl（FastCGI）的安装与配置。

5.1　Nginx与JSP（Tomcat）在Linux上的安装、配置

JSP（Java Server Pages）是由Sun Microsystems公司倡导、许多公司一起参与建立的一种动态网页技术标准。JSP技术有点类似ASP技术，它是在传统的网页HTML文件（*.htm, *.html）中插入Java程序段（Scriptlet）和JSP标记（tag），从而形成JSP文件（*.jsp）。使用JSP开发的Web应用是跨平台的，既能在Linux下运行，也能在其他操作系统上运行。

Tomcat是Apache软件基金会（Apache Software Foundation）的Jakarta项目中的一个核心项目，由Apache、Sun和其他一些公司及个人共同开发而成。由于有Sun的参与和支持，最新的Servlet和JSP规范总是能在Tomcat中得到体现，Tomcat5支持最新的Servlet2.4和JSP2.0规范。因为Tomcat技术先进、性能稳定，而且免费，因此深受Java爱好者的喜爱并得到了部分软件开发商的认可，它已成为目前比较流行的Web应用服务器。目前的最新版本是6.0。

JDK（Java Development Kit）是Sun Microsystems针对Java开发员的产品。自Java推出以来，JDK已经成为使用最广泛的Java SDK。JDK是整个Java的核心，包括Java运行环境、Java工具和Java基础的类库。JDK是学好Java的第一步。从SUN的JDK5.0开始，提供了泛型等非常实用的功能，其版本也不断更新，运行效率得到了很大的提高。

5.1.1　Tomcat和JDK的安装

在Linux上，我们首先要安装JDK。JDK 1.6可以在以下网址下载：

下载完成后，修改jdk-6u17-linux-x64.bin的文件属性为可执行，然后执行该程序安装JDK：

按空格键看完协议，当出现提示“Do you agree to the above license terms? [yes or no]”时，输入“yes”。安装完成后，执行以下语句：

在文件末尾增加以下内容：

保存并退出vi后，执行以下命令使配置生效：

安装完成JDK之后，按照以下步骤安装Tomcat二进制版本：

查找appBase="webapps"，修改为appBase="/data0/htdocs/www"，其中/data0/htdocs/www即为您的网页根目录。

安装完成后，启动Tomcat，默认监听的是8080端口：

停止Tomcat可以使用以下命令：

5.1.2　Nginx与Tomcat的配置

nginx.conf配置文件内容如代码5-1所示。在配置文件中，静态HTML网页、图片、JS、CSS、Flash等使用Nginx来处理，以便得到更快的速度，文件扩展名为.jsp、.do的请求，由Nginx反向代理Tomcat HTTP服务器来处理：

代码5-1

启动Nginx：

如果Nginx处于运行状态，也可以使用nginx -t检查nginx.conf配置文件无错误后，使用“kill-HUP Nginx主进程号”来平滑重启Nginx。

Nginx启动后，可以访问以下URL中的JSP示例程序，检查JSP程序能否正常运行：

5.2　Nginx与ASP.NET（Mono+FastCGI）在Linux上的安装、配置

Mono是一个由Novell公司（先前是Ximian）主持的项目。该项目的目标是创建一系列符合标准ECMA（Ecma-334和Ecma-335）的.NET工具，包括C#编译器和共同语言（CL即Common Language）执行平台（Platform）。与微软的.NET不同，Mono项目不仅可以运行于Windows系统内，还可以运行于Linux、FreeBSD、Unix、Mac OS X和Solaris操作系统内，不过，部分Windows上的ASP.NET程序迁移到Linux+Mono平台时须要做一些移植、修改。

Mono项目的官方网站为http://www.mono-project.com/，您可以通过该网站了解Mono的更多信息。

5.2.1　Mono的安装

在CentOS 5 Linux（注：目前只兼容32位系统）上，按照代码5-2中的步骤安装mono：

代码5-2

从SVN版本库安装fastcgi-mono-server，如代码5-3所示：

代码5-3

以FastCGI方式启动fastcgi-mono-server2，监听本机的9001端口，网页根目录为/data0/htdocs/www/：

5.2.2　Nginx与ASP.NET（Mono+FastCGI）的配置

nginx.conf配置文件内容如代码5-4所示。在配置文件中，静态HTML网页、图片、JS、CSS、Flash等使用Nginx来处理，以便得到更快的速度，文件扩展名为.aspx、.asmx、.ashx、.asax、.ascx、.soap、.rem、.axd、.cs、.config、.dll的请求，由Nginx交给fastcgi-mono-server2进程去处理：

代码5-4

启动Nginx：

如果Nginx处于运行状态，也可以使用nginx -t检查nginx.conf配置文件无错误后，使用“kill-HUP Nginx主进程号”来平滑重启Nginx。

Nginx启动后，我们可以在/data0/htdocs/www/目录下下载一个名为info.aspx的ASP.NET探针文件，以检查ASP.NET程序能否正常运行：

通过浏览器访问http://www..yourdomain.com/info.aspx，如果一切正常，则显示的内容如表5-1所示：

表5-1　访问ASP.NET探针显示的部分内容

System Information

Processor Information

Memory Information

5.3　Nginx与Perl（FastCGI）在Linux上的安装、配置

Perl是一种脚本语言，最初的设计者为拉里·沃尔（Larry Wall），Perl语言于1987年12月18日发表。Perl吸取了C、sed、awk、shell scripting及很多其他程序语言的特性。与脚本语言一样，Perl不需要编译器和链接器来运行代码，要做的只是写出程序并告诉Perl来运行而已。这意味着Perl对于小的编程问题的快速解决方案和为大型事件创建原型来测试潜在的解决方案是十分理想的。Perl的解释程序是开放源码的免费软件，使用Perl不必担心费用。Perl能在绝大多数操作系统运行，可以方便地向不同操作系统迁移。

Perl可以采用FastCGI方式与Nginx配合使用。

5.3.1　Perl（FastCGI）的安装

在CentOS 5 Linux上，我们按照以下步骤安装Perl（FastCGI）：

然后输入代码5-5所示的内容：

代码5-5

赋予脚本可执行权限并启动32个Perl-FastCGI进程。FastCGI进程启动后，将监听本机的9002端口。

5.3.2　Nginx与Perl（FastCGI）的配置

nginx.conf配置文件内容如代码5-6所示。在配置文件中，静态HTML网页、图片、JS、CSS、Flash等使用Nginx来处理，以便得到更快的速度，文件扩展名为.perl、.pl、.cgi的请求，由Nginx交给Perl（FastCGI）进程去处理：

代码5-6

启动Nginx：

如果Nginx处于运行状态，也可以使用nginx -t检查nginx.conf配置文件无错误后，使用“kill-HUP Nginx主进程号”来平滑重启Nginx。

Nginx启动后，可以在/data0/htdocs/www/目录下创建一个名为test.cgi的Perl测试文件，来检查Perl程序能否正常运行：

输入以下内容：

然后赋予test.cgi文件可执行权限：

通过浏览器访问http://www..yourdomain.com/test.cgi，如果一切正常，显示的内容如下：

第6章

Nginx HTTP负载均衡和反向代理的配置与优化

6.1　什么是负载均衡和反向代理

随着网站访问量的快速增长，单台服务器已经无法承担大量用户的并发访问，必须采用多台服务器协同工作，以提高计算机系统的处理能力和计算强度，满足当前业务量的需求。而如何在完成同样功能的多个网络设备之间实现合理的业务量分配，使之不会出现一台设备过忙、而其他的设备却没有充分使用的情况。要解决这一问题，可以采用负载均衡的方法。

6.1.1　负载均衡

负载均衡是由多台服务器以对称的方式组成一个服务器集合，每台服务器都具有等价的地位，都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术，将外部发送来的请求均匀分配到对称结构中的某一台服务器上，而接收到请求的服务器独立地回应客户的请求。均衡负载能够平均分配客户请求到服务器阵列，藉此快速获取重要数据，解决大量并发访问服务问题。这种群集技术可以用最少的投资获得接近于大型主机的性能。

6.1.2　反向代理

反向代理（Reverse Proxy）是指以代理服务器来接受Internet上的连接请求，然后将请求转发给内部网络上的服务器，并将从服务器上得到的结果返回给Internet上请求连接的客户端，此时代理服务器对外就表现为一个服务器。

通常的代理服务器，只用于代理内部网络对Internet的连接请求，客户机必须指定代理服务器，并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。由于外部网络上的主机并不会配置并使用这个代理服务器，普通代理服务器也被设计为在Internet上搜寻多个不确定的服务器，而不是针对Internet上多个客户机的请求访问某一个固定的服务器，因此普通的Web代理服务器不支持外部对内部网络的访问请求。当一个代理服务器能够代理外部网络上的主机访问内部网络时，这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器，外部网络就可以简单把它当作一个标准的Web服务器而不需要特定的配置。不同之处在于，这个服务器没有保存任何网页的真实数据，所有的静态网页或CGI程序，都保存在内部的Web服务器上。因此对反向代理服务器的攻击并不会使网页信息遭到破坏，这样就增强了Web服务器的安全性。

反向代理方式和包过滤方式或普通代理方式并无冲突，因此可以在防火墙设备中同时使用这两种方式，其中反向代理用于外部网络访问内部网络时使用，正向代理或包过滤方式用于拒绝其他外部访问方式并提供内部网络对外部网络的访问能力。因此可以结合这些方式提供最佳的安全访问方式。

6.2　常见的Web负载均衡方法

Web负载均衡的方法有很多，下面介绍几种常见的负载均衡方式。

6.2.1　用户手动选择方式

这是一种较为古老的方式，通过在主站首页入口提供不同线路、不同服务器链接的方式，来实现负载均衡。这种方式在一些提供下载业务的网站中比较常见，例如：华军软件园，如图6-1所示。

图6-1　华军软件园的负载均衡方式

6.2.2　DNS轮询方式

大多域名注册商都支持对同一主机名添加多条A记录，这就是DNS轮询，DNS服务器将解析请求按照A记录的顺序，随机分配到不同的IP上，这样就完成了简单的负载均衡。

DNS轮询的成本非常低，在一些不重要的服务上，被经常使用。

图6-2为全球第二大域名注册商——enom的域名Web管理界面，这里我们为api.bz域名添加一个二级域名ntp.api.bz（主机名为ntp），并为该域名添加多条A记录，让其DNS轮询114.80.81.72、218.75.4.130、61.129.66.79、61.153.197.226、114.80.81.1、114.80.81.69 7个IP，用7台服务器来做负载均衡。

图6-2　DNS服务器的Web管理界面

添加完成后，我们用Linux下的dig命令查看ntp.api.bz域名的域名解析情况，如代码6-1所示：

代码6-1

我们可以发现，域名解析正常，A记录有七个IP。每次访问ntp.api.nz域名会被随机解析到其中一个IP上，从而实现负载均衡的目的。

虽然DNS轮询成本低廉，但是，DNS负载均衡存在两个明显的缺点。

1．可靠性低

假设一个域名DNS轮询多台服务器，如果其中的一台服务器发生故障，那么所有的访问该服务器的请求将不会有所回应，这是任何人都不愿意看到的。即使从DNS中去掉该服务器的IP，但在Internet上，各地区电信、网通等宽带接入商将众多的DNS存放在缓存中，以节省访问时间，DNS记录全部生效需要几个小时，甚至更久。所以，尽管DNS轮流在一定程度上解决了负载均衡问题，但是却存在可靠性不高的缺点。

2．负载分配不均衡

DNS负载均衡采用的是简单的轮询负载算法，不能区分服务器的差异，不能反映服务器的当前运行状态，不能做到为性能较好的服务器多分配请求，甚至会出现客户请求集中在某一台服务器上的情况。

DNS服务器是按照一定的层次结构组织的，本地DNS服务器会缓冲已解析的域名到IP地址的映射，这会导致使用该DNS服务器的用户在一段时间内访问的是同一台Web服务器，导致Web服务器间的负载不均衡。

此外，用户本地计算机也会缓存已解析的域名到IP地址的映射。当多个用户计算机都缓存了某域名到IP地址的映射时，而这些用户又继续访问该域名下的网页，这时也会导致不同Web服务器间的负载分配不均衡。

负载不均衡可能导致的后果有：某几台服务器负荷很低，而另几台服务器负荷很高、处理缓慢；配置高的服务器分配到的请求少，而配置低的服务器分配到的请求多。

因此，DNS轮询方式仅适用于一些可靠性要求不高的服务器集群，例如：图片服务器集群、纯静态网页服务器集群等。

6.2.3　四／七层负载均衡设备

由于DNS轮询的缺点，一些对可靠性要求较高的服务器集群，则通过采用四／七层负载均衡设备来实现服务器的负载均衡。

世界上第一个网络体系结构由IBM公司提出（1974年，名为SNA），以后其他公司也相继提出自己的网络体系结构如：Digital公司的DNA，美国国防部的TCP/IP等，多种网络体系结构并存，其结果是若采用IBM的结构，只能选用IBM的产品，只能与同种结构的网络互联。为了促进计算机网络的发展，国际标准化组织ISO于1977年成立了一个委员会，在现有网络的基础上，提出了不基于具体机型、操作系统或公司的网络体系结构，称为开放系统互联模型（OSI，open system interconnection）。

这个模型把网络通信的工作分为七层（可参见图6-3）。一至四层被认为是低层，这些层与数据移动密切相关。五至七层是高层，包含应用程序级的数据。每一层负责一项具体的工作，然后把数据传送到下一层。由低到高具体分为：物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

OSI模型的最低层或第一层：物理层

物理层包括物理连网媒介，实际上就是布线、光纤、网卡和其他用来把两台网络通信设备连接在一起的设施。它规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性及过程特性。虽然物理层不提供纠错服务，但它能够设定数据传输速率并监测数据出错率。

OSI模型的第二层：数据链路层

数据链路层的主要作用是控制网络层与物理层之间的通信。它保证了数据在不可靠的物理线路上进行可靠的传递。它把从网络层接收到的数据分割成特定的可被物理层传输的帧，保证了传输的可靠性。它的主要作用包括：物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。它是独立于网络层和物理层的，工作时无须关心计算机是否正在运行软件还是其他操作。

数据链路层协议的主要内容包括：SDLC、HDLC、PPP、STP、帧中继等。

OSI模型的第三层：网络层

很多用户经常混淆第二层和第三层的界限，简单来说，如果你在谈论一个与IP地址、路由协议或地址解析协议（ARP）相关的问题，那么这就是第三层的问题。

网络层负责对子网间的数据包进行路由选择，它通过综合考虑发送优先权、网络拥塞程度、服务质量及可选路由的花费来决定一个网络中两个节点的最佳路径。另外，它还可以实现拥塞控制、网际互联等功能。

网络层协议的主要内容包括：IP、IPX、RIP、OSPF等。

OSI模型的第四层：传输层

传输层是OSI模型中最重要的一层，它是两台计算机经过网络进行数据通信时，第一个端到端的层次，起到缓冲作用。当网络层的服务质量不能满足要求时，它将提高服务，以满足高层的要求；而当网络层服务质量较好时，它只须进行很少的工作。另外，它还要处理端到端的差错控制和流量控制等问题，最终为会话提供可靠的、无误的数据传输。

传输层协议的主要内容包括：TCP、UDP、SPX等。

在IP协议栈中第四层是TCP（传输控制协议）和UDP（用户数据报协议）所在的协议层。TCP和UDP包含端口号，它可以唯一区分每个数据包包含哪些应用协议（例如HTTP、FTP、telnet等）。TCP/UDP端口号提供的附加信息可以为网络交换机所利用，四层交换机利用这种信息来区分包中的数据，这是第四层交换的基础。

OSI模型的第五层：会话层

会话层负责在网络中的两节点之间建立和维持通信，并保持会话同步，它还决定通信是否中断，以及通信中断时决定从何处重新发送。

OSI模型的第六层：表示层

表示层的作用是管理数据的解密与加密，如常见的系统口令处理，当你的账户数据在发送前被加密，在网络的另一端，表示层将对接收到的数据解密。另外，表示层还要对图片和文件格式信息进行解码和编码。

OSI模型的第七层：应用层

简单来说，应用层就是为操作系统或网络应用程序提供访问网络服务的接口，包括文件传输、文件管理及电子邮件等的信息处理。

应用层协议的代表包括：Telnet、FTP、HTTP、SNMP等。

OSI网络模型如图6-3所示。

图6-3　OSI网络模型

现代负载均衡技术通常操作于OSI网络模型的第四层或第七层。第四层负载均衡将一个Internet上合法注册的IP地址映射为多个内部服务器的IP地址，对每次TCP连接请求动态使用其中一个内部IP地址，达到负载均衡的目的。在第四层交换机中，此种均衡技术得到广泛的应用，一个目标地址是服务器群VIP（虚拟IP，Virtual IP address）连接请求的数据包流经交换机，交换机根据源端和目的IP地址、TCP或UDP端口号和一定的负载均衡策略，在服务器IP和VIP间进行映射，选取服务器群中最好的服务器来处理连接请求。

第七层负载均衡控制应用层服务的内容，提供了一种对访问流量的高层控制方式，适合对HTTP服务器群的应用。第七层负载均衡技术通过检查流经的HTTP报头，根据报头内的信息来执行负载均衡任务。

常见的四／七层负载均衡设备：

1．硬件四／七层负载均衡交换机

硬件四／七层负载均衡交换机的代表有：F5 BIG-IP、Citrix NetScaler、Radware、Cisco CSS、Foundry等产品，这些产品价格不菲，高达几十万元人民币。在中国大陆，采用F5 Network公司的BIG-IP负载均衡交换机的网站（有些网站为部分频道采用）最多，包括：新浪网、雅虎、百度、搜狐、凤凰网、央视国际、中华英才网、猫扑、慧聪网等。

图6-4是一张F5 BIG-IP实现动、静态网页分离的负载均衡架构图，很好地描述了F5 BIG-IP是如何实现四／七层负载均衡的。

图6-4　F5 BIG-IP实现动、静态网页分离的负载均衡架构图

（1）如图，假设域名blog.s135.com被解析到F5的外网／公网虚拟IP：61.1.1.3（vs_squid），该虚拟IP下有一个服务器池（pool_squid），该服务器池下包含两台真实的Squid服务器（192.168.1.11和192.168.1.12）。

（2）如果Squid缓存未命中，则会请求F5的内网虚拟IP：192.168.1.3（vs_apache），该虚拟IP下有一个默认服务器池（pool_apache_default），该服务器池下包含两台真实的Apache服务器（192.168.1.21和192.168.1.22），当该虚拟IP匹配iRules规则时，则会访问另外一个服务器池（pool_apache_irules），该服务器池下同样包含两台真实的Apache服务器（192.168.1.23和192.168.1.24）。

（3）另外，所有真实服务器的默认网关指向F5的自身内网IP，即192.168.1.2。

（4）所有的真实服务器通过SNAT IP地址61.1.1.4访问互联网。

2．软件四层负载均衡

软件四层负载均衡的代表作品为LVS（Linux Virtual Server），作者为曾经在国家并行与分布式处理重点实验室工作，现在已加盟淘宝网的章文嵩博士。LVS是一个开源的软件，可以实现LINUX平台下的简单负载均衡。LVS集群采用IP负载均衡技术和基于内容请求分发技术。调度器具有很好的吞吐率，将请求均衡地转移到不同的服务器上执行，且调度器自动屏蔽掉服务器的故障，从而将一组服务器构成一个高性能的、高可用的虚拟服务器。整个服务器集群的结构对客户是透明的，而且无须修改客户端和服务器端的程序。为此，在设计时要考虑系统的透明性、可伸缩性、高可用性和易管理性。

LVS负载均衡的结构如图6-5所示。

图6-5　LVS负载均衡架构图

3．软件七层负载均衡

软件的七层负载均衡大多基于HTTP反向代理方式，代表产品有Nginx、L7SW（Layer7 switching）、HAProxy等。Nginx的反向代理负载均衡能够很好地支持虚拟主机，可配置性很强，可以按轮询、IP哈希、URL哈希、权重等多种方式对后端服务器做负载均衡，同时还支持后端服务器的健康检查。

6.2.4　多线多地区智能DNS解析与混合负载均衡方式

以新浪首页（www.sina.com.cn）为例，负载均衡同时用到了“多线多地区智能DNS解析、DNS轮询、四／七层负载均衡交换机”等技术。智能DNS解析能够根据用户本地设置的DNS服务器线路和地区，将对同一个域名请求解析到不同的IP上。

例如：当北京电信用户访问www.sina.com.cn时，会被新浪的DNS服务器解析到北京电信机房的IP上；当北京网通用户访问www.sina.com.cn时，会被解析到北京网通机房的IP上；当教育网的用户访问www.sina.com.cn时，会被解析到教育网机房的IP上；当广东电信的用户访问www.sina.com.cn时，会被解析到广州电信机房的IP上；当湖南、湖北的电信用户访问www.sina.com.cn时，会被解析到武汉电信机房的IP上，等等。

将DNS地址设为北京电信的DNS服务器219.141.136.10，通过Linux下的dig命令可以发现，访问www.sina.com.cn被解析到了北京电信的多台服务器的IP上，这属于智能DNS解析+DNS轮询解决负载均衡，如代码6-2所示。

代码6-2

将DNS地址设为北京网通的DNS服务器202.106.0.20，通过Linux下的dig命令可以发现，访问www.sina.com.cn最终被解析到了北京网通的一个IP地址202.108.33.32上，这属于用智能DNS解析+四／七层负载均衡交换机解决负载均衡，该IP地址202.108.33.32是四／七层负载均衡交换机的虚拟IP，如代码6-3所示。

代码6-3

6.3　Nginx负载均衡与反向代理的配置实例

6.3.1　完整的Nginx反向代理示例

完整的Nginx反向代理示例如代码6-4所示。

代码6-4

通过上述示例，我们已经看到Nginx对于多个域名的负载均衡是如何配置的。Upstream指令用于设置一组可以在proxy_pass和fastcgi_pass指令中使用的代理服务器，默认的负载均衡方式为轮询。Upstream模块中的Server指令用于指定后端服务器的名称和参数，服务器的名称可以是一个域名、一个IP地址、端口号或UNIX Socket。

而在server{...}虚拟主机内，可以通过proxy_pass和fastcgi_pass指令设置进行反向代理的upstream服务器集群。

proxy_set_header指令用于在向反向代理的后端Web服务器发起请求时添加指定的Header头信息。

当后端Web服务器上有多个基于域名的虚拟主机时，要通过添加Header头信息Host，用于指定请求的域名，这样后端Web服务器才能识别该反向代理访问请求由哪一个虚拟主机来处理。

使用反向代理之后，后端Web服务器（以PHP为例）就不能直接通过$_SERVER["REMOTE_ADDR"]变量来获取用户的真实IP了，通过$_SERVER["REMOTE_ADDR"]获取的将是Nginx负载均衡服务器的IP。这时，就要通过在Nginx反向代理时添加Header头信息X-Forwarded-For，让后端Web服务器（以PHP为例）能够通过$_SERVER["HTTP_X_FORWARDED_FOR"]获取到用户的真实IP。

6.3.2　Nginx负载均衡与反向代理实现动、静态网页分离

动、静态网页分离，就是让动态PHP等程序网页去访问PHP Web服务器，让缓存页、图片、JavaScript、CSS、Flash去访问Squid等缓存服务器。

在配置Nginx负载均衡与反向代理之前，我们首先来看一看NetScaler等硬件四／七层负载均衡交换机是如何实现负载均衡的，如图6-6所示。

图6-6　NetScaler负载均衡交换机动静分离系统架构图

NetScarler的七层负载均衡是基于TCP的，可以用于Web Server、MySQL数据库、邮件服务器等大多数基于TCP服务器的负载均衡。Nginx的七层负载均衡仅支持HTTP、邮件协议，能够实现Web Server、邮件服务器的负载均衡。在Web服务器集群应用中，可以通过Nginx负载均衡，来实现并代替NetScaler七层负载均衡的部分功能。对于以上的NetScaler负载均衡架构，我们可以用以下的Nginx负载均衡架构来代替其中的Web服务器部分，如图6-7所示。

图6-7　Nginx反向代理负载均衡动静分离系统架构图

6.4　Nginx负载均衡的HTTP Upstream模块

Upstream模块是Nginx负载均衡的主要模块，它提供了一个简单方法来实现在轮询和客户端IP之间的后端服务器负载均衡，并可以对后端服务器进行健康检查。

代码示例如6-5所示：

代码6-5

6.4.1　ip_hash指令

ip_hash

语法：ip_hash

默认值：none

使用环境：upstream

当对后端的多台动态应用服务器做负载均衡时，ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样，当来自某个IP的用户在后端Web服务器A上登录后，再访问该站点的其他URL，能保证其访问的还是后端Web服务器A。如果不采用ip_hash指令，假设来自某个IP的用户在后端Web服务器A上登录后，再访问该站点的其他URL，有可能被定向到后端Web服务器B，C，…上，由于用户登录后SESSION信息是记录在服务器A上的，B，C，…上没有，这时就会提示用户未登录。

使用ip_hash指令无法保证后端服务器的负载均衡，可能有些后端服务器接收到的请求多，有些后端服务器接收到的请求少，而且设置后端服务器权重等方法将不起作用。所以，如果后端的动态应用服务器能够做到SESSION共享，还是建议采用后端服务器的SESSION共享方式来代替Nginx的ip_hash方式。

如果后端服务器有时要从Nginx负载均衡（已使用ip_hash）中摘除一段时间，你必须将其标记为“down”，而不是直接从配置文件中删掉或注释掉该后端服务器的信息。代码示例如6-6：

代码6-6

这样，当原来为4台后端服务器时，摘除backend3.example.com（标记为“down”）后，Nginx仍然会按4台服务器进行哈希。如果直接注释掉“server backend3.example.com”这行，Nginx就会按照3台服务器进行重新哈希，原来被哈希到backendl.example.com的客户端IP有可能被哈希到backend2.example.com服务器上，原有的SESSION就会失效。

6.4.2　server指令

server

语法：server name [parameters]

默认值：none

使用环境：upstream

该指令用于指定后端服务器的名称和参数。服务器的名称可以是一个域名、一个IP地址、端口号或UNIX Socket。

在后端服务器名称之后，可以跟以下参数：

weight=NUMBER——设置服务器的权重，权重数值越高，被分配到的客户端请求数越多。如果没有设置权重，则为默认权重1。

max_fails=NUMBER——在参数fail_timeout指定的时间内对后端服务器请求失败的次数，如果检测到后端服务器无法连接及发生服务器错误（404错误除外），则标记为失败。如果没有设置，则为默认值1。设为数值0将关闭这项检查。

fail_timeout=TIME——在经历参数max_fails设置的失败次数后，暂停的时间。

down——标记服务器为永久离线状态，用于ip_hash指令。

backup——仅仅在非backup服务器全部宕机或繁忙的时候才启用。

示例如下：

6.4.3　upstream指令

upstream

语法：upstream name {...}

默认值：none

使用环境：http

该指令用于设置一组可以在proxy_pass和fastcgi_pass指令中使用的代理服务器，默认的负载均衡方式为轮询。示例如下：

6.4.4　upstream相关变量

从Nginx 0.5.18版本开始，可以支持用log_format指令设置日志格式，日志格式中可以使用变量，例如：

upstream模块拥有以下变量：

$upstream_addr

处理请求的upstream服务器地址。

$upstream_status

Upstream服务器的应答状态。

$upstream_response_time

Upstream服务器响应时间（毫秒），多个响应以逗号和冒号分割。

$upstream_http_$HEADER

任意的HTTP协议头信息，例如：

6.5　Nginx负载均衡服务器的双机高可用

如果将Web服务器集群当作一个城池，那么负载均衡服务器则相当于城门，重要性不言而喻。如果“城门”关闭了，与外界的通道也就掐断了。如果只有一台Nginx负载均衡服务器，当该服务器发生故障时，则会导致整个网站无法访问。因此，我们需要两台以上的Nginx负载均衡服务器，实现故障转移与高可用。

双机高可用一般是通过虚拟IP（也称漂移IP）方式来实现的，基于Linux/Unix的IP别名技术。双机高可用方式目前可分为两种：第一种方式为一台主服务器加一台热备服务器，正常情况下主服务器绑定一个公网虚拟IP，提供负载均衡服务，热备服务器处于空闲状态，当主服务器发生故障时，热备服务器接管主服务器的虚拟IP，提供负载均衡服务；第二种方式为两台负载均衡服务器都处于活动状态，各自绑定一个公网虚拟IP，提供负载均衡服务，当其中一台服务器发生故障时，另一台服务器接管发生故障服务器的虚拟IP。第一种方式较为常见，但始终有一台服务器处于空闲状态，浪费了一台服务器的负载均衡处理能力。第二种方式需要多用一个公网IP，笔者已经在金山游戏官方网站——逍遥网（xoyo.com）线上环境成功使用，能够在正常情况下将两台服务器都用于实际的负载均衡处理。

第一种方式：

（1）www.yourdomain.com域名解析到虚拟IP 61.1.1.2上。

（2）正常情况下，主机61.1.1.4绑定虚拟IP 61.1.1.2。

（3）用户访问www.yourdomain.com（虚拟IP 61.1.1.2）实际访问的是主机61.1.1.4，而备机61.1.1.5则处于空闲状态。

（4）如果主机61.1.1.4发生故障，备机61.1.1.5将在几秒钟内接管虚拟IP 61.1.1.2，与自己绑定，并发送ARPing包给IDC的公网网关刷新MAC地址。

（5）这时，用户访问www.yourdomain.com（虚拟IP 61.1.1.2）实际上访问的是备机61.1.1.5，从而实现故障转移与高可用，避免了单点故障。转移过程如图6-8所示。

图6-8　一台主机配一台备机的可用服务方式

另外，第一种方式还可以利用基于VRRP路由协议的Keepalived软件来实现。

第二种方式：

（1）www.yourdomain.com域名通过DNS轮询解析到虚拟IP 61.1.1.2和61.1.1.3上。

（2）正常情况下，服务器①61.1.1.4绑定虚拟IP 61.1.1.2，服务器②61.1.1.5绑定虚拟IP61.1.1.3。其联结与运行方式如图6-9所示。

图6-9　两台负载均衡服务器的高可用服务方式（正常状态）

在服务器①61.1.1.4上执行以下命令：

在服务器②61.1.1.5上执行以下命令：

（3）用户访问www.yourdomain.com（虚拟IP 61.1.1.2和61.1.1.3）实际上是根据DNS轮询访问两台负载均衡服务器，两台服务器均处于活动状态。

（4）如果服务器①发生故障，服务器②将在几秒钟内接管服务器①的虚拟IP 61.1.1.2，与自己绑定，并发送ARPing包给IDC的公网网关刷新MAC地址。这时，服务器②同时绑定61.1.1.2和61.1.1.3两个虚拟IP，其联结与运行方式如图6-10所示。

图6-10　其中一台负载均衡服务器发生故障的运行方式

在服务器②61.1.1.5上执行以下命令：

我们可以写两个shell脚本，来实现第二种方式的自动故障转移。

以下代码6-7为脚本1（nginx_ha1.sh），部署在Nginx负载均衡服务器①：

代码6-7

在Nginx负载均衡服务器①将脚本驻留后台运行：

以下代码6-8为脚本2（server2.sh），部署在Nginx负载均衡服务器②：

代码6-8

在Nginx负载均衡服务器②将脚本驻留后台运行：

第7章

Nginx的Rewrite规则与实例

7.1　什么是Nginx的Rewrite规则

Rewrite主要的功能就是实现URL的重写，Nginx的Rewrite规则采用PCRE（Perl Compatible Regular Expressions）Perl兼容正则表达式的语法进行规则匹配，如果您需要Nginx的Rewrite功能，在编译Nginx之前，须要编译安装PCRE库。

正则表达式（英文：Regular Expression）在计算机科学中，是指一个用来描述或匹配一系列符合某个句法规则的字符串的单个字符串。最初的正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算（自动控制）的模型和对形式化语言描述与分类的研究。20世纪40年代，Warren McCulloch与Walter Pitts将神经系统中的神经元描述成小而简单的自动控制元。20世纪50年代，数学家斯蒂芬·科尔·克莱尼利用称之为正则集合的数学符号来描述此模型。肯·汤普逊将此符号系统引入编辑器QED，然后是Unix上的编辑器ed，并最终引入grep。自此，正则表达式被广泛使用于各种Unix或类似Unix的工具，例如Perl。

通过Rewrite规则，可以实现规范的URL、根据变量来做URL转向及选择配置。例如，一些使用MVC框架的程序只有一个入口，可以通过Rewrite来实现。一些动态URL地址须要伪装成静态HTML，便于搜索引擎抓取，也需要Rewrite来处理。一些由于目录结构、域名变化的旧URL，须要跳转到新的URL上，也可以通过Rewrite来处理。

7.2　Nginx Rewrite规则相关指令

Nginx Rewrite规则相关指令有if、rewrite、set、return、break等，其中rewrite是最关键的指令。一个简单的Nginx Rewrite规则语法如下：

如果加上if语句，示例如下：

7.2.1　break指令

语法：break

默认值：none

使用环境：server, location, if

该指令的作用是完成当前的规则集，不再处理rewrite指令。

示例如下：

7.2.2　if指令

语法：if (condition) {...}

默认值：none

使用环境：server, location

该指令用于检查一个条件是否符合，如果条件符合，则执行大括号内的语句。if指令不支持嵌套，不支持多个条件&&和Ⅱ处理。

以下信息可以被指定为条件：

（1）变量名，错误的值包括：空字符串＂＂，或者任何以0开始的字符串；

（2）变量比较可以使用“=”（表示等于）和“!=”（表示不等于）运算符；

（3）正则表达式模式匹配可以使用“~*”和“~”符号；

（4）“~”符号表示区分大小写字母的匹配；

（5）“~*”符号表示不区分大小写字母的匹配（例如firefox与FireFox是匹配的）；

（6）“!~”和“!~*”符号的作用刚好和“~”、“!~*”相反，表示不匹配；

（7）“-f”和“!-f”用来判断文件是否存在；

（8）“-d”和“!-d”用来判断目录是否存在；

（9）“-e”和“!-e”用来判断文件或目录是否存在；

（10）“-x”和“!-x”用来判断文件是否可执行。

部分正则表达式可以在圆括号“（）”内，其值可以通过后面的变量$1至$9访问，示例如代码7-1所示：

代码7-1

示例代码7-1中，内置的变量$invalid_referer值由valid_referers指令提供。

7.2.3　return指令

语法：return code

默认值：none

使用环境：server, location, if

该指令用于结束规则的执行并返回状态码给客户端。状态码可以使用这些值：204，400，402～406，408，410，411，413，416及500～504。此外，非标准状态码444将以不发送任何Header头的方式结束连接。

示例，如果访问的URL以“.Sh”和“.Bash”结尾，则返回状态码403：

下面，我们来详细介绍return指令支持的状态码。

204 No Content

服务器成功处理了请求，但无须返回任何实体内容，并且希望返回更新了的元信息。响应可能通过实体头部的形式，返回新的或更新后的元信息。如果存在这些头部信息，则应当与所请求的变量相呼应。

如果客户端是浏览器，那么用户浏览器应保留发送了该请求的页面，而不产生任何文档视图上的变化，即使按照规范新的或更新后的元信息，也应当被应用到用户浏览器活动视图中的文档。

400 Bad Request

由于包含语法错误，当前请求无法被服务器理解。除非进行修改，否则客户端不应该重复提交这个请求。

402 Payment Required

该状态码是为了将来可能的需求而预留的。

403 Forbidden

服务器已经理解请求，但是拒绝执行它。与401响应不同的是，身份验证并不能提供任何帮助，而且这个请求也不应该被重复提交。如果这不是一个HEAD请求，而且服务器希望能够讲清楚为何请求不能被执行，就应该在实体内描述拒绝的原因。当然服务器也可以返回一个404响应，假如它不希望让客户端获得任何信息。

404 Not Found

请求失败，请求所希望得到的资源未在服务器上发现。没有信息能够告诉用户这个状况到底是暂时的还是永久的。假如服务器知道情况，应当使用410状态码来告知旧资源因为某些内部的配置机制问题，已经永久地不可用，而且没有任何可以跳转的地址。404这个状态码被广泛应用于当服务器不想揭示为何请求被拒绝，或者没有其他适合的响应可用的情况下。

405 Method Not Allowed

请求行中指定的请求方法不能被用于请求相应的资源。该响应必须返回一个Allow头信息，用以表示出当前资源能够接受的请求方法的列表。

鉴于PUT，DELETE方法会对服务器上的资源进行写操作，因而绝大部分的网页服务器都不支持或在默认配置下不支持上述请求方法，对于此类请求均会返回405错误。

406 Not Acceptable

请求的资源的内容特性无法满足请求头中的条件，因而无法生成响应实体。

除非这是一个HEAD请求，否则该响应就应当返回一个包含可以让用户或浏览器从中选择最合适的实体特性及地址列表的实体。实体的格式由Content-Type头中定义的媒体类型决定。浏览器可以根据格式及自身能力自行作出最佳选择。但是，规范中并没有定义任何作出此类自动选择的标准。

408 Request Timeout

请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。客户端可以随时再次提交这一请求而无须进行任何更改。

410 Gone

被请求的资源在服务器上已经不再可用，而且没有任何已知的转发地址。这样的状况应当被认为是永久性的。如果可能，拥有链接编辑功能的客户端应当在获得用户许可后删除所有指向这个地址的引用。如果服务器不知道或无法确定这个状况是否是永久的，就应该使用404状态码。除非额外说明，否则这个响应是可缓存的。

410响应的目的主要是帮助网站管理员维护网站，通知用户该资源已经不再可用，并且服务器拥有者希望所有指向这个资源的远端连接也被删除。这类事件在限时、增值服务中很普遍。同样，410响应也被用于通知客户端在当前服务器站点上，原本属于某个个人的资源已经不再可用。当然，是否要把所有永久不可用的资源标记为'410 Gone'，以及是否要保持此标记多长时间，完全取决于服务器拥有者。

411 Length Required

服务器拒绝在没有定义Content-Length头的情况下接受请求。在添加了表明请求消息体长度的有效Content-Length头之后，客户端可以再次提交该请求。

413 Request Entity Too Large

服务器拒绝处理当前请求，因为该请求提交的实体数据大小超过了服务器愿意或能够处理的范围。此种情况下，服务器可以关闭连接以免客户端继续发送此请求。

如果这个状况是临时的，服务器应当返回一个Retry-After的响应头，以告知客户端可以在多少时间以后重新尝试。

416 Requested Range Not Satisfiable

如果请求中包含了Range请求头，并且Range中指定的任何数据范围都与当前资源的可用范围不重合，同时请求中又没有定义If-Range请求头，那么服务器就应当返回416状态码。

假如Range使用的是字节范围，那么这种情况就是指请求指定的所有数据范围的首字节位置都超过了当前资源的长度。服务器也应当在返回416状态码的同时，包含一个Content-Range实体头，用以指明当前资源的长度。这个响应也被禁止使用multipart/byteranges作为其Content-Type。

500 Internal Server Error

服务器遇到了一个未曾预料的状况，导致了它无法完成对请求的处理。一般来说，这个问题都会在服务器的程序码出错时出现。

501 Not Implemented

服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法，并且无法支持其对任何资源的请求时。

502 Bad Gateway

作为网关或代理工作的服务器尝试执行请求时，从上游服务器接收到无效的响应。

503 Service Unavailable

由于临时的服务器维护或过载，服务器当前无法处理请求。这个状况是临时的，并且将在一段时间以后恢复。如果能够预计延迟时间，那么响应中可以包含一个Retry-After头用以标明这个延迟时间。如果没有给出这个Retry-After信息，那么客户端应当以处理500响应的方式处理它。

注意：503状态码的存在并不意味着服务器在过载的时候必须使用它。某些服务器只不过是希望拒绝客户端的连接。

504 Gateway Timeout

作为网关或代理工作的服务器尝试执行请求时，未能及时从上游服务器（URI标识出的服务器，例如HTTP、FTP、LDAP）或辅助服务器（例如DNS）收到响应。

注意：某些代理服务器在DNS查询超时时会返回400或500错误。

7.2.4　rewrite指令

语法：rewrite regex replacement flag

默认值：none

使用环境：server, location, if

该指令根据表达式来重定向URI，或者修改字符串。指令根据配置文件中的顺序来执行。

注意重写表达式只对相对路径有效。如果你想配对主机名，你应该使用if语句，代码如下：

如果替换串以http://开头，将会采用301或302跳转进行URL重定向。

rewrite指令的最后一项参数为flag标记，支持的flag标记有：

·　last——相当于Apache里的[L]标记，表示完成rewrite；

·　break——本条规则匹配完成后，终止匹配，不再匹配后面的规则；

·　redirect——返回302临时重定向，浏览器地址栏会显示跳转后的URL地址；

·　permanent——返回301永久重定向，浏览器地址栏会显示跳转后的URL地址。

在以上的标记中，last和break用来实现URI重写，浏览器地址栏的URL地址不变，但在服务器端访问的路径发生了变化。redirect和permanent用来实现URL跳转，浏览器地址栏会显示跳转后的URL地址。

last和break标记的实现功能类似，但二者之间有细微的差别，使用alias指令时必须用last标记，使用proxy_pass指令时要使用break标记。last标记在本条rewrite规则执行完毕后，会对其所在的server{......}标签重新发起请求，而break标记则在本条规则匹配完成后，终止匹配，不再匹配后面的规则。例如以下这段规则，就必须使用break标记，使用last标记会导致死循环：

因此，一般在根location中（即location/{......}）或直接在server标签中编写rewrite规则，推荐使用last标记，在非根location中（例如location/cms/{......}），则使用break标记。例如：

如果被替换的URI中含有参数（即类似/app/test.php?id=5之类的URI），默认情况下参数会被自动附加到替换串上，你可以通过在替换串的末尾加上？标记来解决这一问题。

下面我们来比较一下，不加？标记和加上？标记的URL跳转区别：

访问http://www.yourdomain.com/test?id=5经过301跳转后的URL地址为http://www.yourdomain.com/home?id=5

访问http://www.yourdomain.com/test?id=5经过301跳转后的URL地址为http://www.yourdomain.com/home

注：对花括号（｛和｝）来说，它们既能用在重定向的正则表达式里，也能用在配置文件里分割代码块，为了避免冲突，正则表达式里如果带花括号，应该用双引号（或者单引号）包围。比如，要将类似以下的URL：

/photos/123456

重定向到：

/path/to/photos/12/1234/123456.png

可以用以下方法（注意双引号）：

7.2.5　set指令

语法：set variable value

默认值：none

使用环境：server, location, if

该指令用于定义一个变量，并给变量赋值。变量的值可以为文本、变量及文本变量的联合。

示例如下：

7.2.6　uninitialized_variable_warn指令

语法：uninitialized_variable_warn onloff

默认值：uninitialized_variable_warn on

使用环境：http, server, location, if

该指令用于开启或关闭记录关于未初始化变量的警告信息，默认值为开启。

7.2.7　Nginx Rewrite可以用到的全局变量

在if、location、rewrite指令中，可以使用以下全局变量：

·　$args

·　$content_length

·　$content_type

·　$document_root

·　$document_uri

·　$host

·　$http_user_agent

·　$http_cookie

·　$limit_rate

·　$request_body_file

·　$request_method

·　$remote_addr

·　$remote_port

·　$remote_user

·　$request_filename

·　$request_uri

·　$query_string

·　$scheme

·　$server_protocol

·　$server_addr

·　$server_name

·　$server_port

·　$uri

7.3　PCRE正则表达式语法

Perl正则表达式源自于Henry Spencer写的regex，它已经演化成了PCRE（Perl兼容正则表达式，Perl Compatible Regular Expressions），一个由Philip Hazel开发的，为很多现代工具所使用的库。在Nginx的rewrite指令的语法中，“rewrite regex replacement flag”之中的regex使用的是PCRE正则表达式。表7-1是在PCRE中元字符及其在正则表达式上下文中行为的一个完整列表。

表7-1　PCRE正则表达式语法一览表

7.4　Nginx的Rewrite规则编写实例

文件和目录不存在时，重定向到某个PHP文件上，适用于WordPress等MVC结构的开源博客系统：

多目录转成参数abc.domian.com/sort/2=>abc.domian.com/index.php?act=sort&name=abc&id=2：

目录对换/123456/xxxx->/xxxx?id=123456：

如果客户端使用IE浏览器，则重定向到/nginx-ie目录下：

禁止访问多个目录：

禁止访问以/data开头的文件：

设置某些类型文件的浏览器缓存时间：

将多级目录下的文件转换成一个文件/job-123-456-789.html指向/job/123/456/789.html：

禁止访问以.sh、.tlv、.mp4为文件名后缀的URL地址：

#适用于Zend Framework的重写规则：

Bo-blog开源PHP博客系统伪静态重写规则，如代码7-2所示：

代码7-2

根据Referer信息防盗链，代码如下：

7.5　Nginx与Apache的Rewrite规则实例对比

7.5.1　简单的Nginx与Apache Rewrite规则

一般情况下，简单的Nginx和Apache Rewrite规则区别不大，基本上能够完全兼容。例如：

Apache Rewrite规则，代码如下：

Nginx Rewrite规则，代码如下：

由以上示例可以看出，Apache的Rewrite规则改为Nginx的Rewrite规则，其实很简单：Apache的RewriteRule指令换成Nginx的rewrite指令，Apache的[L]标记换成Nginx的last标记，中间的内容不变。

如果Apache的Rewrite规则改为Nginx的Rewrite规则后，使用nginx -t命令检查发现nginx.conf配置文件有语法错误（主要是大括号引起的），那么可以尝试给条件加上引号。例如以下的Nginx Rewrite规则会报语法错误：

加上引号就正确了：

Apache与Nginx的Rewrite规则在URL跳转时有细微的区别：

Apache Rewrite规则，如下：

Nginx Rewrite规则，如下：

以上示例中，我们注意到，Nginx Rewrite规则的置换串中增加了“http://$host”，这是在Nginx中要求的。

另外，Apache与Nginx的Rewrite规则在变量名称方面也有区别，例如：

Apache Rewrite规则，如下：

Nginx Rewrite规则，如下：

下面，我们来介绍Apache与Nginx Rewrite规则的一些功能相同或类似的指令、标记对应关系：

·　Apache的RewriteCond指令对应Nginx的if指令；

·　Apache的RewriteRule指令对应Nginx的rewrite指令；

·　Apache的[R]标记对应Nginx的redirect标记；

·　Apache的[P]标记对应Nginx的last标记；

·　Apache的[R,L]标记对应Nginx的redirect标记；

·　Apache的[P,L]标记对应Nginx的last标记；

·　Apache的[PT,L]标记对应Nginx的las标记；

如果要编写复杂的Rewrite规则，请阅读下一节的示例。

7.5.2　允许指定的域名访问本站，其他域名一律跳转

Apache Rewrite规则，代码如下：

Nginx Rewrite规则如代码7-3所示：

代码7-3

允许指定的域名访问本站，其他域名一律跳转到http://www.aaa.com。

7.5.3　URL重写与反向代理同时进行

Apache Rewrite规则，代码如下：

Nginx Rewrite规则，代码如下：

7.5.4　指定URL之外的URL进行Rewrite跳转

Apache Rewrite规则，代码如下：

Nginx Rewrite规则如代码7-4所示：

代码7-4

7.5.5　域名前缀作为重写规则变量的示例

Apache Rewrite规则，代码如下：

Nginx Rewrite规则如代码7-5所示：

代码7-5

第8章

Nginx模块开发

一些访问量非常大、业务逻辑简单的Web应用，如果采用PHP等解析型语言去处理，虽然可行，但是在并发能力、处理速度上将受到限制，耗费的系统资源也会较大，这就要求我们增加更多的服务器来处理这类应用。而采用Nginx模块来处理这类Web应用，在性能上将得到极大的提高，大大减少服务器的数量，并将在很大程度上节省服务器的运维成本。

要编写一个Nginx模块，你要熟悉Nginx的配置文件。Nginx配置文件主要分成4部分：main（全局配置）、server（虚拟主机配置）、upstream（主要为反向代理、负载均衡相关配置）和location（目录匹配配置），每部分包含若干个指令。main部分的指令将影响其他所有部分；server部分的指令主要用于指定虚拟主机域名、IP和端口；upstream的指令用于设置反向代理及后端服务器的负载均衡；location部分用于匹配网页位置（例如，根目录“/”、“/images”，等等）。location部分会继承server部分的指令，而server部分会继承main部分的指令；upstream既不会继承指令也不会影响其他部分。它有自己的特殊指令，不需要在其他地方应用。

8.1　Nginx模块概述

Nginx的模块不能够像Apache那样动态添加，所有的模块都要预先编译进Nginx的二进制可执行文件中。

Nginx模块有3种角色：

（1）Handlers（处理模块）——用于处理HTTP请求并输出内容；

（2）Filters（过滤模块）——用于过滤Handler输出的内容；

（3）Load-balancers（负载均衡模块）——当有多于一台的后端服务器供选择时，选择一台后端服务器并将HTTP请求转发到该服务器。

当Nginx发送文件或转发请求到其他服务器时，可以用Handlers处理模块为其服务；当需要Nginx把输出压缩或在服务端加一些东西时，可以用Filters过滤模块；Nginx的核心模块主要管理网络层和应用层协议，以及启动针对特定应用的一系列候选模块。

接下来，我们介绍Nginx模块的处理流程。

客户端发送HTTP请求到Nginx服务器→Nginx基于配置文件中的位置选择一个合适的处理模块→负载均衡模块选择一台后端服务器（反向代理情况下）→处理模块进行处理并把输出缓冲放到第一个过滤模块上→第一个过滤模块处理后输出给第二个过滤模块→然后第二个过滤模块又到第三个过滤模块→第N个过滤模块→最后把处理结果发送给客户端。

模块相当于钩子，可以挂在Nginx的以下位置，在某些时段执行某些功能：

（1）当服务读配置文件之前；

（2）当读取在location和server部分或其他任何部分的每一个配置指令时；

（3）当Nginx初始化全局部分的配置时；

（4）当Nginx初始化主机部分（比如主机／端口）的配置时；

（5）当Nginx将全局部分的配置与主机部分的配置合并时；

（6）当Nginx初始化匹配位置部分配置时；

（7）当Nginx将其上层主机配置与位置部分配置合并时；

（8）当Nginx的主进程（master）开始时；

（9）当一个新的工作进程（worker）开始时；

（10）当一个工作进程退出时；

（11）当主进程退出时；

（12）处理HTTP请求时；

（13）过滤HTTP回复的头部时；

（14）过滤HTTP回复的主体时；

（15）选择一台后端服务器时；

（16）初始化到后端服务器的请求时；

（17）重新初始化到后端服务器的请求时；

（18）处理来自后端服务器的回复时；

（19）完成与后端服务器的交互时。

8.2　Nginx模块编写实践

众所周知，“Hello World”几乎已经变成了所有程序语言的第一个范例。“Hello World”程序指的是只在计算机屏幕上输出“Hello World”（意思为“世界，你好！”）这行字符串的计算机程序。一般来说，这是每一种计算机编程语言中最基本、最简单的程序，通常亦是初学者所编写的第一个程序。那么，在这一节，就让我们动手编写一个在浏览器输出“Hello Word”的Nginx模块，在实践中了解如何编写Nginx模块。

8.2.1　Hello World模块编写与安装

（1）执行以下命令创建一个目录，将在该目录内编写我们的Nginx模块：

（2）开始创建Nginx模块所需的配置文件（名称为config）：

然后输入以下内容并保存退出：

（3）创建Nginx模块的C程序文件（名称格式为“ngx_http_模块名称_module.c”，在本示例中，文件名称为ngx_http_hello_world_module.c：

然后输入如代码8-1所示内容并保存退出：

代码8-1

（4）下载Nginx源码包，并将hello world模块编译到其中，如代码8-2所示：

代码8-2

（5）配置nginx.conf，在server部分增加以下内容：

（6）启动Nginx，用浏览器访问http://localhost/hello，就可以看到编写的Nginx Hello World模块输出的文字“Hello World”。

8.2.2　Hello World模块分析

（1）在ngx_http_hello_world_module.c代码中，ngx_command_t函数用于定义包含模块指令的静态数组ngx_http_hello_world_commands，如代码8-3所示。

代码8-3

在数组中，第一项参数ngx_string（"hello_world"）为指令名称字符串，不能含有空格，数据类型是ngx_str_t，经常用来进行字符串实例化。

注意：ngx_str_t结构体由包含有字符串的data成员和表示字符串长度的len成员组成。Nginx用这个数据类型来存放字符串。

第二项参数用来设置指令在配置文件位置的哪一部分使用是合法的，可选值如下，多个选项以“|”隔开：

NGX_HTTP_MAIN_CONF——指令出现在全局配置部分是合法的；

NGX_HTTP_SRV_CONF——指令出现在server主机配置部分是合法的；

NGX_HTTP_LOC_CONF——指令出现在location配置部分是合法的；

NGX_HTTP_UPS_CONF——指令出现在upstream配置部分是合法的；

NGX_CONF_NOARGS——指令没有参数；

NGX_CONF_TAKE1——指令读入1个参数；

NGX_CONF_TAKE2——指令读入2个参数；

……

NGX_CONF_TAKE7——指令读入7个参数；

NGX_CONF_FLAG——指令读入1个布尔型数据；

NGX_CONF_1MORE——指令至少读入1个参数；

NGX_CONF_2MORE——指令至少读入2个参数。

第三项参数ngx_http_hello_world是一个回调函数。该回调函数有3个参数：

ngx_conf_t*cf——指向ngx_conf_t结构体的指针，包含从指令后面传过来的参数。

ngx_command_t*cmd——指向当前ngx_command_t结构体的指针。

void*conf——指向自定义模块配置结构体的指针。

第四项参数用于告诉Nginx是把要保持的值放在全局配置部分、server主机配置部分还是location位置配置部分（使用NGX_HTTP_MAIN_CONF_OFFSET、NGX_HTTP_SRV_CONF_OFFSET、NGX_HTTP_LOC_CONF_OFFSET）。

第五项参数用于设置指令的值保存在结构体的哪个位置。第六项参数一般为NULL。这样，6个参数都设置完毕，此数组在读入ngx_null_command后停止。

（2）接下来的static u_char ngx_hello_world[]="hello world"；语句，则定义了用于输出给客户端浏览器的字符串内容。

（3）ngx_http_module_t用来定义结构体ngx_http_hello_world_module_ctx，如代码8-4所示。

代码8-4

静态ngx_http_module_t结构体，包含很多函数引用，用来创建3个部分的配置和合并配置。一般结构体命名为ngx_http_<module name>_module_ctx。这些函数引用包括：

preconfiguration——在读入配置前调用；

postconfiguration——在读入配置后调用；

create main configuration——在创建全局部分配置时调用（比如，用来分配空间和设置默认值）；

init main configuration——在初始化全局部分的配置时调用（比如，把原来的默认值用nginx.conf读到的值覆盖）；

create server configuration——在创建虚拟主机部分的配置时调用；

merge server configuration——与全局部分配置合并时调用；

create location configuration——创建位置部分的配置时调用；

merge location configuration——与主机部分配置合并时调用。

这些函数参数不同，依赖于它们的功能。代码8-5是这个结构体的定义，摘自http/ngx_http_config.h，你可以看到属性各不相同的回调函数：

代码8-5

如果不用某些函数，可以设定为NULL，Nginx会剔除它。

（4）ngx_module_t定义结构体ngx_http_hello_world_module，如代码8-6所示。

代码8-6

这个结构体变量命名为ngx_http_<module name>_module。它包含有模块的主要内容和指令的执行部分，也有一些回调函数（退出线程、退出进程，等等）。这个模块的定义是把数据处理关联到特定模块的关键。

（5）回调函数ngx_http_hello_world，分为两步，第一步获得这个Location位置配置的“核心”结构体，然后为它分配一个处理函数ngx_http_hello_world_handler，如代码8-7所示。

代码8-7

（6）处理函数ngx_http_hello_world_handler，也是Hello World模块的核心部分。参数ngx_http_request_t*r，可以让我们访问到客户端的头部和不久要发送的回复头部，包含两个成员：r->headers_in和r->headers_out。

b->pos=ngx_hello_world；即为要输出的内容，ngx_hello_world的内容就是之前通过static u_char ngx_hello_world[]="hello world"；语句定义的用于输出给客户端浏览器的字符串“hello world”，如代码8-8所示。

代码8-8

通过以上内容，相信您已经掌握了如何编写一个简单的Nginx模块。Nginx的模块开发涉及的内容非常广，编写更为复杂的Nginx模块，不是本书的重点所在。如果您感兴趣，可以参阅Evan Miller编写的《Evan Miller's Guide to Nginx Module Development》（http://www.evanmiller.org/nginx-modules-guide.html）获取更多的信息。

第9章

Nginx的Web缓存服务与新浪网的开源NCACHE模块

9.1　什么是Web缓存

Web缓存位于内容源Web服务器和客户端之间，当用户访问一个URL时，Web缓存服务器会去后端Web源服务器取回要输出的内容，然后，当下一个请求到来时，如果访问的是相同的URL，Web缓存服务器直接输出内容给客户端，而不是向源服务器再次发送请求。Web缓存降低了内容源Web服务器、数据库的负载，减少了网络延迟，提高了用户访问的响应速度，增强了用户体验。

Web缓存服务器中，最著名的要数Squid Cache（简称为Squid），已经在大多数网站中使用。Squid是一个流行的自由软件（GNU通用公共许可证）的代理服务器和Web缓存服务器。Squid有广泛的用途，从作为网页服务器的前置cache服务器缓存相关请求来提高Web服务器的速度，到为一组人共享网络资源而缓存万维网、域名系统和其他网络搜索，到通过过滤流量帮助网络安全，到局域网通过代理上网。Squid主要设计用于在Unix一类系统运行。

现在，新版本Nginx的proxy_cache指令开始支持Web缓存服务，另外，新浪网为Nginx开发的NCACHE模块，也能够支持Web缓存服务，解决了Squid不能充分利用多核CPU的局限，速度比Squid更快。

9.2　Nginx的Web缓存服务

Nginx从0.7.48版开始，支持了类似Squid的缓存功能。这个缓存是把URL及相关组合当作Key，用md5算法对Key进行哈希，得到硬盘上对应的哈希目录路径，从而将缓存内容保存在该目录内。它可以支持任意URL链接，同时也支持404/301/302这样的非200状态码。虽然目前官方的Nginx Web缓存服务只能为指定URL或状态码设置过期时间，不支持类似Squid的PURGE指令，手动清除指定缓存页面，但是，通过一个第三方的ngx_cache_purge模块，可以清除指定URL的缓存。

金山逍遥网已经在生产环境使用Nginx的proxy_cache缓存功能多月，十分稳定，速度不逊于Squid。在功能上，Nginx已经具备Squid所拥有的Web缓存加速功能、清除指定URL缓存的功能。而在性能上，Nginx对多核CPU的利用，胜过Squid不少。另外，在反向代理、负载均衡、健康检查、后端服务器故障转移、重写、易用性上，Nginx也比Squid强大很多。这使得一台Nginx可以同时作为“负载均衡服务器”与“Web缓存服务器”来使用。

Nginx的Web缓存服务主要由proxy_cache相关指令集和fastcgi相关指令集构成，前者用于反向代理时，对后端内容源服务器进行缓存，后者主要用于对FastCGI的动态程序进行缓存。两者的功能基本上一样。

9.2.1　proxy_cache相关指令集

1．proxy_cache指令

语法：proxy_cache zone_name；

默认值：None

使用环境：http, server, location

该指令用于设置哪个缓存区将被使用，zone_name的值为proxy_cache_path指令创建的缓存区名称。

2．proxy_cache_path指令

语法：proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size]；

默认值：None

使用环境：http

该指令用于设置缓存文件的存放路径。示例如下：

注意该指令只能在http标签内配置，levels指定该缓存空间有两层hash目录，第一层目录为1个字母，第二层为2个字母，保存的文件名会类似/data0/proxy_cache_dir/c/29/b7f54b2df7773722d382f4809d65029c；keys_zone参数用来为这个缓存区起名，500m指内存缓存空间大小为500MB；inactive的1d指如果缓存数据在1天内没有被访问，将被删除；max_size的30g是指硬盘缓存空间为30GB。

3．proxy_cache_methods指令

语法：proxy_cache_methods [GET HEAD POST]；

默认值：proxy_cache_methods GET HEAD；

使用环境：http, server, location

该指令用于设置缓存哪些HTTP方法，默认缓存HTTP GET/HEAD方法，不缓存HTTP POST方法。

4．proxy_cache_min_uses指令

语法：proxy_cache_min_uses the_number；

默认值：proxy_cache_min_uses 1；

使用环境：http, server, location

该指令用于设置缓存的最小使用次数，默认值为1。

5．proxy_cache_valid指令

语法：proxy_cache_valid reply_code [reply_code...] time；

默认值：None

使用环境：http, server, location

该指令用于对不同返回状态码的URL设置不同的缓存时间，例如：

设置200、302状态的URL缓存10分钟，404状态的URL缓存1分钟。

如果不指定状态码，直接指定缓存时间，则只有200、301、302状态的URL缓存5分钟。

对没有单独设置的状态码，全部设置缓存时间为1分钟。

6．proxy_cache_key指令

语法：proxy_cache_key line；

默认值：None

使用环境：http, server, location

该指令用来设置Web缓存的Key值，Nginx根据Key值md5哈希存储缓存。一般根据$host（域名）、$request_uri（请求的路径）等变量组合成proxy_cache_key。例如：

9.2.2　proxy_cache完整示例

上一节中，我们已经介绍了proxy_cache的相关指令集，现在来看一个proxy_cache的完整示例。

（1）首先，我们要按照以下步骤，把第三方的ngx_cache_purge模块编译安装到Nginx中，用来清除指定URL的缓存，示例如代码9-1所示。

代码9-1

（2）然后，在同一分区下创建两个缓存目录，分别供proxy_temp_path、proxy_cache_path指令设置缓存路径。

注：两个指定设置的缓存路径必须为同一磁盘分区，不能跨分区。

（3）Nginx配置文件（nginx.conf）：对扩展名为gif、jpg、jpeg、png、bmp、swf、js、css的图片、Flash、JavaScript、CSS文件开启Web缓存，其他文件不缓存，示例如代码9-2所示。

代码9-2

9.2.3　fastcgi_cache相关指令集

1．fastcgi_cache指令

语法：fastcgi_cache zone_name；

默认值：off

使用环境：http, server, location

该指令用于设置哪个缓存区将被使用，zone_name的值为fastcgi_cache_path指令创建的缓存区名称。

2．fastcgi_cache_path指令

语法：fastcgi_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size]；

默认值：None

使用环境：http

该指令用于设置缓存文件的存放路径。示例如下：

注意该指令只能在http标签内配置，levels指定该缓存空间有两层hash目录，第一层目录为1个字母，第二层为2个字母，保存的文件名会类似/data0/fastcgi_cache_dir/c/29/b7f54b2df7773722d382f4809d65029c；keys_zone参数用来为这个缓存区起名，500m指内存缓存空间大小为500MB；inactive的1d指如果缓存数据在1天内没有被访问，将被删除；max_size的30g是指硬盘缓存空间为30GB。

3．fastcgi_cache_methods指令

语法：fastcgi_cache_methods [GET HEAD POST]；

默认值：fastcgi_cache_methods GET HEAD；

使用环境：http, server, location

该指令用于设置缓存哪些HTTP方法，默认缓存HTTP GET/HEAD方法，不缓存HTTP POST方法。

4．fastcgi_cache_min_uses指令

语法：fastcgi_cache_min_uses the_number；

默认值：fastcgi_cache_min_uses 1；

使用环境：http, server, location

该指令用于设置缓存的最小使用次数，默认值为1。

5．fastcgi_cache_valid指令

语法：fastcgi_cache_valid reply_code [reply_code...] time；

默认值：None

使用环境：http, server, location

该指令用于对不同返回状态码的URL设置不同的缓存时间，例如：

设置200、302状态的URL缓存10分钟，404状态的URL缓存1分钟。

如果不指定状态码，直接指定缓存时间，则只有200、301、302状态的URL缓存5分钟。

对没有单独设置的状态码，全部设置缓存时间为1分钟。

6．fastcgi_cache_key指令

语法：fastcgi_cache_key line；

默认值：None

使用环境：http, server, location

该指令用来设置Web缓存的Key值，Nginx根据Key值md5哈希存储缓存。一般根据FastCGI服务器的地址和端口、$request_uri（请求的路径）等变量组合成fastcgi_cache_key。例如：

9.2.4　fastcgi_cache完整示例

上一节中，我们已经介绍了fastcgi_cache的相关指令集，现在来看一个fastcgi_cache的完整示例：

（1）首先，在同一分区下创建两个缓存目录，分别供fastcgi_temp_path、fastcgi_cache_path指令设置缓存路径。

注：两个指定设置的缓存路径必须为同一磁盘分区，不能跨分区。

（2）Nginx配置文件（nginx.conf）：对扩展名为gif、jpg、jpeg、png、bmp、swf、js、css的图片、Flash、JavaScript、CSS文件开启Web缓存，其他文件不缓存，示例如代码9-3所示。

代码9-3

9.3　新浪网开源软件项目

——基于Nginx的NCACHE网页缓存系统

NCACHE是基于Nginx的Web服务器模型构建起来的缓存系统，是新浪公司的开源产品。NCACHE最早的时候是作为Nginx的一个HTTP模块进行开发的，因为当时希望获得更好的兼容性和可扩展性，作为独立模块，可以被更好地推广和使用，安装也会很方便。但后来发现随着代码量的增加、功能的扩充，Nginx的原有模块框架已经不能很好地满足要求了，因此，我们提取了Nginx的内核代码，并把CACHE部分嵌入其中，形成了今天的NCACHE。

NCACHE本身功能并不强大，且不具备像SQUID般完善的功能和开发框架，甚至不能支持RFC中关于CACHE部分的描述。NCACHE完全是一套定制化的产品，可以满足要快速部署、简单易用、大并发量、大存储量的需求，它不需要复杂的配置，不需要冗余的复杂代码，并使用最先进的技术组合。

NCACHE 2.0版本，是作为一个完整的Nginx模块进行发布和使用的，从原有的NCACHE内核中进行了剥离，更方便开发者的安装和配置。

NCACHE 3.0版本，相对于2.0版本有了很大的改进，对文件的缓存不再使用传统的目录模式，而是通过MMAP一个大文件，在其中以页分配的形式存储缓存数据，由操作系统来负责决定哪些数据应该留在内存里，这与VARNISH缓存的原理是一致的，大大提高了IO性能，目前该版本只支持64位Linux和FREEBSD系统。

9.3.1　NCACHE模块的安装

NCACHE需要在编译Nginx时，将自己编译进Nginx。NCACHE模块最新的版本为ncache-3.1.64，目前该版本只支持64位Linux和FREEBSD操作系统，ncache-3.1.64能够兼容nginx-0.6.x系列版本，目前还不兼容nginx-0.7.x、nginx-0.8.x版本。

下面，我们将ncache-3.1.64版本编译进nginx-0.6.39，如代码9-4所示：

代码9-4

9.3.2　NCACHE配置文件编写

创建配置文件/usr/local/webserver/ncache/conf/nginx.Conf，如代码9-5所示：

代码9-5

9.3.3　NCACHE的管理维护

1．运行NCACHE

2．停止NCACHE

3．清除缓存的Shell脚本

4．查看NCACHE状态

9.3.4　NCACHE后端内容源服务器设置

（1）必须用HTTP Header头“Cache-Control:max-age=秒数”来控制缓存时间，如果不指定将不缓存。

（2）后端内容源服务器发送NCACHE的HTTP数据，必须带有“Content-Length”Header头。

（3）NCACHE的缓存时间以分钟为单位，会将所有max-age=的秒数值转换为分钟，如果max-age小于1分钟，NCACHE会将缓存时间设置成1分钟。

（4）自动删除缓存文件进程，会在每天的凌晨2点删除大约20％的不活动缓存数据。

第3部分

实战篇

第10章

Nginx在国内知名网站中的应用案例

Nginx在国内知名网站中的应用案例主要可分为三类：Nginx反向代理与负载均衡类网站应用案例、Nginx+PHP/JSP类网站应用案例、Nginx静态内容Web服务器应用案例。下面，我们找了一些截至2009年9月，使用Nginx作为Web服务器的网站代表：

1．使用Nginx运行PHP（FastCGI）、JSP程序的网站

新浪播客（http://v.sina.com.cn/）：nginx/0.7.62+PHP

金山逍遥网（http://www.xoyo.com/）：nginx/0.8.15+PHP 5.2.9

金山爱词霸（http://www.iciba.com/）：nginx/0.6.32+PHP

六间房视频（http://www.6.cn/）：nginx/0.7.21+PHP

Discuz！官方论坛（http://www.discuz.net/）：nginx/0.7.59+PHP/5.2.10

赶集网（http://www.ganji.com/）：nginx/0.7.62+PHP/5.2.8

搜狐通行证（http://passport.sohu.com/）：nginx/0.6.37+JSP

网易博客（http://blog.163.com/）：nginx/0.7.59+JSP

人人网（原校内网）（http://renren.com/）：nginx/0.6.32+JSP

2．使用Nginx作反向代理、规则过滤的网站

新浪播客接口服务器（http://interface.video.sina.com.cn/）：nginx/0.5.35

新浪博客（http://blog.sina.com.cn/）：nginx/0.7.62

YUPOO相册（http://www.yupoo.com/）：nginx/0.5.35

金山游戏用户中心（http://my.xoyo.com/）：nginx/0.8.15

豆瓣（http://www.douban.com/）：nginx

3．使用Nginx运行静态HTML页、图片、FLV视频的网站

网易新闻（http://news.163.com）：nginx/0.6.36

酷6网（http://www.ku6.com/）视频服务器：nginx/0.5.36

迅雷看看（http://www.xunlei.com/）：nginx/0.6.31

新华网RSS订阅频道（http://rss.xinhuanet.com/）：nginx

腾讯网（http://www.qq.com/）：nginx/0.6.39

开心网图片服务器（http://img1.kaixin001.com.cn/）：nginx

无论是新浪、搜狐、网易、腾讯等门户网站，还是目前红红火火的Web 2.0网站，都已经有使用Nginx作为某些项目的Web服务器案例。Nginx大有取代Apache之势。下面，我们就来结合实际案例，介绍一下Nginx在国内知名网站中的应用。

10.1　Nginx反向代理与负载均衡类网站应用案例

10.1.1　Nginx负载均衡在新浪播客中的应用

2008年的新浪播客（v.sina.com.cn、you.video.sina.com.cn）由静态服务器集群和动态服务器集群两部分组成，分别采用不同的域名。静态服务器集群即我们在浏览器地址栏经常能看到v.sina.com.cn和you.video.sina.com.cn域名，采用Squid做前端缓存，服务器分布在全国各地机房。动态服务器集群采用interface.video.sina.com.cn域名，也称接口服务器，主要用来实时显示播放数、记录播放日志、为Flash视频播放器提供数据、与新浪内部产品、外部合作产品交互。

接口服务器最上层采用F5 BIG-IP硬件四／七层负载均衡交换机，对4台Nginx反向代理服务器进行四层负载均衡，由这4台Nginx服务器判断URL，进行分组，对后端的3组Web服务器进行七层负载均衡。F5 BIG-IP也支持七层负载均衡，但是，由于一对F5 BIG-IP要服务新浪的多个产品，七层交换需要耗费F5 BIG-IP不少的CPU资源，而F5 BIG-IP四层交换有专门的硬件芯片来处理，耗费的资源较少，所以，在新浪，F5 BIG-IP一般只用四层负载均衡。

F5 BIG-IP后端的3组Web服务器，配置不一样，第1组为内存密集型服务器，技术类型主要是PHP+Memcached服务：第2组为CPU密集型服务器，主要耗费的是CPU资源；第3组为磁盘密集型服务器，为记录日志等操作，要求磁盘空间大、磁盘转速高。

代码10-1是新浪播客接口服务器的Nginx负载均衡配置，提供按URL分组服务、负载均衡服务：

代码10-1

10.1.2　Nginx负载均衡在金山逍遥网中的应用

在金山逍遥网（www.xoyo.com）中，前端的负载均衡服务器采用的是Nginx，两台Nginx服务器为一组，承担多种类型的负载均衡服务，两台负载均衡服务器都处于活动状态，各自绑定一个公网虚拟IP，作为负载均衡服务器，当其中一台服务器发生故障时，另一台服务器接管发生故障服务器的虚拟IP。这种方式的详细介绍请见第6章。

代码10-2是Nginx负载均衡在金山逍遥网中的配置（nginx.conf）：

代码10-2

10.2　Nginx＋PHP类网站应用案例

10.2.1　Nginx＋PHP在金山逍遥网CMS发布系统中的应用

金山逍遥网CMS发布系统采用PHP编写，自主开发的MVC框架，和其他的MVC框架一样，拥有单一请求处理入口/application/cmsmanage/index.php，逻辑清晰，Nginx的配置也就简单明了：如果文件不存在，则直接Rewrite（重写）到单一入口文件/application/cmsmanage/index.php上。

MVC是Model（模型）、View（视图）、Controller（控制器）这三个单词的缩写组合。MVC是一种普遍的软件敏捷开发模式，在许多领域特别是桌面编程领域早已经得到了广泛的应用，随着众多框架的涌现，MVC在PHP的各个框架中也得到了实现。

单一入口指在一个网站中，所有的动态请求都是指向一个脚本文件的，例如http://cms.xoyo.com/application/cmsmanage/index.php，所有对应用程序的访问都必须通过这个入口。正是单一入口才使得MVC模式得以实现，因为当你访问一个URL的时候，index.php会调用基础类库，做初始化工作，并通过从地址栏的URL路径获取参数，加载控制器、视图、模型等内容信息。

代码10-3则是金山游戏官方网站——逍遥网的CMS发布系统Nginx配置：

代码10-3

10.2.2　Nginx＋PHP在某分类信息网站中的应用

由于历史原因，该网站没有任何开发框架，针对搜索引擎的URL优化，兼容旧的URL地址，几乎全靠Rewrite规则来实现，这也使得该网站nginx.conf配置中拥有大量的Rewrite规则。虽然这种方法不推荐使用，但是，这些实现各种功能的Rewrite规则的应用，具有不小的学习价值。

由于篇幅有限，本书就不列出配置文件的完整内容了，感兴趣的读者可以访问以下网址查看：

http://blog.s135.com/book/nginx/nginx_rewrite_conf.txt

10.3　Nginx视频点播类网站应用案例

10.3.1　Nginx视频点播在金山游戏视频网站中的应用

金山逍遥视频网站为金山软件公司网络游戏的宣传视频，提供Flash视频流媒体点播服务。

整个逍遥视频站点由4部分组成：

（1）v.xoyo.com（逍遥视频网站页面部分）；

（2）FLV视频节点部分；

（3）api.v.xoyo.com（逍遥视频Flash播放器与API接口部分）；

（4）admin.v.xoyo.com（逍遥视频管理后台部分、集成在CMS系统中）。

视频发布流程如下：

金山软件公司的视频编辑人员通过CMS统一登录入口，登录进入admin.v.xoyo.com视频管理后台。在此后台可以上传FLV视频、文字描述。视频上传完成后，系统会自动生成视频ID编号（即vid），并将视频Rsync推送到各节点服务器。

视频播放流程（以访问vid＝387的视频为例）如下：

（1）用户访问逍遥视频页面http://v.xoyo.com/play/387，页面内嵌入了Flash播放器地址：http://api.v.xoyo.com/external/player.swf?config=http://api.v.xoyo.com/external/video-387.swf，其中http://api.v.xoyo.com/external/player.swf为Flash播放器，http://api.v.xoyo.com/external/video-387.swf为经过Rewrite重写规则伪静态的视频API接口，其真实地址为http://api.v.xoyo.com/external/video.php?vid=387。

（2）视频API接口（http://api.v.xoyo.com/external/video.php?vid=387）记录视频播放数等信息，并根据用户来源IP所属的地域、ISP网络接入商进行判断，选择一个当前用户下载速度最快的FLV视频节点，输出包含FLV视频下载地址的XML文件，内容如下。该API接口还会根据各FLV视频节点报告的实时带宽使用情况，在多个IDC节点动态调节视频带宽资源。当一个IDC节点的使用带宽超过设定值后，新的视频播放请求将自动按照地域、ISP类型等顺序，分到邻近的带宽尚有空余的其他IDC，代码如下。

（3）Flash播放器调用、播放FLV视频文件。

（4）不同地域、不同ISP的用户访问的是离自己最近的FLV视频节点上的视频。

（5）能够支持Flash播放器进度条拖动到任意位置播放。

图10-1为系统架构图。

图10-1　金山逍遥视频点播系统架构图

系统架构图中的视频节点采用的是Nginx服务器提供FLV视频播放服务，配置过程可以参见第11章11.2.1节的“采用Nginx的Flv Stream模块搭建HTTP下载方式的FLV视频服务器”。

第11章

Nginx的非典型应用实例

Nginx的用途非常多，在第10章已经介绍了Nginx作为负载均衡服务器、动态应用服务器、静态内容服务器的典型应用案例。而在本章中，主要介绍Nginx的一些实用的非典型应用实例。

11.1　用HTTPS（SSL）构建一个安全的Nginx Web服务器

HTTPS（全称：Hypertext Transfer Protocol over Secure Socket Layer），是以安全为目标的HTTP通道，简单来讲是HTTP的安全版。即HTTP下加入SSL层，HTTPS的安全基础是SSL，因此加密的详细内容就需要SSL。

它是一个URI scheme（抽象标识符体系），句法类同http:体系，用于安全的HTTP数据传输。https:URL表明它使用了HTTP，但HTTPS存在不同于HTTP的默认端口及一个加密／身份验证层（在HTTP与TCP之间）。这个系统的最初研发由网景公司进行，提供身份验证与加密通信方法，现在它被广泛用于万维网上安全敏感的通信，例如交易支付方面。

国内一些大型网站用户中心、邮箱、电子支付等业务，都支持HTTPS（SSL）加密传输。

11.1.1　自行颁发不受浏览器信任的SSL证书

HTTPS的SSL证书可以自行颁发，下面笔者以域名api.bz自行颁发一个SSL证书为例，介绍SSL证书的颁发步骤。

首先，创建一个私钥文件。api.bz.key和api.bz_nopass.key都是私钥文件，不同的是前者须要输入密码，而后者不须要。假设在Linux的/etc/rc.local文件中添加Nginx的启动脚本，重启服务器后，Nginx会自动启动。但是，如果私钥api.bz.key用于Nginx，那么在Nginx启动时会提示输入该私钥文件的密码，Nginx则无法完成自动启动。使用api.bz_nopass.key在启动Nginx时无须输入密码，代码如下。

以上三条语句的操作步骤如图11-1所示。

图11-1　自行生成SSL私钥

然后，创建一个自签署的CA证书：

按照提示，填写国家、省份、城市、公司、部门、域名、邮箱等内容：

通过自行颁发私钥文件api.bz_nopass.key和CA证书api.bz.crt，就可以搭建安全的Nginx Web服务器了。

编译安装Nginx服务器时，须要加上SSL模块，例如：

然后，可以按照代码11-1示例内容，在nginx.conf配置文件中配置HTTP（SSL）虚拟主机：

代码11-1

自行颁发的SSL证书虽然能够实现加密传输功能，但得不到浏览器的信任，会出现如图11-2所示提示。

图11-2　自行颁发的SSL证书在IE7、IE8浏览器下的提示

要解决浏览器的信任问题，需要由正规的CA机构来颁发证书。

11.1.2　向CA机构申请颁发受浏览器信任的SSL证书

能够颁发受浏览器信任的SSL证书的CA机构有很多家，国外著名的CA机构有VeriSign、GlobalSign、GeoTrust、Thawte、Visa、Microsoft等，国内的CA机构有中国互联网络信息中心（CNNIC）。

向CA机构申请SSL证书，同样要按照以下步骤操作，先生成自己的私钥文件和CSR文件。然后把CSR文件（api.bz.csr）提交给CA机构，由CA机构生成CRT证书文件给你。

CA机构颁发的SSL证书，通常单域名和泛域名的价格不一样，所以在使用openssl生成CSR文件时，须要注意Common Name的填写，如果你购买的是单域名SSL证书，Common Name填写的内容就必须和你购买的SSL证书域名一致。例如你购买了sms.api.bz域名的SSL证书，Common Name就必须填写sms.api.bz：

在国内的互联网企业中，对于安全性要求较高的网站，例如招商银行网上银行、中国工商银行网上银行、中国建设银行网上银行、支付宝、百度的百付宝、腾讯的财付通，可选择VeriSign作为其SSL证书供应商。其他一些网站，例如网易邮箱、金山逍遥网用户中心，采用的是CNNIC颁发的SSL证书。

当然，上述这些CA机构颁发的SSL证书是要付费的。目前只有一家CA机构，颁发的SSL证书是免费的。

跟VeriSign一样，StartSSL（网址：http://www.startssl.com，公司名：StartCom）也是一家CA机构，它的根证书很早之前就被一些具有开源背景的浏览器支持（Firefox浏览器部分版本、谷歌Chrome浏览器、苹果Safari浏览器等）。

2009年9月，微软在Windows升级补丁中，更新了通过Windows根证书认证程序（Windows Root Certificate Program）的厂商清单，并首次将StartCom公司列入了该认证清单，这是微软首次将提供免费数字验证技术的厂商加入根证书认证列表中。现在，在Windows 7或安装了升级补丁的Windows Vista或Windows XP操作系统中，系统会完全信任由StartCom这类免费数字认证机构认证的数字证书，从而让StartSSL也获得IE浏览器的支持。

注册成为StartSSL（http://www.startssl.com）用户，并通过邮件验证后，就可以申请免费的可信任的SSL证书了。步骤比较复杂，就不详细介绍了，申请向导的主要步骤如下：

（1）在申请向导中选择验证类型为域名验证。StartSSL将通过发邮件到你的域名Whois信息中的联系人E-mail地址，来验证您是否为该域名的拥有者。只有验证通过，才会颁发证书给你，如图11-3所示。

图11-3　StartSSL免费SSL证书申请向导（1）

（2）输入你要申请SSL证书的域名，如图11-4所示。

图11-4　StartSSL免费SSL证书申请向导（2）

（3）选择证书使用目的：Web Server SSL，如图11-5所示。

图11-5　StartSSL免费SSL证书申请向导（3）

并非所有浏览器都能信任StartSSL的证书，如果您的网站比较重要，还是建议您购买VeriSign、GlobalSign、CNNIC等商业CA机构的SSL证书。

11.2　采用Nginx搭建FLV视频服务器

国内外著名的视频分享网站，例如YouTube、优酷网、土豆网、新浪播客等，采用的都是Flash播放器播放FLV/MP4视频文件的技术。

FLV视频可以采用两种方式发布，一种是普通的HTTP下载方式，另一种是基于Flash Media Server或Red5服务器的RTMP/RTMPT流媒体方式。YouTube、优酷网、土豆网、新浪播客等，采用的是HTTP下载方式，金山逍遥网的部分游戏视频采用的是RTMP流媒体方式。流媒体方式无须下载视频文件到本地，可以实时播放服务器上的FLV文件，可以任意拖曳Flash播放器播放进度条，用户体验较好，但是比较消耗服务器资源。而HTTP下载方式须要下载FLV视频文件到本地播放，一旦FLV视频下载完成，就不消耗服务器资源和带宽了，虽然也可以实现拖动，但是拖动功能不如流媒体方式强大。

对基于HTTP下载方式的FLV视频发布，可以通过Nginx的Flv Stream模块，实现FLV视频播放的进度条拖动。对基于RTMPT流媒体协议的FLV视频发布，Nginx可以用来实现对后端Flash Media Server或Red5服务器RTMPT的反向代理。

11.2.1　采用Nginx的Flv Stream模块搭建HTTP下载方式的FLV视频服务器

Flv Stream模块是Nginx的可选模块，需要在编译安装Nginx服务器时，把Flv Stream模块加上，例如：

然后，按照代码11-2所示示例方式，在nginx.conf配置文件中配置存储FLV视频文件的虚拟主机：

代码11-2

重启Nginx后，Nginx配置部分就算OK了。limit_rate_after 3m和limit_rate 512k两项指令设置了一开始不限速，在客户端下载FLV视频大小超过3MB后，开始限制下载速度为512KB/秒。一开始不限速可以使得刚播放视频时，下载到客户端的视频文件字节数尽量多，用户播放无须长时间等待缓冲。大小超过3MB的视频文件一般都比较大，可以限速让用户边观看边下载，在不影响用户体验的情况下，可以节省不少服务器带宽资源。

当用户拖动Flash播放器的进度条时，会发起一个类似http://flv.domain.com/test.flv?start=12345的请求URL到Nginx服务器，告诉Nginx服务器下载start参数值附近的关键帧之后的那部分FLV文件，从而实现拖动播放。

光配置好Nginx服务器不管用，还需要FLV文件MetaData中含有关键帧信息，才能实现拖动播放。一般从其他视频格式转换成FLV视频格式的文件MetaData中是不含关键帧信息的，可以在Linux下使用开源软件自动为FLV文件添加关键帧信息。

Linux下为FLV文件添加关键帧的常用软件有两种。

（1）开源软件Yamdi：

我们可以按照代码11-3所示方式编译安装Yamdi：

代码11-3

安装完成Yamdi之后，可以按照以下示例为FLV文件添加关键帧信息：

（2）开源软件FlvTool2：

在CentOS下，可以按照以下方式安装FlvTool2：

安装完成Yamdi之后，可以按照以下示例为FLV文件添加关键帧信息：

采用FlvTool2为FLV文件添加的关键帧为每两秒钟一个，比Yamdi添加的关键帧要多，因此视频拖动播放时要更流畅。但是，FlvTool2为FLV文件添加关键帧所耗费的时间要比Yamdi多几倍到几十倍。

为FLV视频文件添加完关键帧后，就要找一个支持HTTP进度条拖动的Flash播放器来播放FLV视频了。开源的JW Player播放器是个不错的选择，可以通过其官网网站（http://www.longtailvideo.com/）下载。

我们可以通过JW Player，测试播放Nginx服务器上的FLV视频，如果不出意外，应该可以正常支持播放进度条拖动：

11.2.2　采用Nginx实现FMS/Red5流媒体视频服务器的负载均衡

Adobe公司官方的FMS（Flash Media Server）和第三方的开源Red5流媒体服务器都支持RTMP协议、RTMPT协议的FLV视频流媒体播放。

RTMP全称Real Time Messaging Protocol（实时消息传送协议），是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的私有协议。

RTMPT协议是一个包装了RTMP的HTTP协议，它从客户端发送POST请求到服务器。由于HTTP连接的非持久性本质，为了及时更新状态和数据，RTMPT需要客户端周期性向服务器轮询，取得服务器或其他客户端产生的通知事件。

通过Nginx，可以实现多台FMS/Red5流媒体服务器RTMPT协议流媒体视频播放的负载均衡。nginx.conf配置示例如代码11-4所示：

代码11-4

刚才已经介绍过的开源JW Player播放器，同样可以用来播放RTMPT协议的FLV视频，示例如下：

播放基于RTMPT协议的FLV流媒体视频时，可以通过Nginx的访问日志/data1/logs/rtmpt.log来了解整个播放流程。RTMPT用命令：OPEN、SEND、IDLE、CLOSE来控制网络连接，当处理RTMPT的请求时，所有的RTMPT命令使用POST方法来处理请求和回应，此外其他命令则可以使用GET方法，如代码11-5所示。

代码11-5

通过Nginx对FMS/Red5流媒体视频服务器的反向代理，既能够实现负载均衡，又能够实现自动故障转移，是一项不错的选择。

11.3　Nginx＋PHP＋MySQL在小内存VPS服务器上的优化

VPS（全称Virtual Private Server）是利用最新虚拟化技术在一台物理服务器上创建多个相互隔离的虚拟私有主机。它们以最大化的效率共享硬件、软件许可证及管理资源。对其用户和应用程序来讲，每一个VPS平台的运行和管理都与一台独立主机完全相同，因为每个VPS均可独立进行重启并拥有自己的root访问权限、用户、IP地址、内存、过程、文件、应用程序、系统函数库及配置文件。

目前提供VPS租用服务的提供商越来越多，大有取代虚拟主机之势。VPS服务器最重要的指标就是内存大小，多个VPS服务器可以共享一颗CPU，但不能共享同一块内存。内存越大，价格越贵。

本节针对128MB内存Linux操作系统的VPS，对Nginx＋PHP＋MySQL优化进行介绍。

11.3.1　增加swap交换文件

如果您的VPS提供商没有为您的VPS划分swap交换分区，则可以自行创建swap交换文件来代替交互分区。

（1）创建并激活swap交换文件。

（2）加到fstab文件中让系统引导时自动启动。

在末尾增加以下内容：

11.3.2　Nginx的主配置文件（nginx.conf）优化

Nginx的主配置文件（nginx.conf）优化示例如代码11-6所示：

代码11-6

11.3.3　PHP（FastCGI）的配置优化

（1）php.ini配置文件中关于eAcelerator的优化。只使用1MB共享内存，删除所有在最后3600秒内无法存取的脚本缓存，用磁盘辅助进行缓存，如代码11-7所示。

代码11-7

（2）如果您按照第5章安装了PHP（FastCGI），则可以按照以下方式对php-fpm.conf配置进行优化。

修改两项，一是修改以下一行，将启动的php-cgi进程数改为5个：

二是修改以下一行，将TCP模式改为Unix Socket模式：

11.3.4　MySQL 5.1配置优化

（1）使用以下参数编译安装的MySQL 5.1默认支持4种存储引擎：CSV、MRG_MYISAM、MEMORY、MyISAM，不支持InnoDB存储引擎。由于内存有限，而InnoDB耗费的内存较大，这里推荐使用MyISAM存储引擎。

（2）MySQL 5.1配置文件（my.cnf）优化示例如代码11-8所示。

代码11-8

11.4　采用Nginx搭建正向代理服务器

正向代理就是通常所说的代理，是某台电脑通过一台服务器来上Internet网的这种方式，其中这台电脑就叫客户机，这台服务器就叫正向代理服务器，也就是通常所说的代理服务器。一般情况下，客户机必须指定代理服务器（IE浏览器可在工具→Internet选项→连接→局域网设置→代理服务器中设置）。

Nginx正向代理的nginx.conf配置文件如代码11-9所示：

代码11-9

配置完成后，重启Nginx使配置生效。然后，你就可以在IE浏览器菜单栏中的“工具”→“Internet选项”→“连接”→“局域网设置”→“代理服务器”中设置代理服务器IP地址（假设为61.1.1.1）和端口，如图11-6所示。

图11-6　IE浏览器中的代理服务器设置

然后，您的IE浏览器就可以在Nginx代理服务器访问Internet了。

第4部分

模块篇

第12章

Nginx的核心模块

在第4部分，我们主要介绍Nginx的各类模块。Nginx的模块分为核心模块、标准HTTP模块、可选HTTP模块、邮件模块、第三方模块和补丁。

其中，Nginx的核心模块包括主模块和事件模块两部分。

12.1　主模块指令

Nginx的主模块是实现Nginx的基本功能的指令集，它们一般写在Nginx的配置文件的最上方。下面，我们来介绍Nginx主模块中包含的指令。

12.1.1　daemon指令

语法：daemon on｜off

默认值：on

示例：daemon off;

在生产环境中，请不要使用daemon和master_process指令。这些选项仅用于开发调试。当然，你也可以在生产环境中设置daemon off，然后使用进程管理工具启动Nginx，但是，平滑重启、升级等功能将无法使用。master_process off绝对不应该用于生产环境。

12.1.2　env指令

语法：env VAR|VAR＝VALUE

默认值：TZ

使用环境：main

此项指令用来定义变量集合，以下场合须更改环境变量，或者添加新的环境变量：

·　在零停机情况下平滑升级Nginx时；

·　启用Nginx内置Perl模块时使用；

·　被Nginx进程所使用。

如果没有明确定义TZ的值，默认情况下它集成老版本的值，且默认情况下内置的Perl模块总是可以使用TZ值的。

例如：

12.1.3　debug_points指令

语法：debug_points[stop|abort]

默认值：none

示例：debug_points stop;

用于调试，在调试器内设置断点。

12.1.4　error_log指令

语法：error_log file[debug|info|notice|warn|error|crit]

默认值：${prefix}/logs/error.log

示例：debug_points stop;

file参数用来指定记录Nginx及FastCGI错误日志的文件路径。错误日志记录了服务器运行期间遇到的各种错误，以及一些普通的诊断信息，我们可以设置日志文件记录信息级别的高低，控制日志文件记录信息的数量和类型。通常情况下，Nginx分为6个错误级别，其中debug级别最低，记录的错误日志数量最多，范围最广；而crit级别最高，只记录非常严重的错误，一般在生产环境中使用。

日志中默认的错误级别：

·　main部分：error

·　HTTP部分：crit

·　server部分：crit

Nginx支持将不同虚拟主机的日志存储在不同的位置，这是个很有特色的功能。在lighttpd中，它们一直拒绝提供类似的功能。代码12-1为针对不同虚拟主机提供不同日志的示例：

代码12-1

如果你在编译Nginx的时候，使用了--with-debug指令，则还可以使用：

注意：error_log off无法禁用日志，这种写法将会创建一个名为off的日志文件。如果要禁用日志，请用下面的写法：

12.1.5　log_not_found指令

语法：log_not_found on|off

默认值：on

使用环境：debug_points stop;

启用或禁用404错误日志，这个指令可以用来禁止Nginx记录找不到robots.txt和favicon.ico这类文件的错误信息。

示例：

12.1.6　include指令

语法：linclude file|*

默认值：无

使用此指令，可以包含任何你想要包含的配置文件。从0.4.4开始，include指令开始支持文件名匹配，例如：

注意：直到0.6.7版本为止，include文件的路径是相对于configure时由--prefix=<path>指令指定的路径而言的，默认情况下是/usr/local/nginx。如果在编译compiledNginx时你没有指定这个值，请使用绝对路径。

从0.6.7开始，include文件的路径实现归于Nginx配置文件nginx.conf的所在目录，不再是Nginx编译时指定的路径。这个改进大大增加了include的灵活性。

12.1.7　lock_file指令

语法：lock_file file

默认值：compile-time option

示例：lock_file /var/log/lock_file;

如果Nginx是由gcc、Intel C++或SunPro C++在i386、amd64平台上编译的，Nginx可采用异步互斥进行访问控制。

12.1.8　master_process指令

语法：master_process on|off

默认值：on

示例：master_process off;

生产环境中，请不要使用daemon和master_process指令，这些选项主要用于开发调试。

12.1.9　pid指令

语法：pid file

默认值：compile-time option

示例：pid/var/log/nginx.pid;

pid文件内记录着当前Nginx主进程的ID号，可以通过kill命令发送信号给该ID号，例如重新加载Nginx配置文件完成平滑重启：kill-HUP'cat/var/log/nginx.pid'

12.1.10　ssl_engine指令

语法：ssl_engine engine

默认值：系统默认依赖的引擎

此指令可以设置首选的SSL引擎。你可以通过命令行工具openssl engine -t找出系统目前支持的SSL引擎，例如：

12.1.11　timer_resolution指令

语法：timer_resolution t

默认值：none

示例：timer_resolution 100ms;

该指令可以减少gettimeofday()函数获取当前时间的系统调用次数。在默认情况下，gettimeofday()函数会在每一次kevent()、epoll、/dev/poll、select()、poll()返回时被调用。如果你需要在日志中记录毫秒级的准确时间，或者毫秒级的准确反向代理响应时间，你要使用此指令。

12.1.12　try_files指令

语法：try_files path1 [path2] uri

默认值：none

备注：从Nginx 0.7.27版本开始提供此指令。

该指令可以按照参数顺序检查文件是否存在，以及返回第一个被找到的文件名。以“/”结尾的表示一个目录。如果文件没有找到，将被内部重定向到最后一个参数上。最后的参数是一个后备的URI（统一资源标识符），它必须存在，否则会报内部错误。

代码12-2为在反向代理中使用try_files指令：

代码12-2

代码12-3为在FastCGI中使用try_files指令：

代码12-3

在以上两个例子中，指令try_files：

类似于以下的指令：

和

try_files指令还可以在请求提交给PHP等FastCGI服务器之前，检查PHP文件是否存在。

在Wordpress博客系统和Joomla内容发布系统中使用的示例如代码12-4所示：

代码12-4

12.1.13　user指令

语法：user user [group]

默认值：nobody nobody

示例：user www users;

该指令用于指定运行Nginx Worker进程的用户和组，默认的用户名和组名都是nobody。如果组名没有指定，Nginx则默认组名与用户名相同。

12.1.14　worker_cpu_affinity指令

语法：user user[group]

默认值：nobody nobody

备注：只能在Linux环境中使用。

使用此指令，你可以为每个Nginx Worker进程绑定指定的一颗CPU（双核CPU算做两颗），Nginx采用sched_setaffinity()函数绑定CPU。

示例如下：

分别给每个worker进程绑定一个CPU：

在上例中，第一个Nginx Worker进程绑定了CPU0/CPU2，第二个Nginx Worker进程绑定了CPU1/CPU3。这种配置适用于超线程技术。

12.1.15　worker_priority指令

语法：worker_priority[-]number

默认值：on

使用该选项可以给所有的worker进程分配优先值。

12.1.16　worker_processes指令

语法：worker_processes number

默认值：1

示例：worker_processes 5;

Nginx可以使用多个worker进程，原因如下：

（1）使用SMP对称多处理方式，充分发挥多核CPU的优势。SMP的全称是“对称多处理”（Symmetrical Multi-Processing）技术，是指在一个计算机上汇集了一组处理器（多CPU），各CPU之间共享内存子系统及总线结构。它是相对非对称多处理技术而言的、应用十分广泛的并行技术。在这种架构中，一台电脑不再由单个CPU组成，而同时由多个处理器运行操作系统的单一复本，并共享内存和一台计算机的其他资源。虽然同时使用多个CPU，但是从管理的角度来看，它们的表现就像一台单机一样。系统将任务队列对称地分布于多个CPU之上，从而极大地提高了整个系统的数据处理能力。所有的处理器都可以平等地访问内存、I/O和外部中断。在对称多处理系统中，系统资源被系统中所有CPU共享，工作负载能够均匀地分配到所有可用处理器之上。

（2）能够减少进程在磁盘I/O阻塞上的延迟时间。

（3）当使用select()/poll()模型时，能够限制每个进程的连接数。

通过worker_processes和worker_connections两个指令可以计算出最大客户端连接数，计算公式如下：

12.1.17　worker_rlimit_core指令

语法：worker_processes number

该指令用于指定每个Nginx进程的最大core文件大小。

12.1.18　worker_rlimit_nofile指令

语法：worker_rlimit_nofile limit

示例：worker_rlimit_nofile 65535;

该指令用于指定Nginx进程可以打开的最大文件描述符数量。

12.1.19　worker_rlimit_sigpending指令

语法：worker_rlimit_sigpending limit

示例：worker_rlimit_sigpending 32768;

（Linux 2.6.8以上内核支持）该指令指定调用进程的真正用户ID的排队数量。

12.1.20　working_directory指令

语法：working_directory path

默认值：--prefix

该指令用于指定Nginx的工作目录，path参数只能使用绝对路径。该指令的默认值为Nginx使用configure文件编译安装时，参数--prefix==PATH指定的路径。

12.2　主模块变量

在主模块指令中，可以从以下变量获取相关信息：

当前运行的Nginx版本号。

进程ID号。

Root目录绝对路径。

12.3　事件模块指令

Nginx的事件模块是控制Nginx处理访问连接的指令集，跟主模块指令一样，事件模块的指令也写在Nginx的配置文件的最上方区域。下面，我们来介绍Nginx事件模块中包含的指令。

12.3.1　accept_mutex指令

语法：accept_mutex[on|off]

默认值：on

Nginx使用连接互斥锁进行顺序的accept()系统调用。

12.3.2　accept_mutex_delay指令

语法：accept_mutex_delay Nms;

默认值：500ms

如果一个工作进程没有互斥锁，它将在最少N毫秒延迟之后再次尝试获取互斥锁。默认的延迟时间为500毫秒。

12.3.3　debug_connection指令

语法：debug_connection[ip|CIDR]

默认值：none

从Nginx 0.3.54版本开始支持CIDR地址格式。这个选项用于记录IP/网络的用户端侦错日志。示例如下：

12.3.4　use指令

语法：use[kqueue|rtsig|epoll|/dev/poll|select|poll|eventport]

如果你在使用./configure脚步编译安装Nginx时，指定了一个以上的事件模型，则要告诉Nginx使用哪种事件模型。如果您的操作系统是FreeBSD 4.1以上版本，推荐使用Kqueue模型，如果您的操作系统是Linux 2.6以上内核版本，推荐使用epoll模型，如果您的操作系统是Solaris 10，推荐使用eventport模型。Kqueue、epoll、eventport分别属于FreeBSD、Linux、Solaris操作系统中高效的时间模型。

12.3.5　worker_connections指令

语法：worker_connections number

该指令用于设置每个工作进程能够处理的连接数。通过worker_connections和worker_proceses（Nginx工作进程数）可以计算出Nginx服务器能够处理的最大连接数max_clients，计算公式如下：

假设你开启了8个Nginx进程（worker_proceses），设置的worker_connections连接数为32768，那么最大连接数max_clients为8*32768＝262144。这只是理论值，实际情况下，受操作系统、文件描述符与端口数的限制，最大连接数是达不到262144的。

在反向代理情况下，最大连接数变成了：

因为，Internet Explorer浏览器通常默认打开两个与服务器的连接，而Nginx使用同一个文件描述符池中的描述符来连接后端。

第13章

Nginx的标准HTTP模块

本章介绍的HTTP模块会在编译Nginx时自动编译进来，除非使用configure命令禁止编译这些模块。

在本章的指令介绍中，指令的“使用环境”是该指令可以在Nginx配置文件中使用的位置，例如使用环境为“http, server, location”，表示该指令可以在以下位置使用：

http{......}大括号内；server{......}大括号内；location{......}大括号内。

13.1　HTTP的核心模块

13.1.1　alias指令

语法：alias file-path|directory-path;

默认值：no

使用环境：location

该指令用于在URL和文件系统路径之间实现映射。它与root指令类似，但是网页文件的root根目录不会改变，改变的只是请求URL的文件系统路径。

示例如下：

在示例中，访问URL地址“/i/top.gif”会返回文件“/spool/w3/images/top.gif”。

在被替换的路径中，可以使用变量。在含有正则表达式的location中，不能使用alias指令，如果你想使用，可以使用rewrite和root指令的组合来实现。

13.1.2　client_body_in_file_only指令

语法：client_body_in_file_only on|off

默认值：off

使用环境：http，server，location

该指令允许将一个客户端的请求内容记录到一个文件中，该文件在请求完成后不会被删除。在内置Perl中，该指令可以用于调试$r->request_body_file方法。

13.1.3　client_body_in_single_buffer指令

语法：client_body_in_single_buffer

默认值：off

使用环境：http，server，location

该指令（0.7.58以上版本支持）指定是否保持整个内容在一个单一的客户端请求缓冲区中。该指令在使用变量$request_body时被推荐使用。

13.1.4　client_body_buffer_size指令

语法：client_body_buffer_size the_size

默认值：8k/16k

使用环境：http，server，location

示例：client_body_buffer_size 128k;

该指令指定客户端请求内容的缓冲区大小。如果客户端请求内容大于缓冲区，整个请求内容或部分请求内容将被写入临时文件。缓冲区默认大小相当于网页大小的两倍，为8k或16k。

13.1.5　client_body_temp_path指令

语法：client_body_temp_path dir-path [level1 [level2 [level3]

默认值：client_body_temp

使用环境：http，server，location

该指令用于指定存放请求内容临时文件的目录。缓存目录最多支持3层子目录。

示例：

client_body_temp_path/spool/nginx/client_temp 1 2;

以上示例的目录结构类似：

/spool/nginx/client_temp/7/45/00000123457

13.1.6　client_body_timeout指令

语法：client_body_timeout time

默认值：60

使用环境：http，server，location

该指令用于设置读取客户端请求内容的超时时间。如果超过该指令设置的时间，Nginx将返回“Request time out”错误信息（HTTP状态码为408）。

13.1.7　client_header_buffer_size指令

语法：client_header_buffer_size size

默认值：1k

使用环境：http，server

该指令用于设置客户端请求的Header头缓冲区大小。对绝大多数请求来说，1KB大小的Header头缓冲区已经足够，但是对于Cookie内容较大的请求来说，可能不够用，你可以加大该值。

13.1.8　client_header_timeout指令

语法：client_header_timeout time

默认值：60

使用环境：http，server

该指令用于设置读取客户端请求Header头信息的超时时间。如果超过该指令设置的时间，Nginx将返回“Request time out”错误信息（HTTP状态码为408）。

13.1.9　client_max_body_size指令

语法：client_max_body_size size

默认值：client_max_body_size 1m

使用环境：http，server，location

示例：client_max_body_size 300m;

该指令用于设置允许接受的客户端请求内容的最大值，即客户端请求Header头信息中设置的Content-Length的最大值。如果超过该指令设置的最大值，Nginx将返回“Request Entity Too Large”错误信息（HTTP状态码为413）。当默认值为1MB时，如果Nginx服务器提供上传1MB以上的大文件等操作，则要加大该值。

13.1.10　default_type指令

语法：default_type MIME-type

默认值：default_type text/plain

使用环境：http，server，location

MIME-type是用来告诉浏览器请求的文件媒体类型的，例如MIME-type名text/plain表示该文件为文本文件，text/html表示该文件为HTML网页文件。如果Nginx无法识别该文件属于何种MIME-type类型，则将该文件标记为default_type指令设置的MIME-type。

例如：

13.1.11　directio指令

语法：directio[size|off]

默认值：directio off

使用环境：http，server，location

该指令用于设置一个文件大小，当读取的文件超过该大小时，将使用O_DIRECT标签（FreeBSD, Linux）、F_NOCACHE标签（Mac OS X）或directio()函数（Solaris）来读取该文件。打开文件时如果用O_DIRECT，系统就不会使用buffer缓冲区，而直接通过DMA读取文件。DMA的英文拼写是“Direct Memory Access”，汉语的意思就是直接内存访问，是一种不经过CPU而直接从内存存取数据的数据交换模式。

directio指令将使sendfile功能失效。对于大文件来说，使用该指令是有益的。在以下的示例中，设置了对4MB以上的文件使用O_DIRECT、F_NOCACHE标签或directio()函数读取：

13.1.12　error_page指令

语法：error_page code[code...][=|=answer-code] uri

默认值：no

使用环境：http，server，location，if in location

该指令用于设置如果出现指定的HTTP错误状态码，则返回给客户端显示的对应URI地址。

示例如下：

如果遇到404错误状态码（客户端请求的页面不存在），则显示指定的/404.html文件内容给客户端。注意/404.html文件大小不能超过512字节，否则Internet Explorer浏览器会默认为其错误页面，而不是指定的/404.html页面。

如果遇到502、503、504错误状态码（服务器错误），则显示指定的/50x.html文件内容给客户端。

如果遇到403错误状态码（服务器已经理解请求，但是拒绝执行它），则跳转到URL地址http://example.com/forbidden.html。

此外，还可以更改HTTP的错误响应码为别的响应码，以便某些客户端浏览器能够支持，例如：

如果遇到404错误状态码（客户端请求的页面不存在），将状态码改为200，并显示指定的/empty.gif文件内容给客户端。

如果响应错误代码的页面是PHP等FastCGI程序，则最好在error_page中加上=号。

如果你想返回原样的错误状态码，则去掉error_page指令中的=号。

13.1.13　if_modified_since指令

语法：if_modified_since[off|exact|before]

默认值：if_modified_since exact

使用环境：http，server，location

if-modified-since是由客户端浏览器往Nginx服务器发送的头信息。当再次请求本地存在的缓存页面时，客户端浏览器会通过if-modified-since头信息将先前Nginx服务器端发过来的Last-Modified最后修改时间戳发送回去，这是为了让Nginx服务器端进行验证，通过这个时间戳判断客户端的页面是否是最新的。如果不是最新的，则返回新的内容；如果是最新的，则返回304状态码告诉客户端浏览器其本地缓存的页面是最新的，于是浏览器就可以直接从本地加载页面，这样在网络上传输的数据就会大大减少，从而可加快页面的显示速度，同时也减轻服务器的负担。

if_modified_since指令（Nginx 0.7.24以上版本支持）用于设置如何去比较客户端请求Header头信息中的“if-modified-since”文件的修改时间。

·　off——不检查“if-modified-since”请求头；

·　exact——时间完全符合；

·　before——文件修改时间应该早于“if-modified-since”请求头中的时间。

13.1.14　index指令

语法：index file[file...]

默认值：index index.html

使用环境：http，server，location

该指令用于设置Nginx的默认首页文件。

例1：在文件名中可以使用变量，并且最后的默认首页文件可以使用绝对路径（即/index.html）：

例2：

如果某个目录下没有指定的默认首页文件，则可以开启以下指令，显示当前目录的文件列表：

13.1.15　internal指令

语法：internal

默认值：no

使用环境：location

该指令用于设置某个location路径只能在Nginx内部使用，外部无法访问。

例1：

例2：

13.1.16　keepalive_timeout指令

语法：keepalive_timeout[time]

默认值：keepalive_timeout 75

使用环境：http，server，location

keep-alive功能可使客户端到服务器端的连接持续有效，当出现对服务器的后继请求时，keep-alive功能可避免建立或重新建立连接。市场上的大部分Web服务器，包括IIS、Apache、Nginx、Lighttpd，都支持HTTP keep-alive。对于提供静态内容的网站来说，这个功能通常很有用。但是，对于负担较重的网站来说，这里存在另外一个问题：虽然为客户保留打开的连接有一定的好处，但它同样影响了性能，因为在暂停期间，本来可以释放的资源仍旧被占用。当Web服务器和应用服务器在同一台机器上运行时，keep-alive功能对资源利用的影响尤其突出。此功能为HTTP 1.1预设的功能，HTTP 1.0加上keep-alive header也可以提供HTTP的持续作用功能。

该指令用于设置keep-alive连接超时时间，使用该指令第二个参数设置的时间（秒）将显示在输出的Header头keep-alive：timeout=time中。不过，一些浏览器不支持keep-alive。

另外，在IE浏览器中，浏览器自身限制keepalive时间为60秒。无论是客户端浏览器（Internet Explorer）还是Web服务器都具有较低的keepalive值，这些都将是限制因素。例如，如果客户端的超时值是两分钟，而Web服务器的超时值是一分钟，则最大超时值是一分钟。客户端或服务器都可以是限制因素。

13.1.17　keepalive_requests指令

语法：keepalive_requests n

默认值：keepalive_requests 100

使用环境：http，server，location

设置一个keep-alive连接使用的次数。一次请求结束后，如果该连接使用的次数没有超过keepalive_requests指令设置的请求次数，则服务器并不立即主动断开连接，而是直到达到keepalive_timeout指令设置的时间，才关闭连接。

13.1.18　large_client_header_buffers指令

语法：large_client_header_buffers number size

默认值：large_client_header_buffers 4 4k/8k

使用环境：http，server

该指令用于设置客户端请求的Header头缓冲区大小，默认值为4KB。客户端请求行不能超过large_client_header_buffers指令设置的值，客户端请求的Header头信息不能大于large_client_header_buffers指令设置的缓冲区大小，否则会报“Request URI too large”（414）或“Bad request”（400）错误。如果客户端的Cookie信息较大，则须增加缓冲区大小，示例如下：

13.1.19　limit_except指令

语法：limit_except methods{...}

默认值：no

使用环境：location

该指令用于限制HTTP方法访问location中的内容，示例如下：

13.1.20　limit_rate指令

语法：limit_rate speed

默认值：no

使用环境：http，server，location，if in location

该指令主要用来限速，限速单位是“字节数／秒”，一般在提供HTTP下载等应用中会用到该指令。限速只对一个连接起效，如果客户端开启两个连接下载，下载的速度将是限速值的两倍。

例1：限制每个连接的下载速度为100KB/秒：

例2：在特定条件下开启限速功能：

13.1.21　limit_rate_after指令

语法：limit_rate_after time

默认值：limit_rate_after 1m

使用环境：http，server，location，if in location

该指令可以设置一个字节数（例如1MB），下载的字节数大于该值后，limit_rate指令的限速功能将起效。对于MP3在线播放、HTTP方式的Flash FLV视频点播等应用，使用该指令将会起到不错的效果。

例：下载的文件字节数超过1MB后，限速为100KB/秒。

13.1.22　listen指令

语法：listen address:port[default[backlog=num|rcvbuf=size|sndbuf=size|accept_filter=filter|deferred|bind|ssl]

默认值：listen 80

使用环境：server

该指令用于设置虚拟主机监听的服务器地址和端口号。你可以同时设置服务器地址和端口号，也可以只指定一个IP地址，或者一个端口号，或者一个服务器名。如果listen指令只设置一个服务器名或IP地址，那么它的默认端口号为80。

示例如下：

监听IPV6地址示例如下：

示例：通过以下配置，可以设置一个虚拟主机同时支持HTTP和HTTPS：

13.1.23　location指令

语法：location[=|~|~*|^~]/uri/{...}

默认值：no

使用环境：server

该指令允许对不同的URI进行不同的配置，既可以使用字符串，也可以使用正则表达式。使用正则表达式，须使用以下前缀：

（1）~*，表示不区分大小写的匹配。

（2）~，表示区分大小写的匹配。

在匹配过程中，Nginx将首先匹配字符串，然后再匹配正则表达式。匹配到第一个正则表达式后，会停止搜索。如果匹配到正则表达式，则使用正则表达式的搜索结果，如果没有匹配到正则表达式，则使用字符串的搜索结果。

可以使用前缀“^~”来禁止匹配到字符串后，再去检查正则表达式。匹配到URI后，将停止查询。

使用前缀“=”可以进行精确的URI匹配，如果找到匹配的URI，则停止查询。例如“location=/”，只能匹配到“/”，而“/test.html”则不能被匹配。

正则表达式的匹配，按照它们在配置文件中的顺序进行，写在前面的优先。

示例如代码13-1所示：

代码13-1

请求处理匹配结果示例：

·　/->configuration A;

·　/documents/document.html->configuration B;

·　/images/1.gif->configuration C;

·　/documents/1.jpg->configuration D。

你可以采用不同的顺序定义这4个配置，但是，匹配结果是一样的。

另外，前缀“@”是一个命名标记，这种location不会用于正常的请求，它们通常只用于处理内部的重定向（例如：error_page、try_files），示例代码如13-2所示：

代码13-2

13.1.24　log_not_found指令

语法：log_not_found[on|off]

默认值：log_not_found on

使用环境：http，server，location

该指令用来启用或禁用404错误日志，这个指令可以用来禁止Nginx记录找不到robots.txt和favicon.ico这类文件的错误信息。

13.1.25　log_subrequest指令

语法：log_subrequest[on|off]

默认值：log_subrequest off

使用环境：http，server，location

该指令用来启动或禁止在access_log中记录类似rewrite rules、SSI requests等子请求。

13.1.26　msie_padding指令

语法：msie_padding[on|off]

默认值：msie_padding on

使用环境：http，server，location

此指令关闭或开启MSIE浏览器的msie_padding特性，若启用此选项，Nginx会为response头部填满至512字节，这样就阻止了相关浏览器激活友好错误页面，因此不会隐藏更多的错误信息。

13.1.27　msie_refresh指令

语法：msie_refresh[on|off]

默认值：msie_refresh off

使用环境：http，server，location

此指令允许或禁止为MSIE指派一个refresh而不是重定向。

13.1.28　open_file_cache指令

语法：open_file_cache max=N[inactive=time]|off

默认值：open_file_cache off

使用环境：http，server，location

该指令用于设置打开文件的缓存。以下信息可以被缓存：

·　打开文件描述符的文件大小和修改时间信息。

·　存在的目录信息。

·　搜索文件的错误信息：文件不存在，无权限读取等错误。

·　max——指定缓存的最大数量，当缓存数量不够用时，使用LRU规则清除最早写入、最近没有被访问过的缓存。

·　inactive——指定缓存的过期时间，默认值为60秒。

·　off——关闭缓存。

示例代码如下：

13.1.29　open_file_cache_errors指令

语法：open_file_cache_errors on|off

默认值：open_file_cache_errors off

使用环境：http，server，location

该指令设置是否开启搜索文件的缓存错误。

13.1.30　open_file_cache_min_uses指令

语法：open_file_cache_min_uses number

默认值：open_file_cache_min_uses 1

使用环境：http，server，location

该指令用于指定在open_file_cache指令设置的时间内文件的最小使用数。如果打开的文件超过该数量，则文件描述符会保持缓存中的打开状态。

13.1.31　open_file_cache_valid指令

语法：open_file_cache_valid time

默认值：open_file_cache_valid 60

使用环境：http，server，location

该指令用于指定检查open_file_cache指令中条款有效性的时间，单位为秒。

13.1.32　optimize_server_names指令

语法：optimize_server_names[on|off]

默认值：optimize_server_names on

使用环境：http，server

该指令激活或停用基于域名的虚拟主机的优化。特别地，影响了检查中使用的主机名重定向。如果打开优化选项，以及侦听所有基于域名的虚拟主机，监听一个IP地址和所有基于域名的服务器地址：端口对有相同的配置，然后名称不检查，并在执行请求重定向使用的第一台服务器的名称。

如果重定向必须使用主机名并且在客户端检查通过，那么这个参数必须设置为off。

注意：这个参数不建议在nginx 0.7.x版本中使用，请使用server_name_in_redirect。

13.1.33　port_in_redirect指令

语法：port_in_redirect[on|off]

默认值：port_in_redirect on

使用环境：http，server，location

该指令允许或阻止Nginx重定向过程中的端口操作。如果port_in_redirect为on，Nginx在请求重定向时则不会加上端口。

13.1.34　recursive_error_pages指令

语法：recursive_error_pages[on|off]

默认值：recursive_error_pages off

使用环境：http，server，location

该指令允许或禁止除了第一条error_page指令之外的error_page指令。

13.1.35　resolver指令

语法：resolver address

默认值：no

使用环境：http，server，location

13.1.36　resolver_timeout指令

语法：resolver_timeout time

默认值：30

使用环境：http，server，location

该指令用于解析超时时间。

13.1.37　root指令

语法：root path

默认值：root html

使用环境：http，server，location，if in location

该指令主要用来指定请求的文档根目录。例如，配置内容为location/i/{root/spool/w3;}时，请求URI地址“/i/top.gif”将返回文件“/spool/w3/i/top.gif”的内容给客户端。

13.1.38　satisfy_any指令

语法：satisfy_any[on|off]

默认值：satisfy_any off

使用环境：location

该指令用于检查至少一个成功的访问权限认证，它可以在NginxHttpAccess模块或NginxHttpAuthBasicModule中使用。

13.1.39　send_timeout指令

语法：send_timeout the time

默认值：send_timeout 60

使用环境：http，server，location

该指令用于设置发送给客户端的应答超时时间。超时时间是指进行了两次TCP握手，还没有转为established状态的时间。如果超过这个时间，客户端没有响应，Nginx则关闭连接。

13.1.40　sendfile指令

语法：sendfile[on|off]

默认值：sendfile off

使用环境：http，server，location

该指令启用或禁用sendfile()函数。sendfile()是作用于数据拷贝在两个文件描述符之间的操作函数，这个拷贝操作是在内核中操作的，所以称为“零拷贝”。sendfile函数比read和write函数要高效得多，因为read和write要把数据拷贝到用户应用层进行操作。但是，在Nginx的生产环境应用中，出现过启用sendfile比禁用sendfile效率更低的情况，所以，是否启用该函数须谨慎选择。

13.1.41　server指令

语法：server{...}

默认值：no

使用环境：http

该指令用于配置虚拟主机。在server{......}中，使用listen指令来为一个虚拟主机设置监听的IP和端口，使用server_name指令来设置不同的虚拟主机名称。

13.1.42　server_name指令

语法：server_name name[...]

默认值：server_name hostname

使用环境：server

该指令主要完成以下两项操作：

（1）根据客户端请求Header头信息中的Host域名，来匹配该请求应该由哪个虚拟主机配置server{...}来处理。

域名处理的优先级按照以下顺序执行：

A．全名。

B．以通配符开头的域名，例如“*.example.com”。

C．以通配符结尾的域名，例如“www.example.*”。

D．使用正则表达式的域名。

如果Header头信息中的Host域名在各server{...}中没有匹配项，该请求将按照以下优先级顺序由一个server{...}来处理：

A．listen指令被标记为default的server{...}。

B．第一个出现listen指令（或者默认为80端口）的server{...}。

（2）如果server_name_in_redirect设置为on，设置的主机名将被用于HTTP重定向。

示例代码如下：

第一个名称为服务器的基础名称，该虚拟主机的主机名（hostname）即为该名称。

可以使用通配符“*”来代替域名的前部分或后部分，例如：

以上两个服务器名称（example.com和*.example.com）可以写成一句：

服务器名称也可为使用正则表达式，在正则表达式加上“~”，例如：

服务器的基础名称将被用于HTTP重定向，如果客户端请求中没有Host头信息，或者Host头信息没有匹配server_name，你可以使用“*”强制Nginx在HTTP重定向中使用Host头（注意：“*”不能作为虚拟主机的第一个名称，但是，你可以使用一个伪名称“_”来代替第一个名称）：

注意：在Nginx 0.6版本中该处配置稍有不同：

从Nginx 0.7.12版本开始，支持空的服务器名称，用来匹配那些没有指定Host头信息的客户端请求：

从Nginx 0.8.25版本开始，可以在server_name正则表达式中使用命名的捕获变量（named captures），而不是数括号来获知匹配的捕获变量。

一些老的PCRE正则表达式库提供了类似以下的语法，如果你在使用命名的捕获变量中遇到问题，可以尝试使用以下配置：

13.1.43　server_name_in_redirect指令

语法：server_name_in_redirect on|off

默认值：server_name_in_redirect on

使用环境：http，server，location

如果server_name_in_redirect指令设置为on，Nginx将使用server_name指令设置的第一个名称来作重定向。如果server_name_in_redirect指令设置为on，Nginx将使用客户端请求中的Host头信息来作重定向。

13.1.44　server_names_hash_max_size指令

语法：server_names_hash_max_size number

默认值：server_names_hash_max_size 512

使用环境：http

该指令用于指定服务器名称哈希表的最大值。

13.1.45　server_names_hash_bucket_size指令

语法：server_names_hash_bucket_size number

默认值：server_names_hash_bucket_size 32/64/128

使用环境：http

该指令用于指定服务器名称哈希表的框大小。该默认值取决于CPU缓存。

13.1.46　server_tokens指令

语法：server_tokens on|off

默认值：server_tokens on

使用环境：http，server，location

是否在错误页面或服务器Header头中输出Nginx版本号给客户端浏览器。

13.1.47　tcp_nodelay指令

语法：tcp_nodelay[on|off]

默认值：tcp_nodelay on

使用环境：http，server，location

该指令允许或禁止使用套接字选项TCP_NODELAY，仅适用于keep-alive连接。

默认情况下数据发送时，内核并不会马上发送，它可能等待更多的字节组成一个包，这样可以提高IO发送的效率。但在每次只发送很少字节的程序中，使用TCP_NODELAY时等待时间就会比较长。请根据实际情况选择是否开启。

13.1.48　tcp_nopush指令

语法：tcp_nopush[on|off]

默认值：tcp_nopush off

使用环境：http，server，location

该指令允许或禁止使用FreeBSD上的TCP_NOPUSH，或者Linux上的TCP_CORK套接字选项。该选择仅在sendfile开启的时候才起作用。设置该选择的原因是Nginx在Linux和FreeBSD 4.x上，试图在一个包中发送它的HTTP应答头。

13.1.49　try_files指令

语法：try_files param1[param2...paramN]fallback

默认值：none

使用环境：location

该指令用于告诉Nginx测试每个文件是否存在，并且使用首先找到的文件作为URI。如果没有找到文件，则调用location fallback（“fallback”可以为任何名称）。fallback是一个请求参数，它可以是一个命名的location，也可以是任何可能的URI。示例：

13.1.50　types指令

语法：types{...}

使用环境：http，server，location

该指令用于应答的MIME-types对应的扩展名，一个MIME-types可以对应多个扩展名。默认情况下，使用这些扩展名：

完整的MIME-types与扩展名的映射表在被包含的conf/mime.types文件中。

如果你想让某些location使用MIME类型：application/octet-stream，则可以使用以下配置：

13.1.51　HTTP核心模块中可以使用的变量

Nginx HTTP核心模块支持一些与Apache变量名称相同的内置变量，例如：$http_user_agent、$http_cookie，此外，还支持一些Nginx特有的其他变量：

$arg_PARAMETER

该变量包含了当查询字符串时，GET请求可变参数的值。

$args

这个变量等于请求行中的参数。

$binary_remote_addr

二进制格式的客户端地址。

$content_length

这个变量等于客户端请求头中的content-length值。

$content_type

这个变量等于客户端请求头中的content-type值。

$cookie_COOKIE

客户端请求Header头中的cookie变量。前缀“$cookie_”加上cookie名称的变量，该变量的值即为cookie名称的值。例如客户端请求头中某一行的内容为“Cookie:PHPSESSID=6fd171f5c1b4e42783f2b6b9d7124065;userid=2”，那么Nginx变量$cookie_userid的值则为2。

$document_root

这个变量等于当前请求所属的root指令设置的文档根目录路径。

$document_uri

这个变量与$uri类似。

$host

这个变量等于客户端请求头中的Host值，如果客户端请求头中没有Host值，那么这个变量等于为当前请求提供服务的服务器名称。

$http_HEADER

客户端请求header头中的变量。将客户端请求头每行名称中的横线“-”换成下划线“_”，大写字母转为小写字母，前缀加上“$http_”，即为该名称对应的变量。例如客户端请求头中cookie行的内容为“Accept-Encoding: gzip, deflate”，那么在Nginx中则有一个变量$http_accept-encoding，该变量的值为“gzip, deflate”。类似的变量有：$http_user_agent、$http_referer...

$is_args

如果$args已经设置，则该变量的值为"?"，否则为""。

$limit_rate

这个变量允许限制连接速率。

$query_string

这个与$args类似。

$remote_addr

客户端的IP地址。

$remote_port

客户端的端口。

$remote_user

这个变量等于用户名，Auth Basic模块中会使用到该变量。

$request_filename

这个变量等于当前请求的文件路径，由root、alias指令及URI请求生成。

$request_body

这个变量（0.7.58以上版本支持）包含了请求的body主体内容。在使用proxy_pass或fastcgi_pass指令的location中，这个变量比较有意义。

$request_body_file

客户端请求主体的临时文件名。

$request_method

这个变量等于HTTP请求的动作，常使用的动作为GET或POST。

在0.8.20及之前的版本中，这个变量总是等于主请求的动作名，如果当前请求是一个子请求，该变量的值并不是当前请求的动作名。

$request_uri

这个变量等于带有参数的完整URI。

$scheme

HTTP方法（例如IE浏览器支持的http和https）。按需使用，示例如下：

这个变量等于服务器的地址。通常，在一次系统调用后，该变量的值可以确定。如果为了避开系统调用，则要在listen指令中指出地址，并且使用参数bind。

$server_name

服务器的主机名。

$server_port

请求到达的服务器端口。

$server_protocol

这个变量等于请求采用的协议，通常该变量的值为HTTP/1.0或HTTP/1.1。

$uri

这个变量等于当前请求的URI（不带参数），它可以不同于最初的值，例如可以被内部重定向所改变。

13.2　HTTP Upstream模块

HTTP Upstream模块是与反向代理、负载均衡相关的模块，包含ip_hash、server、upstream等指令。这一模块已在前面第6章中做了详细介绍。

13.3　HTTP Access模块

HTTP Access模块提供了一个简单的基于host名称的访问控制。通过该模块，可以允许或禁止指定的IP地址或IP段访问某些虚拟主机或目录。

示例如下：

13.3.1　allow指令

语法：allow[address|CIDR|all]

默认值：none

使用环境：http，server，location，limit_except

允许指定的IP地址或IP段访问某些虚拟主机或目录。

13.3.2　deny指令

语法：deny[address|CIDR|all]

默认值：none

使用环境：http，server，location，limit_except

禁止指定的IP地址或IP段访问某些虚拟主机或目录。

13.4　HTTP Auth Basic模块

该模块采用基于HTTP基本身份验证的用户名和密码登录方式，来保护你的虚拟主机或目录。示例如下：

13.4.1　auth_basic指令

语法：auth_basic[text|off]

默认值：auth_basic off

使用环境：http，server，location，limit_except

该指令用于指定弹出的用户名和密码登录框中提示的名称，例如设置auth_basic名称为“Kingsoft”，效果如图13-1所示：

图13-1　auth_basic指令弹出的用户名和密码登录框

如果设置auth_basic off，则关闭HTTP基本身份验证。

13.4.2　auth_basic_user_file指令

语法：auth_basic_user_file the_file

默认值：no

使用环境：http，server，location，limit_except

该指令用于设置htpasswd密码文件的名称。在Nginx 0.6.7版本之前，htpasswd密码文件相对路径为Nginx安装目录，在Nginx 0.6.7版本之后，htpasswd密码文件的相对路径为nginx.conf文件所在的路径。如果您的Nginx安装在/usr/local/nginx/路径下，并设置了“auth_basic_user_file htpasswd;”，那么Nginx将读取/usr/local/nginx/conf/htpasswd文件。

htpasswd密码文件的格式如下：

1　密码必须使用函数crypt(3)加密，你可以通过Apache的htpasswd程序生成密码。

你也可以使用perl创建密码文件，pw.pl的内容如下：

然后执行：

papAq5PwY/QQM就是password的crypt()密码。

13.5　HTTP Autoindex模块

该模块用于提供自动目录列表。该模块只有在找不到默认的index文件时才启用。

13.5.1　autoindex指令

语法：autoindex[on|off]

默认值：autoindex off

使用环境：http，server，location

该指令允许和禁止自动目录列表。

13.5.2　autoindex_exact_size指令

语法：autoindex_exact_size[on|off]

默认值：autoindex_exact_size on

使用环境：http，server，location

该指令用于设置按照什么单位显示目录列表中文件的大小、默认字节，或者KB、MB、GB。

13.5.3　autoindex_localtime指令

语法：autoindex_localtime[on|off]

默认值：autoindex_localtime off

使用环境：http，server，location

该指令的参数为on时，采用本地时间显示文件修改时间，为off时，采用GMT格林尼治时间显示文件修改时间。

13.6　HTTP Browser模块

该模块可以根据客户端“User-agent”请求头中的信息创建变量。

$modern_browser——如果浏览器被识别为新浏览器，则等于modern_browser_value指令设置的值。

$ancient_browser——如果浏览器被识别为旧浏览器，则等于ancient_browser_value指令设置的值。

$msie——如果浏览器被鉴定为MSIE浏览器，该变量的值则为1。

配置示例如下：

（1）根据浏览器类型选择不同的首页文件，代码如下：

（2）重定向旧的浏览器，代码如下：

13.6.1　ancient_browser指令

语法：ancient_browser line[line...]

默认值：no

使用环境：http，server，location

该指令用于设置“User-agent”头信息中包含的旧的浏览器名称，多个浏览器名称可以用空格分隔。特殊的行可以采用正则表达式，例如“^Mozilla/[1-4]”。

13.6.2　ancient_browser_value指令

语法：ancient_browser_value line

默认值：ancient_browser_value 1

使用环境：http，server，location

该指令为$ancient_browser变量指定Value值。

13.6.3　modern_browser指令

语法：modern_browser browser version|unlisted

默认值：no

使用环境：http，server，location

该指令用于设置新浏览器类型，可选的浏览器参数只能是msie、gecko（Mozilla-based浏览器）opera、safari、konqueror几种。

版本可以设置为X、X.X、X.X.X或X.X.X.X，它们各自的最大值分别为4000、4000.99、4000.99.99和4000.99.99.99。

特殊的值“unlisted”表示即不属于新浏览器，也不属于旧浏览器的其他浏览器类型。

如果“User-Agent”头信息为空值，将会被归为新浏览器。

代码13-3的配置可以判断客户端浏览器是否为手机浏览器：

代码13-3

13.6.4　modern_browser_value指令

语法：modern_browser_value line

默认值：modern_browser_value 1

使用环境：http，server，location

该变量为$modern_browser变量指定Value值。

13.7　HTTP Charset模块

该模块用来添加文本编码类型到HTTP应答头“Content-Type indicated”。此外，该模块还能够将服务器端网页原来的文本编码转换成另一种文本编码，输出给客户端。例如：

13.7.1 charset指令

语法：charset encoding|off

默认值：charset off

使用环境：http，server，location，if in location

该指令用来添加文本编码类型到HTTP应答头“Content-Type indicated”。如果编码与source_charset指令设置的编码不一样，将进行重编码。参数为“off”。

13.7.2　charset_map指令

语法：charset_map encoding1 encoding2{...}

默认值：no

使用环境：http，server，location

该指令用来添加字符集映射，可以将一种编码映射成另一种编码。代码符号以十六进制方式表示。该指令主要是针对俄文的，示例如下：

以上示例是为了将KOI8-R编码转换成Windows-1251编码。

美国英语使用的编码是ASCII（American National Standard Code）编码，它是一种7位（128个字符）编码，只包含拉丁字母和一些符号，因此西里尔字符编码采用7位是不够的。KOI8-R（Kod Obmena Informatsii，俄语Код Обмена Инфармации的拉丁写法，缩写为КОИ8）是一种官方的Internet标准编码，它是一种包含西里尔字母的8位编码，它是由KOI8派生的，KOI8-R中的8就是指8位的意思，R指俄语（KOI8-U使用于乌克兰语），这在Cyrillic Character Set（RFC, Request For Comments，请求注解，Internet标准草案，1489）的注册纪录中有详细描述。它同时也是事实上的e-mail和NNTP（Network News Transfer Protocol，网络新闻传输协议）的西里尔字符标准。另外，它还是Unix系统的标准编码，如图13-2所示。

图13-2　KOI8-R编码

CP1251是MS Widows编码页1251，它是Microsoft西里尔字符的标准编码，它也恰恰是MS Windows平台实事上的西里尔字符标准，如图13-3所示。

图13-3　Widows-CP1251编码

13.7.3　override_charset指令

语法：override_charset on|off

默认值：override_charset off

使用环境：http，server，location，if in location

当该指令开启时，如果后端的FASTCGI服务器响应头带有“Content-Type”头信息，将开启编码转换。

13.7.4　source_charset指令

语法：source_charset encoding

默认值：no

使用环境：http，server，location，if in location

该指令用于设定原始编码，如果编码与charset指令设置的编码不一样，将进行重编码。

13.8　HTTP Empty Gif模块

该指令可以保持一个1×1像素的透明GIF图片在内存中，当请求该图片时，能够得到非常快的响应速度。示例如下：

13.8.1　empty_gif指令

语法：empty_gif

默认值：n/a

使用环境：location

13.9　HTTP Fcgi模块

该模块用于设置Nginx与FastCGI进程交互，并通过传递参数来控制FastCGI进程工作。示例如代码13-4所示：

代码13-4

缓冲示例如代码13-5所示：

代码13-5

13.9.1　fastcgi_buffers指令

语法：fastcgi_buffers the_number is_size;

默认值：fastcgi_buffers 8 4k/8k;

使用环境：http，server，location

该指令设置了读取FastCGI进程返回信息的缓冲区数量和大小。默认情况下，一个缓冲区的大小应该跟操作系统的页大小一样，默认为4k/8k自动选择。

你可以通过以下命令查看系统页大小：

或

或者编译以下C代码来查看：

13.9.2　fastcgi_buffer_size指令

语法：fastcgi_buffer_size the_size

默认值：fastcgi_buffer_size 4k/8k

使用环境：http，server，location

该指令设置FastCGI服务器相应头部的缓冲区大小。通常情况下，该缓冲区的大小设置等于fastcgi_buffers指令设置的一个缓冲区的大小。默认为4k/8k自动选择。

13.9.3　fastcgi_cache指令

语法：fastcgi_cache zone;

默认值：off

使用环境：http，server，location

该指令用来设置缓存在共享内存中的名称。一款区域可能被几个地方引用。

13.9.4　fastcgi_cache_key指令

语法：fastcgi_cache_key line;

默认值：none

使用环境：http，server，location

该指令用来设置被缓存的key，示例如下：

13.9.5　fastcgi_cache_methods指令

语法：fastcgi_cache_methods[GET HEAD POST];

默认值：fastcgi_cache_methods GET HEAD;

使用环境：main，http，location

该指令用于设置哪些HTTP请求可以被缓存。参数可选值为GET、HEAD、POST，默认值为GET、HEAD。另外，如果你只设置“fastcgi_cache_methods POST;”，GET/HEAD的缓存不会被禁止。

13.9.6　fastcgi_index指令

语法：fastcgi_index file

默认值：none

使用环境：http，server，location

如果请求的FastCGI URI以“/”斜线结束，该指令设置的文件会被附加到URI的后面并保存在变量$fastcgi_script_name中。

13.9.7　fastcgi_hide_header指令

语法：fastcgi_hide_header name

使用环境：http，server，location

默认情况下，Nginx不会将FastCGI进程返回的“Status”、“X-Accel-...”Header头信息返回给客户端。该指令可以被用来隐藏其他的Header头信息。

如果需要“Status”、“X-Accel-...”消息头，就须要使用fastcgi_pass_header指令让FastCGI强制发送消息头给客户端。

13.9.8　fastcgi_ignore_client_abort指令

语法：fastcgi_ignore_client_abort on|off

默认值：fastcgi_ignore_client_abort off

使用环境：http，server，location

如果客户端中断对服务器的请求，则该指令可决定当前对FastCGI的请求是否该中断。

13.9.9　fastcgi_intercept_errors指令

语法：fastcgi_intercept_errors on|off

默认值：fastcgi_intercept_errors off

使用环境：http，server，location

该指令用来决定是否要把客户端转向4xx和5xx错误页，或者允许Nginx自动指定错误页。

注意：你需要在此明确错误页，它才是有用的。Igor曾说：“如果没有定制的处理机制，Nginx不会拦截一个没有默认页的错误。Nginx只会拦截一些小的错误，放过一些其他错误。

13.9.10　fastcgi_max_temp_file_size指令

语法：fastcgi_max_temp_file_size 0

该指令用于关闭磁盘缓冲。

13.9.11　fastcgi_param指令

语法：fastcgi_param parameter value

默认值：none

使用环境：http，server，location

该指令指定的参数，将被传递给FastCGI-server。

它可能使用字符串、变量及其它们的组合来作为参数值。如果不在此制定参数，它就会继承外层设置；如果在此设置了参数，将清除外层相关设置，仅启用本层设置。

下面是一个例子，对PHP来说的最精简的必要参数：

参数SCRIPT_FILENAME是PHP用来确定执行脚本的名字，而参数QUERY_STRING是它的一个子参数。

如果要处理POST，那么这三个附加参数是必要的：

如果PHP在编译时使用了——enable-force-cgi-redirect选项，设置参数REDIRECT_STATUS的值为200就是必须的了。

13.9.12　fastcgi_pass指令

语法：fastcgi_pass fastcgi-server

默认值：none

使用环境：location，if in location

该指令用于指定FastCGI服务器监听的端口或Unix套接字。

示例如下：

使用Unix套接字的示例如下：

如果有多台FastCGI服务器，你也可以使用upstream指令指定FastCGI服务器，示例如下：

13.9.13　fastcgi_pass_header指令

语法：fastcgi_pass_header name

默认值：http，server，location

13.9.14　fastcgi_read_timeout指令

语法：fastcgi_read_timeout time

默认值：60

使用环境：http，server，location

该指令用于设置upstream模块等待FastCGI进程发送数据的超时时间，默认值为60秒，如果你有执行时间较长的FastCGI程序，则须更改此值。

13.9.15　fastcgi_redirect_errors指令

语法：fastcgi_redirect_errors on|off

该指令用于开启或关闭FastCGI错误重定向。

13.9.16　fastcgi_split_path_info指令

语法：fastcgi_split_path_info regex

使用环境：location

Nginx版本要求：>=0.7.31

13.10　geo模块

geo模块主要用于做全局负载均衡，可以根据不同的客户端IP访问到不同的服务器。一些针对不同地区的客户，使用不同的服务器去处理的需求，可以使用geo模块。

geo简单的配置示例如下：

下面，我们来看geo全局负载均衡与upstream反向代理的配合使用，示例如代码13-6所示：

代码13-6

13.10.1　geo指令

语法：geo[$ip_variable]$variable{...}

默认值：none

使用环境：http

geo指令默认使用客户端的IP地址（变量$remote_addr的值）来进行全局负载均衡，从Nginx 0.7.27版本开始，可以支持使用指定的变量来做全局负载均衡，例如：

geo指令支持以下描述：

default：任何IP地址，相当于0.0.0.0/0。

include：可以引用一个文本文件，里面包含geo的配置内容。当geo配置的IP段较多时，可以将IP段写在另一个配置文件中，并引用进来。

ranges：从Nginx 0.7.23版本开始，支持使用区间形式来指定IP段。该指令必须写在geo配置环境的第一行。

Default、include描述示例代码如13-7所示：

代码13-7

引用的配置文件conf/geo.conf的内容如下：

当指定的IP段区间存在包含关系时，取最精确的配值。例如在以下示例中，IP地址127.0.0.1取得的value值为ru，而不是us。

Ranges区间形式指定IP段示例如代码13-8所示：

代码13-8

13.11　Gzip模块

Gzip模块主要用于对返回给客户端的网页采用gzip进行压缩输出。

目前，90％的浏览器都支持gzip和deflate两种压缩格式。如果浏览器支持gzip压缩，就会在HTTP请求头中发送一行“Accept-Encoding:gzip,deflate”，这时候Nginx服务器可以输出经过gzip压缩后的页面给浏览器，浏览器再解压。这种方式可以将网络线路上传输的大量数据消减60％以上，不仅节省了服务器带宽，同时加速了用户的下载速度和体验。

一个典型的IE7浏览器HTTP GET请求头的信息如代码13-9所示：

代码13-9

13.11.1　gzip指令

语法：gzip on|off

默认值：gzip off

使用环境：http，server，location，if (x) location

该指令用于开启或关闭gzip模块。

13.11.2　gzip_buffers指令

语法：gzip_buffers number size

默认值：gzip_buffers 4 4k/8k

使用环境：http，server，location

设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。例如4 4k代表以4k为单位，按照原始数据大小以4k为单位的4倍申请内存。4 8k代表以8k为单位，按照原始数据大小以8k为单位的4倍申请内存。

如果没有设置，默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。

13.11.3　gzip_comp_level指令

语法：gzip_comp_level 1..9

默认值：zip_comp_level 1

使用环境：http，server，location

gzip压缩比，1压缩比最小处理速度最快，9压缩比最大但处理速度最慢（传输快但比较消耗cpu）。

13.11.4　gzip_min_length指令

语法：gzip_min_length length

默认值：gzip_min_length 0

使用环境：http，server，location

设置允许压缩的页面最小字节数，页面字节数从header头的Content-Length中进行获取。默认值是0，不管页面多大都压缩。建议设置成大于1k的字节数，小于1k可能会越压越大。即：gzip_min_length 1024。

13.11.5　gzip_http_version指令

语法：gzip_http_version 1.0|1.1

默认值：gzip_http_version 1.1

使用环境：http，server，location

识别http的协议版本。由于早期的一些浏览器或http客户端，可能不支持gzip自解压，用户就会看到乱码，所以做一些判断还是有必要的[1]。

13.11.6　gzip_proxied指令

语法：gzip_proxied[off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any]...

默认值：gzip_proxied off

使用环境：http，server，location

Nginx作为反向代理的时候启用，开启或关闭后端服务器返回的结果，匹配的前提是后端服务器必须要返回包含“Via”的header头。

off——关闭所有的代理结果数据的压缩。

expired——启用压缩，如果header头中包含“Expires”头信息。

no-cache——启用压缩，如果header头中包含“Cache-Control:no-cache”头信息。

no-store——启用压缩，如果header头中包含“Cache-Control:no-store”头信息。

private——启用压缩，如果header头中包含“Cache-Control:private”头信息。

no_last_modified——启用压缩，如果header头中不包含“Last-Modified”头信息。

no_etag——启用压缩，如果header头中不包含“ETag”头信息。

auth——启用压缩，如果header头中包含“Authorization”头信息。

any——无条件启用压缩。

13.11.7　gzip_types指令

语法：gzip_types mime-type[mime-type...]

默认值：gzip_types text/html

使用环境：http，server，location

匹配mime类型进行压缩，（无论是否指定）“text/html”类型总是会被压缩的。

注意：如果作为http server来使用，主配置文件中要包含文件类型配置文件。

如果你希望压缩常规的文件类型，可以写成代码13-10这样。

代码13-10

13.12　HTTP Headers模块

这一组指令主要用来设置Nginx返回网页内容给用户时，附加的Header头信息。示例：

13.12.1　add_header指令

语法：add_header name value

默认值：none

使用环境：http，server，location

当HTTP应答状态码为200、204、301、302或304的时候，增加指定的Header头，其中Header头的值可以使用变量。

13.12.2　expires指令

语法：expires[time|epoch|max|off]

默认值：expires off

使用环境：http，server，location

使用本指令可以控制HTTP应答中的“Expires”和“Cache-Control”Header头信息，起到控制浏览器端页面缓存的作用。

可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的time值来获得。

epoch指定“Expires”的值为1 January, 1970, 00:00:01 GMT。

max指定“Expires”的值为31 December 2037 23:59:59 GMT，“Cache-Control”的值为10年。

-1指定“Expires”的值为服务器当前时间-1s，即永远过期。

“Cache-Control”头标的值由您指定的时间来决定：

负数：Cache-Control: no-cache。

正数或零：Cache-Control: max-age=#, #为您指定时间的秒数。

“off”表示不修改“Expires”和“Cache-Control”的值。

注意：expires指令同样也只能工作于200、204、301、302或304应答状态。

13.13　HTTP Index模块

该模块可以用于指定虚拟主机目录下的默认首页文件名称。例如：

也可以指定多个默认首页文件名称，如果您指定了多个文件，那么将按照从左到右的顺序逐个查找。可以在列表末尾加上一个绝对路径名的文件。例如：

13.13.1　index指令

语法：index file-path[file-path[...]];

默认值：no

使用环境：server，location

该指令用来指定做默认文档的文件名，可以在文件名处使用变量。如果您指定了多个文件，那么将按照您指定的顺序逐个查找。可以在列表末尾加上一个绝对路径名的文件。

示例如下：

13.14　HTTP Referer模块

HTTP Referer是Header的一部分，当浏览器向Web服务器发送请求的时候，一般会带上Referer，告诉服务器我是从哪个页面链接过来的，服务器借此可以获得一些信息用于处理，例如防止未经允许的网站盗链图片、文件等。因为HTTP Referer头信息是可以通过程序来伪装生成的，所以，通过Referer信息防盗链并非100％可靠，但是，它能够限制大部分的盗链情况。示例如代码13-11所示：

代码13-11

13.14.1　valid_referers指令

语法：valid_referers[none|blocked|server_names]...

默认值：none

使用环境：server，location

该指令会根据Referer Header头的内容分配一个值0或1给变量$invalid_referer。如果Referer Header头不符合valid_referers指令设置的有效Referer，变量$invalid_referer将被设置为1（详情请见代码13-11示例）。

该指令的参数可以为以下内容：

none：表示无Referer值的情况；

blocked：表示Referer值被防火墙进行伪装，例如：“Referer:XXXXXXX”；

server_names：表示一个或多个主机名称。从Nginx 0.5.33版本开始，server_names中可以使用通配符“*”号。

13.15　HTTP Limit Zone模块

该模块用于针对条件，进行会话的并发连接数控制，例如限制每个IP的并发连接数等。配置示例如代码13-12所示：

代码13-12

13.15.1　limit_zone指令

语法：limit_zone zone_name $variable memory_max_size

默认值：no

使用环境：http

该指令定义了一个数据区，其中记录会话状态信息。$variable定义判断会话的变量；memory_max_size定义内存记录区的总容量。示例如下：

在以上示例中，定义一个叫“one”的记录区，总容量为10MB，以变量$binary_remote_addr作为会话的判断基准（即一个地址一个会话）。

您可能注意到了，在这里使用的是$binary_remote_addr而不是$remote_addr。

$remote_addr的长度为7至15 bytes，会话信息的长度为32或64 bytes。而$binary_remote_addr的长度为4 bytes，会话信息的长度为32 bytes。

当记录区的大小为1MB的时候，大约可以记录32000个会话信息（一个会话占用32 bytes）。

13.15.2　limit_conn指令

语法：limit_conn zone_name max_clients_per_ip

默认值：no

使用环境：http，server，location

该指令用于指定一个会话最大的并发连接数。当超过指定的最大并发连接数时，服务器将返回“Service unavailable”（503）。

示例：

以上示例中，定义一个叫“one”的记录区，总容量为10MB，以变量$binary_remote_addr作为会话的判断基准（即一个地址一个会话）。限制/download/目录下，一个会话只能进行一个连接。简单来说，就是限制/download/目录下，一个IP只能发起一个连接，多于一个，一律返回“Service unavailable”（503）状态。

13.16　HTTP Limit Req模块

该模块允许你对Session会话、单个客户端IP地址，限制指定单位时间内的并发请求数。你可以在一定程度上减轻对应用服务器的DOS恶意攻击。配置示例如代码13-13所示：

代码13-13

13.16.1　limit_ req_zone指令

语法：limit_req_zone $session_variable zone=name_of_zone:size rate=rate

默认值：none

使用环境：http

该指令用于定义一块内存存储区，用来存储Session会话的状态，Session的变量由指定的变量构成，通常可以设置为存储客户端IP的变量$binary_remote_addr。以下是一个示例：

在本例中，为Session会话状态分配了一个名为one的10MB内存存储区，限制了每秒只接受一个IP的一次请求（1 Request/Sec）。这里使用变量$binary_remote_addr代替$remote_addr，可以为每个会话减少64字节的内存存储空间，从而使得1MB内存可以存储大概16000个会话状态。

速度限制的条件可以设置为“请求数／秒（r/s）”或“请求数／分钟（r/m）”，比率必须为整型数，如果你要设置少于每秒1个请求数的值，例如“1个请求／2秒”，你应该设置为“30r/m”。

13.16.2　limit_req指令

语法：limit_req zone=zone burst=burst[nodelay]

默认值：none

使用环境：http，server，location

该指令用于指定使用的内存存储区（zone）名称，以及最大的突发请求数（burse）。如果请求的速率超过limit_req_zone指令中设置的速率，这些请求将被延迟处理，以便能够按照limit_req_zone指令中设定的速度处理请求。多余的请求将被延迟处理，直到这些请求的数量不超过burst参数中规定的数量。在这种情况下，请求将获得服务不可用信息：“Service unavailable”（503错误代码）。Burst的值默认为0。

示例如下：

在该示例中，允许一个用户平均每秒不超过1个请求，同时处理的查询数量最多不超过5个。如果查询数小于burst值，延迟不是必须的，你可以使用nodelay参数设置为非延迟：

13.17　HTTP Log模块

该指令用于控制Nginx的日志格式。示例如下：

13.17.1　access_log指令

语法：access_log path[format[buffer=size|off]]

默认值：access_log log/access.log combined

使用环境：http，server，location

该指令用于设置日志文件的路径、格式和缓冲区大小。使用“off”作为唯一参数，将不记录日志文件。如果没有指定日志格式，将默认采用“combined”格式。缓冲区的大小必须小于写入磁盘文件的原子记录大小。这个大小对于FreeBSD 3.0-6.0系统无限制。

从Nginx 0.7.4版本开始，日志文件的路径可以包含变量，但是有一些限制：

Nginx的Worker用户必须有权限去创建文件；

缓冲将不会工作；

每个请求到来时，日志文件将被打开，在日志写入后，又将立即关闭日志文件。频繁使用的文件描述符将被保存到open_log_file_cache指令设置的缓冲区中，关于日志的轮换，必须随着时间的推移被记住（在open_log_file_cache指令的参数中设置），日志仍然继续记录在旧的文件中。

Nginx支持为每个location环境设置强大的日志格式。相同的访问可以被同时记录在一个或多个日志文件中。

13.17.2　log_format指令

语法：log_format name format [format...]

默认值：log_format combined "..."

使用环境：http, server

该指令用来描述日志格式。在日志的格式中，可以使用Nginx的大多数通用变量，以及一些仅在写日志时存在的变量，如下：

$body_bytes_sent——减去应答头之后的传输给客户端的字节数。

$bytes_sent——传输给客户端的字节数。

$connection——连接数。

$msec——正在写日志的当前时间（精确到微秒级，即百万分之一秒）。

$pipe——如果请求是pipelined管道。

$request_length——请求的主体（body）长度。

$request_time——请求在Nginx开始处理之前所消耗的时间（包括TCP连接时间、客户端的HTTP发送时间等），单位为毫秒（在Nginx 0.5.19版本之前，单位为秒）。

$status——应答状态。

$time_local——写入日志的本地服务器时间。

$http_x_forwarded_for——上级反向代理服务器中通常用于记录用户真实IP的X-Forward信息。

13.17.3　log_format_combined指令

Nginx有一个名为“combined”的预定义（内部已经定义的）指令，相当于以下设置：

13.17.4　open_log_file_cache指令

语法：open_log_file_cache max=N[inactive=time][min_uses=N][valid=time]|off

默认值：open_log_file_cache off

使用环境：http server location

该指令用于为带有变量的日志文件路径所频繁使用的文件描述符设置缓存。指令选项如下：

max——缓存中可以存放的最大文件描述符。缓存满之后，根据LRU算法删除最早缓存，并且最近没有被使用的文件描述符。

inactive——设置一个时间，在该时间范围内没有被使用的文件描述符将被移除。默认时间为10秒。

min_uses——设置一个文件描述符在inactive参数规定的单位时间范围内，最少使用的次数。满足最少使用次数的文件描述符才会被放入缓存中。默认的最少使用次数为1次。

valid——设置检查同名文件是否存在的时间周期，默认为60秒。

off——禁用缓存。

13.18　HTTP Map模块

该模块允许你去分类，或者映射一组值到一组不同的值，并将这些值存储在一个变量中。示例如代码13-14所示：

代码13-14

我们可以使用本模块的映射，来代替写许多的server/location指令或redirect重定向规则，如代码13-15所示：

代码13-15

13.18.1　map指令

语法：map $varl $var2{...}

默认值：none

使用环境：http

map指令定义了被用来设置变量的映射表，该指令有3个特殊的参数：

default——指定无匹配内容时的默认值；

hostnames——支持近似域名查找。示例如下：

另外，以“.”开头的字符串，将用来精确匹配以该字符串结尾的主机名（域名）。例如，以下两台记录：

可以用一条记录来代替：

include——包含一个含有映射信息的文件。它可以包含多个文件。

13.18.2　map_hash_max_size指令

语法：map_hash_max_size number

默认值：map_hash_max_size 2048

使用环境：http

该指令用于设置保存变量映射关系的哈希表的最大值。

13.18.3　map_hash_bucket_size指令

语法：map_hash_bucket_size n

默认值：map_hash_bucket_size 32/64/128

使用环境：http

该指令用于设置一张哈希表中映射变量的最大值。默认值取决于处理器的缓存大小。

13.19　HTTP Memcached模块

Memcached是一个高性能的分布式内存对象缓存系统，用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数，从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键／值对的hashmap。其守护进程（daemon）是用C写的，但是客户端可以用任何语言来编写，并通过Memcached协议与守护进程通信，且它并不提供冗余（例如，复制其hashmap条目）；当某个服务器停止运行或崩溃了，所有存放在该服务器上的键／值对都将丢失。

Memcached（官方网站：http://www.memcached.org/）由Danga Interactive开发，用于提升LiveJournal.com访问速度。LJ每秒动态页面访问量几千次，用户700万。Memcached将数据库负载大幅降低，以便更好地分配资源，更快地访问。

Memcached服务器端的编译安装如代码13-16所示：

代码13-16

启动Memcached服务器端：

Nginx中的Memcached模块，相当于Memcached的客户端软件，使用本模块可以完成一些简单的缓存任务。Nginx官方计划在不久的将来继续完善这一模块。

配置示例如代码13-17所示：

代码13-17

或者在Nginx 0.7.x版本中使用如代码13-18所示的内容：

代码13-18

接下来，我们结合PHP，使用Memcached模块做缓存。在代码13-19所示示例中，如果用户访问以“/cache/”开始的URI，则读取以URI为key的Memcached缓存内存，显示给用户。如果key不存在，则重定向到“/write_memcached.php”程序文件，该PHP程序会往Memcached内写入以URI为key的缓存数据，缓存时间为120秒。

代码13-19

write_memcached.php文件的内容如代码13-20所示：

代码13-20

13.19.1　memcached_pass指令

语法：memcached_pass[name:port]

默认值：none

使用环境：http, server, location

该指令用于设置Memcached服务器的地址和端口，Memcached的key为“/uri?args”。

从Nginx 0.5.9版本开始，Memcached的key存储在$memcached_key变量中。

13.19.2　memcached_connect_timeout指令

语法：memcached_connect_timeout[time]

默认值：60000

使用环境：http, server, location

该指令用于设置连接Memcached服务器的超时时间，单位为毫秒。

13.19.3　memcached_read_timeout指令

语法：memcached_read_timeout[time]

默认值：60000

使用环境：http, server, location

该指令用于设置从Memcached服务器读取数据的超时时间，单位为毫秒。

13.19.4　memcached_send_timeout指令

语法：memcached_send_timeout[time]

默认值：60000

使用环境：http, server, location

该指令用于设置向Memcached服务器发送数据的超时时间，单位为毫秒。

13.19.5　memcached_buffer_size指令

语法：memcached_buffer_size[size]

默认值：see getpagesize (2)

使用环境：http, server, location

该指令用于设置接收、发送数据的缓冲区大小，单位为字节。

13.19.6　memcached_next_upstream指令

语法：memcached_next_upstream[error|timeout|invalid_response|not_found|off]

默认值：error timeout

使用环境：http, server, location

该指令用于指定在哪种错误条件下，将请求转发到upstream负载均衡服务器池中的另一台服务器。仅适用于当upstream中的memcached_pass指令拥有两个或两个以上后端服务器的情况。

13.19.7　HTTP Memcached模块中的变量

该变量的内容为Memcached的key值。通常情况下，以当前请求的URI作为Memcached的key，可以设置变量为：

13.19.8　第三方的Memcached模块

除了Nginx官方的Memcached模块之外，还有一个第三方的Memcached模块，几乎支持Memcached所有的功能。但是，考虑到第三方模块通常缺乏稳定性与兼容性，这里就不再详细介绍，感兴趣的朋友可以访问：http://wiki.nginx.org/NginxHttpMemcModule，获取更多的信息。

13.20　HTTP Proxy模块

该模块用于转发请求到其他的服务器。Keep-alive是指在HTTP/1.1协议中，同一个连接中发出和接收多次HTTP请求，节省了创建TCP连接过程的时间开销。而HTTP/1.0协议不具备keep-alive请求的能力。因此，在HTTP/1.0协议中，每一个到后端的请求都会创建一个连接，传输完成后会删除这个连接。Nginx采用HTTP/1.1协议与浏览器进行通信，采用HTTP/1.0协议与后端服务器进行通信。

示例如下：

注意：当使用HTTP代理模块时（或者当使用FastCGI时），整个客户端请求在传递给后端服务器之前，将被Nginx缓存，数据传输的进度测量将不准确。

13.20.1　proxy_buffer_size指令

语法：proxy_buffer_size the_size

默认值：proxy_buffer_size 4k/8k

使用环境：http, server, location

该指令用于设置从被代理服务器获取的第一部分应答信息的缓冲区大小，这个缓存区间会保存用户的头信息以供Nginx进行规则处理，一般只要能保存下头信息即可。但是，也可以将该值设置得较小。

13.20.2　proxy_buffering指令

语法：proxy_buffering on|off

默认值：proxy_buffering on

使用环境：http, server, location

该指令用于开启对被代理的服务器的应答缓冲。

如果缓冲开启，Nginx会假设被代理服务器的应答尽可能地快，并将其保存到缓冲区。可以使用指令proxy_buffer_size和proxy_buffers来配置缓冲区信息。

如果应答内容无法完全放在内存中，那么应答内容的一部分将被写入在磁盘。

如果缓存关闭，从后端服务器接收到的应答内容，将被立即同步传送到客户端。

Nginx不会尝试统计被代理服务器的全部应答数、数据的最大值，Nginx能够接受proxy_buffer_size指令设置的值。

对于长轮询的计算机信息传输应用，应该尽可能地设置proxy_buffering为off，否则异步地应答将被缓存，计算机信息传输将不工作。

13.20.3　proxy_buffers指令

语法：proxy_buffers the_number is_size;

默认值：proxy_buffers 8 4k/8k;

使用环境：http, server, location

该指令用于设置从被代理服务器读取应答信息的缓冲区数目和大小。通常情况下，一个缓冲区的大小相当于网页的大小。该指令的默认缓冲区大小取决于操作系统平台，不是4k就是8k。

假设你的网页平均大小都在32k以下，则可以设置：

13.20.4　proxy_busy_buffers_size指令

语法：proxy_busy_buffers_size size；

默认值：proxy_busy_buffers_size["#proxy buffer size"]*2；

使用环境：http, server, location, if

系统很忙的时候可以申请更大的proxy_buffers缓冲区，官方推荐为proxy_buffers缓冲区的大小*2，例如：

13.20.5　proxy_cache相关指令集

proxy_cache相关指令集，包含proxy_cache、proxy_cache_path、proxy_cache_methods、proxy_cache_min_uses、proxy_cache_valid、proxy_cache_use_stale等指令，在前面第9章中已经有详细说明，这里就不再重复介绍。

13.20.6　proxy_connect_timeout指令

语法：proxy_connect_timeout timeout_in_seconds

使用环境：http, server, location

该指令用于设置跟后端服务器连接的超时时间。该时间不是服务器返回页面的时间，而是发起握手等候响应的超时时间。

13.20.7　proxy_headers_hash_bucket_size指令

语法：proxy_headers_hash_bucket_size size；

默认值：proxy_headers_hash_bucket_size 64；

使用环境：http, server, location, if

该指令用于设置哈希表的存储桶数量。

13.20.8　proxy_headers_hash_max_size指令

语法：proxy_headers_hash_max_sizes size；

默认值：proxy_headers_hash_max_size 5l2；

使用环境：http, server, location, if

该指令用于设置哈希表的最大值。

13.20.9　proxy_hide_header指令

语法：proxy_hide_header the_header

默认值：http, server, location

Nginx不会传输从被代理服务器应答内容获取的"Date"、"Server"、"X-Pad"和"X-Accel-..."等Header行。proxy_hide_header指令允许隐藏一些额外的Header行。除了必须被传递的Header行，其他Header行都可以使用proxy_pass_header指令来隐藏。例如你可以按照以下方法隐藏MS-Office Webserver和AspNet-Version：

13.20.10　proxy_ignore_client_abort指令

语法：proxy_ignore_client_abort[on|off]

默认值：proxy_ignore_client_abort off

使用环境：http, server, location

如果客户端自身终止请求，防止中断代理请求。

13.20.11　proxy_ignore_headers指令

语法：proxy_ignore_headers name[name...]

默认值：none

使用环境：http, server, location

Nginx 0.7.54以上版本开始支持该指令。该指令可以禁止处理从代理服务器返回的Header行。它可以指定字符串，例如："X-Accel-Redirect"、"X-Accel-Expires"、"Expires"或"Cache-Control"。

13.20.12　proxy_intercept_errors指令

语法：proxy_intercept_errors[on|off]

默认值：proxy_intercept_errors off

使用环境：http, server, location

该指令判断Nginx是否会拦截HTTP状态码为400及以上代码的应答。

默认情况下，来自被代理服务器的所有应答将照常发送。

如果设定proxy_intercept_errors on, Nginx将会拦截error_page指令明确指定的错误状态码。如果来自被代理服务器的应答状态码不匹配一个error_page指令，应答将被照常发送。

13.20.13　proxy_max_temp_file_size指令

语法：proxy_max_temp_file_size size；

默认值：proxy_max_temp_file_size 1G；

使用环境：http, server, location, if

该指令用于设置当网页内容大于代理内存缓冲区的时候，临时文件大小的最大值。如果文件大于这个值，它将从upstream服务器同步地传递请求，而不是缓冲到磁盘。

13.20.14　proxy_method指令

语法：proxy_method[method]

默认值：None

使用环境：http, server, location

该指令允许代理额外的HTTP方法。HTTP协议除了常用的GET、POST方法外，还有一些其他的方法，例如Squid缓存服务器使用的自定义PURGE方法。

注意：当使用本指令时，Nginx只允许单个HTTP方法参数，所以目前还不能代理类似Subversion版本控制服务的请求。

proxy_method指令使用示例：

13.20.15　proxy_next_upstream指令

语法：proxy_next_upstream

[error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off]

默认值：proxy_next_upstream error timeout

使用环境：http, server, location

该指令用于设置当在哪种情况下，将请求转发到下一台服务器。在upstream负载均衡代理服务器池中，假设后端的一台服务器无法访问或返回指定错误响应代码时，可以使用该指令将请求转发到池中的下一台服务器。

可以设置的错误响应参数如下：

error——如果连接服务器时、发送请求时、读取应答信息时发送错误。

timeout——如果连接服务器时、传递请求时、读取后端服务器应答信息时超时。

invalid_header——后端服务器返回一个空的或错误的应答时。

http_500——后端服务器返回500应答状态码时。500状态码一般是Nginx配置、FastCGI程序出错导致。

http_502——后端服务器返回500应答状态码时。502状态码一般是后端服务器程序执行超时、无法访问导致。

http_503——后端服务器返回503应答状态码时。

http_504——后端服务器返回504应答状态码时。

http_404——后端服务器返回500应答状态码时。404状态码一般是文件不存在导致。

off——禁止将请求转发到下一台后端服务器。

当没有任何数据传送到客户端时，将请求转发到下一台后端服务器才会生效。确切地说，如果在传送应答内容给客户端的过程中出错或超时，将不会尝试重新请求一个不同的后端服务器。

13.20.16　proxy_pass指令

语法：proxy_pass URL

默认值：no

使用环境：location, if in location

该指令用于设置被代理服务器端口或套接字，以及URI。

可以使用域名（IP地址）和端口来指定被代理的服务器，例如：

也可以使用Unix套接字来指定被代理的服务器，例如：

请求转发给后端服务器的URI部分，取自Nginx代理服务器的location后面的URI路径部分。例如在Nginx代理服务器的以下配置中，访问/name/test/test.html将反向代理访问http://192.168.1.2/test/test.html的内容：

但是，对于以上的规则有以下两个例外：

（1）当以正则表达式的方式指定location时。

（2）在location中使用rewrite规则改变URI时，使用这个配置可以能够更精确地处理请求（break）：

在这些URI的传递案例中没有使用映射。

此外，须指明，以下URI将使用同样的格式转发。在工作过程中：

两个或多个连续的斜线将被转换成一个斜线："//"--"/"；

引用的当前目录会被删除："/./"--"/"；

引用的主目录会被删除："/dir/../"--"/"。

如果一个服务器上要传送未经处理的格式，那么proxy_pass的参数则要使用不含URI的URL，例如：

在proxy_pass指令中使用变量是一个特例，也可以使用rewrite和proxy_pass的组合：

13.20.17　proxy_pass_header指令

语法：proxy_pass_header the_name

使用环境：http, server, location

该指令允许转发为应答转发Header行。

13.20.18　proxy_pass_request_body指令

语法：proxy_pass_request_body[on|off]；

默认值：proxy_pass_request_body on；

使用环境：http, server, location

13.20.19　proxy_pass_request_headers指令

语法：proxy_pass_request_headers[on|off]；

默认值：proxy_pass_request_headers on；

使用环境：http, server, location

13.20.20　proxy_redirect指令

语法：proxy_redirect [default|off|redirect replacement]

默认值：proxy_redirect default

使用环境：http, server, location

该指令用于更改被代理服务器的应答Header头中的"Location"和"Refresh"。

我们假设被代理服务器返回的行是：Location: http://localhost:8000/two/some/uri/，那么，以下指令：

会将此行重写为Location: http://frontend/one/some/uri/。

在代替的行中可以不用写服务器的名称，只用写相对路径就可以了，例如：

这样，就设置了服务器的基本名称和端口，即使它不是80端口。

默认参数“default”，取决于location和proxy_pass指令的值。

例如以下两个配置的效果是一样的，这里的参数“default”的值，取决于proxy_pass指令的参数“http://upstream:port/two/”和location指令的参数“/one/”：

在代替的行中，可以使用一些Nginx变量，例如：

该指令有时候可以重复：

参数off在这个使用环境（例如location/one/{......}）中禁止所有的proxy_redirect指令：

以下这条语句可以帮助被代理服务器为相对重定向添加主机名：

13.20.21　proxy_read_timeout指令

语法：proxy_read_timeout the_time

默认值：proxy_read_timeout 60

使用环境：http, server, location

该指令用于设置从后端被代理服务器读取应答内容的超时时间。它决定Nginx等待多长时间来取得一个请求的应答。超时时间是指完成TCP两次握手，到TCP状态为ESTABLISHED时（数据正在传输）的时间，而不是整个时间。

注意不要将此时间设置得太低，如果被代理服务器超过此时间，仍然没有传输数据，Nginx将关闭该次连接。

13.20.22　proxy_redirect_errors指令

目前，已经不赞成使用该指令。请使用proxy_intercept_errors指令。

13.20.23　proxy_send_lowat指令

语法：proxy_send_lowat[on|off]

默认值：proxy_send_lowat off；

使用环境：http, server, location, if

该指令用于设置是否使用SO_SNDLOWAT，该指令只可以在FreeBSD操作系统中使用。

13.20.24　proxy_send_timeout指令

语法：proxy_send_timeout time_in_seconds

默认值：proxy_send_timeout 60

使用环境：http, server, location

该指令用于指定代理服务器转发请求的超时时间。超时时间是指完成TCP两次握手，到TCP状态为ESTABLISHED时（数据正在传输）的时间，而不是整个时间。如果代理服务器超过此时间，仍然没有转发数据到后端服务器，Nginx将关闭该次连接。

13.20.25　proxy_set_body指令

语法：proxy_set_body[on|off]

默认值：proxy_set_body off；

使用环境：http, server, location, if

从Nginx 0.3.10版本开始，可以使用该指令。

13.20.26　proxy_set_header指令

语法：proxy_set_header header value

默认值：Host and Connection

使用环境：http, server, location

该指令允许重新定义或添加Header行到转发给被代理服务器的请求信息中，它的值可以是文本，也可以是变量，或者是文本和变量的组合。

当proxy_set_header指令没有对指定的Header行进行定义时，将从客户端请求的Header行中继承这些行的信息。默认情况下，只有以下两行可以被重新定义：

未修改的Header头“Host”能够按照如下方式发送：

然而，如果客户端请求中没有这个Header头，将没有“Host”行的数据发送给被代理服务器。在这种情况下，最好使用$host变量，它的值相当于服务器的主机名（如果使用域名访问，则该值为域名；如果使用IP访问，则该值为IP）：

此外，可以将主机名和被代理服务器的端口一起传递：

如果设置指定Header行的值为空，该Header行将不会被发送到upstream。例如，以下示例可以用来在upstream中禁止后端服务器使用gzip压缩：

13.20.27　proxy_store指令

语法：proxy_store[on|off|path]

默认值：proxy_store off

使用环境：http, server, location

该指令可以设置哪些从后端服务器传送过来的文件被Nginx存储。参数“on”保持文件与alias或root指令设置的目录一致，参数“off”不存储文件。此外，路径名称中可以使用变量，例如：

文件的最后修改时间将被在应答数据的“Last-Modified”Header头中设定。为了文件的安全，可以使用proxy_temp_path指令设置一个临时目录。

该指令可以为不经常修改的文件建立一份本地镜像，从而减轻后端被代理服务器的压力。使用示例如代码13-21所示：

代码13-21

或者代码13-22中的内容：

代码13-22

注意：proxy_store不是缓存，存储的文件不会自动过期，它相当于一个镜像。

13.20.28　proxy_store_access指令

语法：proxy_store_access users:permissions[users:permission...]

默认值：proxy_store_access user:rw

使用环境：http, server, location

该指令用于指定创建文件和目录的权限，例如：

如果指定的用户组是正确的，那么，不需要指定用户的权限，例如：

13.20.29　proxy_temp_file_write_size指令

语法：proxy_temp_file_write_size size；

默认值：proxy_temp_file_write_size["#proxy buffer size"]*2；

使用环境：http, server, location, if

设置写入proxy_temp_path临时目录的数据大小。它可以防止一个工作进程阻塞太长时间。

13.20.30　proxy_temp_path指令

语法：proxy_temp_path dir-path[level1[level2[level3]；

默认值：$NGX_PREFIX/proxy_temp controlled by--http-proxy-temp-path at./configure stage

使用环境：http, server, location

该指令工作方式类似client_body_temp_path，用于指定一个本地目录来缓冲较大的代理请求。

13.20.31　proxy_upstream_fail_timeout指令

从Nginx 0.5.0版本开始，不赞成使用该指令。请使用upstream模块中的fail_timeout参数来代替它。

13.20.32　proxy_upstream_max_fails指令

从Nginx 0.5.0版本开始，不赞成使用该指令。请使用upstream模块中的max_fails参数来代替它。

13.20.33　HTTP Proxy模块的变量

HTTP Proxy模块包含一些内置变量，可以用于proxy_set_header指令：

被代理服务器的主机名和端口。

被代理服务器的端口。

包含以半角逗号分割的客户端请求头“X-Forwarded-For”和$remote_addr的内容。如果没有请求头“X-Forwarded-For”，该变量的值等于$remote_addr的值。

13.21　HTTP Rewrite模块

该模块及相关指令已经在第7章中有详细说明，这里就不再重复介绍。

13.22　HTTP SSI模块

SSI（Server Side Include），通常称为服务器端嵌入。

SSI的工作原理：将内容发送到浏览器之前，可以使用“服务器端包含（SSI）”指令将文本、图形或应用程序信息包含到网页中。例如，可以使用SSI包含时间／日期戳、版权声明或供客户填写并返回的表单。对于在多个文件中重复出现的文本或图形，使用包含文件是一种简便的方法。将内容存入一个包含文件中即可，而不必将内容输入所有文件。通过一个非常简单的语句即可调用包含文件，此语句指示Web服务器将内容插入适当网页。而且，使用包含文件时，对内容的所有更改只需在一个地方就能完成。

因为包含SSI指令的文件要求特殊处理，所以必须为所有SSI文件赋予SSI文件扩展名。默认扩展名是“.shtml”。例如以下的网址，则使用了SSI：

Nginx支持SSI，但是，目前功能并不是十分完善。

13.22.1　ssi指令

语法：ssi[on|off]

默认值：ssi off

使用环境：http, server, location, if in location

该指令用于开启或关闭SSI处理。

13.22.2　ssi_silent_errors指令

语法：ssi_silent_errors[on|off]

默认值：ssi_silent_errors off

使用环境：http, server, location

该指令设置为off时，当处理SSI时发生错误，不输出“[an error occurred while processing the directive]”错误信息。

13.22.3　ssi_types指令

语法：ssi_types mime-type[mime-type...]

默认值：ssi_types text/html

使用环境：http, server, location

允许SSI处理其他MIME类型。SSI默认可以处理“text/html”类型。

Enables SSI processing for MIME-types in addition to "text/html" types.

13.22.4　ssi_value_length指令

语法：ssi_value_length length

默认值：ssi_value_length 256

使用环境：http, server, location

定义SSI中允许使用的参数长度。

13.22.5　SSI命令

指令格式如下：

支持的SSI命令列表如下：

1．block

该命令允许创建一个块，在块中可以使用SSI命令：

name——块的名称。示例：

2．config

为SSI配置一些参数。

·　errmsg——SSI处理过程中的错误行，默认字符串为：[an error occurred while processing the directive]

·　timefmt——时间字符串的格式，strftime（3）函数使用，默认为：

时间中的秒可以使用“％S”。

3．echo

打印一个变量。

·　var——变量的名称。

·　default——如果变量为空，则显示这个字符串，默认值为“none”。示例：

与以下写法的功能相似：

4．if/elif/else/endif

使用方法：

以上示例只允许一层嵌套，不允许多层嵌套。

·　expr——匹配一个表达式，可以是变量：

字符串比较：

正则匹配：

如果使用变量，则用它们的值代替。

5．include

包含一个其他来源的文档。

·　file——包含一个文件，例如：

·　virtual——包含一个请求，例如：

多个请求将并行执行，如果要按顺序执行，请使用“wait”选项。

·　stub——如果请求为空或返回一个错误后使用的默认块。

·　wait——当设置为yes时，在当前的请求完成之前，剩余的SSI不会判定，示例：

6．set

设置一个变量。

·　var——变量。

·　value——包含变量名变量的值，它们将被匹配。

13.22.6　SSI变量

SSI变量代码格式如下：

本地时区的当前时间，选项"timefmt"控制格式。

当前的格林尼治时间，选项"timefmt"控制格式。

13.23　HTTP Userid模块

该模块相当于Apache的mod_uid模块，主要用于做客户端的身份标识。它主要使用$uid_got和$uid set变量。

配置示例：

13.23.1　userid指令

语法：userid[on|v1|log||off]

默认值：userid off

使用环境：http, server, location

该指令允许或禁止发布cookie及记录请求的cookie：

on——允许使用版本2的cookie及记录它们。

v1——允许使用版本1的cookie及记录它们。

log——不发送cookie，但是写下cookie来记录。

off——禁止发送及写cookie。

13.23.2　userid_domain指令

语法：userid_domain[name|none]

默认值：userid_domain none

使用环境：http, server, location

指定cookie的域名。参数“none”不为cookie指定域名。

13.23.3　userid_expires指令

语法：userid_expires[time|max]

默认值：none

使用环境：http, server, location

设置cookie的过期时间。

参数设置并发出浏览器cookie的过期时间。参数值“max”指定过期时间为“2037年12月31日23:55:55 GMT”，这是一些老的浏览器能够识别的最大时间。

13.23.4　userid_name指令

语法：userid_name name

默认值：userid_name uid

使用环境：http, server, location

该指令用于指定cookie的名称。

13.23.5　userid_p3p指令

语法：userid_p3p line

默认值：none

使用环境：http, server, location

Header头“P3P”的值，将和cookie一起传递。

13.23.6　userid_path指令

语法：userid_path path

默认值：userid_path/

使用环境：http, server, location

设置cookie的路径。

13.23.7　userid_service指令

语法：userid_service number

默认值：userid_service address

使用环境：http, server, location

该指令用于设置发出cookie的服务器IP地址。如果不设置。版本1的cookie设置为0，版本2的cookie设置为服务器的IP。

第14章

Nginx的其他HTTP模块

本章介绍的HTTP模块不会在编译Nginx时自动编译进来，除非使用“./configure --with-模块名”命令指定编译这些模块到Nginx中。

在本章的指令介绍中，指令的“使用环境”是指该指令可以在Nginx配置文件中使用的位置，例如使用环境为“http, server, location”，则表示该指令可以在以下位置使用：

http{......}大括号内；server{......}大括号内；location{......}大括号内。

14.1　HTTP Addition模块

本模块可以在当前的location内容之前或之后添加其他的location内容。

它作为一个输出过滤器被执行，主请求的内容和到其他location的内容不会被完全缓冲，将仍以流处理的方式发送到客户端。因为当发送HTTP Header头信息时，最终响应Body主体的长度是未知的，所以这里Nginx将不会在Header头中提供Content-Length头信息，而是始终采用HTTP Chunked编码动态地提供body内容的长度。进行Chunked编码传输的HTTP响应会在Header头中设置：Transfer-Encoding: chunked，表示Body主体将用Chunked编码传输内容。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

本模块相关指令的使用示例如下：

限制项如下：

在Nginx 0.8.17中，如果当前的location为它自身的子请求提供服务，该子请求的内容将不会被添加，例如代码14-1示例：

代码14-1

访问/foo不会使用/baz代替子请求/bar之前的内容。另外，在before/after body localtion中，只能使用字符串，而不能使用变量。以下配置虽然可以在nginx.conf配置文件检测时通过，但是不能正常工作。

14.1.1　add_before_body指令

语法：add_before_body uri

默认值：no

使用环境：http, server, location

该指令用于在应答主体之前添加URI子请求的内容结果。

14.1.2　add_after_body指令

语法：add_after_body uri

默认值：no

使用环境：http, server, location

该指令用于在应答主体之后添加URI子请求的内容结果。

14.1.3　addition_types指令

语法：addition_types mime-type[mime-type...]

默认值：text/html

使用环境：http, server, location

该指令（从Nginx 0.7.9版本开始）允许location处理自定义的MIME类型（默认为“text/html”）。

在Nginx 0.8.17之前的版本，该指令在源代码中被错误地拼写为“addtion_types”，这个Bug在0.8.17版本中被修正。

14.2　Embedded Perl模块

本模块允许在Nginx中直接执行Perl，或者通过SSI调用Perl。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

另外，您的操作系统中必须安装Perl 5.6.1以上版本。

已知问题：

（1）如果Perl模块执行长时间的操作，例如DNS查询、数据库查询等，运行Perl脚本的工作进程将一直处于阻塞状态，因此，内置的Perl脚本应该非常简单，执行尽可能快。

（2）Nginx在通过“kill-HUP<pid>”命令重新加载配置文件时，可能会导致内存泄露。

示例如代码14-2所示：

代码14-2

perl/lib/hello.pm示例如代码14-3所示：

代码14-3

14.2.1　perl指令

语法：perl module::function|'sub{...}'

默认值：no

使用环境：location

该指令用来指定数据location中须要用到的Perl函数。

14.2.2　perl_modules指令

语法：perl_modules path

默认值：no

使用环境：http

该指令用于为Perl模块指定额外的路径。从Nginx 0.6.7版本开始，该路径与nginx.conf配置文件所在目录有关，而不是Nginx的prefix安装目录。

14.2.3　perl_require指令

语法：perl_require module

默认值：no

使用环境：http

这里，你可以使用多个perl_require指令。

14.2.4　perl_set指令

语法：perl_set module::function|'sub{...}'

默认值：no

使用环境：http

该指令用于设置一个名称为变量名的函数体。示例如代码14-4：

代码14-4

14.2.5　从SSI调用Perl脚本

指令格式如下：

请求对象的方法$r：

$r->args——返回请求参数的方法。

$r->discard_request_body——告诉Nginx丢弃请求主体的方法。

$r->filename——返回与URI请求想符合的文件名。

$r->has_request_body（function）——如果没有请求的主体，则返回0。如果请求的主体存在，则建立传递的函数并返回1。在主体处理的结尾，Nginx将调用已经建立的处理器。用法示例如代码14-5：

代码14-5

$r->header_in（header）——检索一个HTTP请求头。

$r->header_only——如果只须要返回一个应答头，则为真。

$r->header_out（header, value）——设置一个应答头。

$r->internal_redirect（uri）——使用内部重定向到指定的URI。重定向只能在Perl脚本执行结束后发生。

$r->print（args,...）——发送数据到客户端。

$r->request_body——当主体没有记录进临时文件时，返回客户端请求主体。因此，为了保证客户端请求主体保留在内存中，须要使用client_max_body_size指令限制其大小，并且使用client_body_buffer_size指令指定足够大的缓冲区。

$r->request_body_file——返回存储客户端需求主体的文件名。该文件在处理完成后必须被删除。如果需要请求主体总是写入该文件，你须要设置client_body_in_file_only指令为on。

$r->request_method——返回HTTP请求方法。

$r->remote_addr——返回客户端IP地址。

$r->rflush——马上发送数据到客户端。

$r->sendfile（file[,displacement[,length]）——传输文件的内容给客户端显示。可选的参数用来设置初始位置点及传送数据的长度。严格来说，数据传输只能发生在Perl脚本执行完毕后。

$r->send_http_header（type）——添加Header到应答中。参数选项“type”用来填写Header行“Content-Type”的值。

$r->sleep（milliseconds, handler）——设置在给定请求时间内的指定处理程序，或者停止处理。在这段时间内，Nginx将继续处理其他请求。在规定的超时时间期满后，Nginx将运行安装处理程序。请注意，你须要传递一个标识符给函数处理程序。在处理器之间传输数据，你应该使用$r->variable()。用法示例如代码14-6：

代码14-6

$r->status（code）——设置HTTP应答头。

$r->unescape（text）——使用unescape方法对以％XX十六进制形式编码的文本进程解码。

$r->uri——返回请求的URI。

$r->variable（name[,value]）——返回或设置指定变量的值。对每个查询来说，变量为局部变量。

14.3　Flv Stream模块

本模块用于FLash播放器以HTTP下载方式播放远程Web服务器上的FLV视频时，支持播放进度条拖动，即支持以test.flv?start=12345的方式从指定字节位置下载文件。国内著名的视频分享网站优酷网、土豆网、新浪播客等，都支持这种拖动方式。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

本模块的配置示例如下：

在前面第11章第11.2.1节中，已详细介绍了“采用Nginx的Flv Stream模块搭建HTTP下载方式的FLV视频服务器”，这里不再赘述。

14.3.1　flv指令

语法：flv

默认值：None

使用环境：location

为当前的location开启针对FLV视频拖动播放的特殊文件处理。

14.4　HTTP Gzip Static模块

在一个文件传送给能够接受Gzip压缩的客户端浏览器之前，本模块用来检查同名location下是否存在以“.gz”结尾的文件。这样做的意图是避免重复压缩相同的文件。

本模块从Nginx 0.6.24版本开始被引入，默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

示例代码如下：

14.4.1　gzip_static指令

语法：gzip_static on|off

默认值：gzip_static off

使用环境：http, server, location

开启HTTP Gzip Static模块。你应该确保压缩文件和未压缩文件的时间戳一样。

14.4.2　gzip_http_version指令

参见第13章第13.11.5节的gzip_http_version指令。

14.4.3　gzip_proxied指令

参见第13章第13.11.6节的gzip_proxied指令。

14.5　HTTP Random Index模块

本模块用于从目录中选择一个随机目录索引。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例代码如下：

14.5.1　random_index指令

语法：random_index[on|off]

默认值：off

使用环境：location

如果在一个指定的location中开启本指令，它将为每次访问扫描指定目录内的文件，并发送一个随机选取的文件代替通常的index.html。以“.”开头的文件不会被选取。

14.6　HTTP Geo IP模块

本模块基于客户端IP地址与MaxMind()提供的GeoIP地址库进行比对，创建一些变量，用来实现地区性负载均衡。本模块适用于Nginx 0.7.63和0.8.6之后的版本。

本模块需要Geo IP数据库及读取该数据库的libgeoip类库，如代码14-7所示。

代码14-7

在CentOS Linux操作系统，你可以使用yum命令安装libgeoip：

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例代码如下：

14.6.1　geoip_country指令

语法：geoip_country path/to/db.dat；

默认值：none

使用环境：http

该指令用于指定判断访问者IP地址所属国家的.dat数据库文件路径。通过该指令的设置，GeoIP模块会创建以下可用的变量：

$geoip_country_code；——两个字母的国家代码，例如“RU”，“US”。

$geoip_country_code3；——三个字母的国家代码，例如“RUS”，“USA”。

$geoip_country_name；——国家名称，例如：“Russian Federation”，“United States”。

如果你只需要国家名称，则只设置geoip_country数据库（1.1MB）即可，因为geoip_city数据库（43MB）要大得多，并且所有的数据库将被缓存在内存中。

14.6.2　geoip_city指令

语法：geoip_city path/to/db.dat；

默认值：none

使用环境：http

该指令用于指定判断访问者IP地址所属国家、地区、城市的.dat数据库文件路径。通过该指令的设置，GeoIP模块会创建以下可用的变量：

$geoip_city_country_code——两个字母的国家代码，例如“RU”，“US”。

$geoip_city_country_code3——三个字母的国家代码，例如“RUS”，“USA”。

$geoip_city_country_name——国家名称，例如：“Russian Federation”，“United States”（if available）。

$geoip_region——地区名称（省，地区，州，大行政区，联邦政府国土等）例如：“Moscow City”，“DC”（如果存在）。

$geoip_city——城市名称，例如：“Moscow”，“Washington”（如果存在）。

$geoip_postal_code——邮政编码（如果存在）。

$geoip_city_continent_code——洲（指欧、亚、非、南北美、澳、南极洲之一）代码（如果存在）。

$geoip_latitude——纬度（如果存在）。

$geoip_longitude——经度（如果存在）。

14.7　HTTP RealIp模块

本模块可以修改客户端请求头中的客户端IP地址，例如X-Real-IP和X-Forwarded-For。如果Nginx位于Squid等代理服务器之后，或者位于F5 Big-IP、NetScaler等七层负载均衡交换机之后，本模块将非常有用。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

假设一台Nginx位于Squid的后端，Squid设置了X-Forwarded-For头信息，记录了用户的真实IP，但是，如果存在多级代理的情况，X-Forwarded-For头信息的内容值将变成以逗号分隔的多个IP地址。

通过本模块，你可以设置一个可信的代理服务器IP列表，Header头中第一个不受信任的IP将作为客户端IP。例如以上的X-Forwarded-For信息中，假设202.108.1.1为客户端IP，其他均为代理服务器IP，就可以使用以下配置：

这样，X-Forwarded-For中的IP信息就只剩下客户端的IP地址202.108.1.1了。

14.7.1　set_real_ip_from指令

语法：set_real_ip_from[the address|CIDR]

默认值：none

使用环境：http, server, location

该指令用于设置可信的代理服务器IP地址，这些IP地址将在请求转发时被从Header头信息中去掉。

14.7.2　real_ip_header指令

语法：real_ip_header[X-Real-IP|X-Forwarded-For]

默认值：real_ip_header X-Real-IP

使用环境：http, server, location

该指令用于设置转发客户端IP地址的Header头名称。

14.8　HTTP SSL模块

本模块用于HTTPS支持。

它支持使用以下两个限制检查客户端证书：

（1）不允许指定过期证书的列表。

（2）如果你有一个证书链文件，你无须像Apache那样指定每个证书文件。例如金山逍遥网用户中心使用的中国互联网信息中心（CNNIC）SSL证书，则是由三个证书链文件构成的。根证书由Entrust.net颁发给自己，中级根证书由Entrust.net颁发给CNNIC，域名my.xoyo.com的CRT证书文件由CNNIC颁发，如图14-1所示。

图14-1　Windows上查看证书链文件

将三个证书文件的内容（文本格式）按照低级别证书在前的方式，拷贝到一个证书链文件（文本格式）中，即可构成证书链文件，Nginx配置文件中只须要指定这个证书链文件即可。证书链格式如代码14-8所示：

代码14-8

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例如代码14-9：

代码14-9

从Nginx 0.7.14版本开始，通常习惯在listen指令中使用“ssl”参数：

生成证书：

通常情况下，你可以按照以下步骤生成一个自行颁发的证书，如代码14-10所示：

代码14-10

在Nginx配置文件中配置新证书，如代码14-11：

代码14-11

重启Nginx，然后访问：

在第11章，已介绍了使用HTTPS（SSL）构建一个安全的Nginx Web服务器实例。

14.8.1　在多个server{......}虚拟主机中使用通配符SSL证书

如果你有一个通配符SSL证书，例如颁发给*.nginx.org域名的SSL证书，你可以在http{......}中指定证书文件和私钥文件，那么在各虚拟主机中就可以继承相同的证书。配置示例如代码14-12：

代码14-12

14.8.2　ssl指令

语法：ssl[on|off]

默认值：ssl off

使用环境：main, server

为一个server{......}虚拟主机开启HTTPS（SSL）支持。

14.8.3　ssl_certificate指令

语法：ssl_certificate file

默认值：ssl_certificate cert.pem

使用环境：main, server

为当前的虚拟主机指定PEM格式的证书文件。一个文件中可以包含多个证书文件（证书链），同样，密钥也必须为PEM格式。从Nginx 0.6.7版本开始，证书文件的相对路径为nginx.conf配置文件所在的目录，而不是Nginx安装目录。

14.8.4　ssl_certificate_key指令

语法：ssl_certificate_key file

默认值：ssl_certificate_key cert.pem

使用环境：main, server

为当前的虚拟主机指定PEM格式的私钥文件。从Nginx 0.6.7版本开始，证书文件的相对路径为nginx.conf配置文件所在的目录，而不是Nginx安装目录。

14.8.5　ssl_client_certificate指令

语法：ssl_client_certificate file

默认值：none

使用环境：main, server

指定PEM格式的CA证书，用于检查客户端证书。

14.8.6　ssl_dhparam指令

语法：ssl_dhparam file

默认值：none

使用环境：main, server

指定PEM格式的含有Diffie-Hellman参数的文件，用于TLS会话键。

14.8.7　ssl_ciphers指令

语法：ssl_ciphers file

默认值：ssl_ciphers ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP

使用环境：main, server

指定许可密码的描述。密码以OpenSSL支持的格式指定，例如：

使用以下命令可以查看OpenSSL支持的完整格式列表：

14.8.8　ssl_crl指令

语法：ssl_crl file

默认值：none

使用环境：http, server

该指令（Nginx 0.8.7以上版本开始支持）用于指定一个PEM格式的证书吊销文件，用于检查客户端证书。

14.8.9　ssl_prefer_server_ciphers指令

语法：ssl_prefer_server_ciphers[on|off]

默认值：ssl_prefer_server_ciphers off

使用环境：main, server

对SSLv3和TLSv1协议的服务器端密码需求优先级高于客户端密码。

14.8.10　ssl_protocols指令

语法：ssl_protocols[SSLv2][SSLv3][TLSv1]

默认值：ssl_protocols SSLv2 SSLv3 TLSv1

使用环境：main, server

该指令用于指定使用的SSL协议。

14.8.11　ssl_verify_client指令

语法：ssl_verify_client on|off|ask

默认值：ssl_verify_client off

使用环境：main, server

该指令用于开启客户端证书验证。参数“ask”在客户端主动提出检查证书时，对客户端证书进行检查。

14.8.12　ssl_verify_depth指令

语法：ssl_verify_depth number

默认值：ssl_verify_depth 1

使用环境：main, server

设置客户端证书链的深度。

14.8.13　ssl_session_cache指令

语法：ssl_session_cache off|none|builtin:size and/or shared:name:size

默认值：ssl_session_cache off

使用环境：main, server

该指令设置用来存储SSL会话的缓存类型和大小。缓存类型为：

off——硬关闭：Nginx明确告诉客户端这个会话不可用。

none——软关闭：Nginx告诉客户端会话能够被重用，但是Nginx实际上不会重用它们。这是为某些邮件客户端使用的一种变通方法，可以被用于邮件代理和HTTP服务器中。

builtin——OpenSSL内置缓存，仅可用于一个工作进程。缓存大小用会话数来指定。注意：使用该指令会导致内存碎片，当使用此功能时须要考虑。

shared——位于所有工作进程的共享缓存。缓存的大小用字节数指定，1MB缓存能够容纳大约4000会话。每个共享缓存必须拥有自己的名称。同名的缓存可以用于多个虚拟主机。

你也可以同时使用builtin和shared，示例如下：

然而，只使用共享内存而不使用builtin缓存，将更有效。

14.8.14　ssl_session_timeout指令

语法：ssl_session_timeout time

默认值：ssl_session_timeout 5m

使用环境：main, server

设置客户端能够重复使用存储在缓存中的会话参数时间。

该模块支持一些非标准的错误代码，可以借助error_page指令来做debug调试：

495——检查客户端证书时发生错误。

496——客户端不允许必须的证书。

497——正常的请求发送到HTTPS。

在调试完成后，可以取得一些变量，例如$request_uri、$uri、$arg等。Nginx的Http SSL模块支持这些内置变量：

$ssl_cipher：返回既定SSL连接中使用的密码行。

$ssl_client_serial：返回既定SSL连接的客户端证书的序列号。

$ssl_client_s_dn：返回既定SSL连接的客户端证书的DN主题行。

$ssl_client_i_dn：返回既定SSL连接的客户端证书的DN发行站行。

$ssl_protocol：返回既定SSL连接的协议。

$ssl_session_id：在Nginx 0.8.20以上版本支持该变量。

$ssl_client_cert

$ssl_client_raw_cert

$ssl_verify "SUCCESS"：如果客户端证书验证通过，该变量的值为“SUCCESS”

14.8.15　ssl_engine指令

语法：ssl_engine

该指令指定允许去使用的OpenSSL引擎，例如Padlock。须要安装一个近期发布的OpenSSL版本。

14.9　HTTP Stub Status模块

本模块主要用于查看Nginx的一些状态信息。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例如代码14-13：

代码14-13

14.9.1　stub_status指令

语法：stub_status on

默认值：None

使用环境：location

该指令用于开启Nginx状态信息。

访问以上示例中配置的http://status.yourdomain.com/，显示的Nginx状态信息示例如下：

Active connections——对后端发起的活动连接数。

Server accepts handled requests——Nginx总共处理了43629083个连接，成功创建43629083次握手（证明中间没有失败的），总共处理了259552136个请求。

Reading——Nginx读取到客户端的Header信息数。

Writing——Nginx返回给客户端的Header信息数。

Waiting——开启keep-alive的情况下，这个值等于active-（reading+writing），意思就是Nginx已经处理完成，正在等候下一次请求指令的驻留连接。

所以，在访问效率高，请求很快被处理完毕的情况下，Waiting数比较多是正常的。如果reading+writing数较多，则说明并发访问量非常大，正在处理过程中。

14.10　HTTP Sub模块

本模块主要用来搜索并替换Nginx应答内容中的文本。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

示例如下：

14.10.1　sub_filter指令

语法：sub_filter text substitution

默认值：none

使用环境：http, server, location

该指令允许使用一些其他的文本替换Nginx应答内容中的一些文本。匹配不区分大小写，替换的文本可以包含变量。每个location只能指定一个替换规则。

14.10.2　sub_filter_once指令

语法：sub_filter_once on|off

默认值：sub_filter_once on

使用环境：http, server, location

该指令的值设置为off时，允许搜索并替换所有匹配行。该指令的默认值为on，只替换第一个匹配项。

14.10.3　sub_filter_types指令

语法：sub_filter_types mime-type[mime-type...]

默认值：sub_filter_types text/html

使用环境：http, server, location

该指令用于指定sub_filter指令将检查哪一内容类型，默认值为text/html。

14.11　HTTP Dav模块

本模块用来设置允许HTTP和WebDAV方法：PUT、DELETE、MKCOL、COPY、MOVE。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

示例如代码14-14：

代码14-14

14.11.1　dav_access指令

语法：dav_access user:permissions[users:permissions]...

默认值：dav_access user:rw

使用环境：http, server, location

该指令用于指定文件和目录的访问权限，示例如下：

如果指定任何允许的groups或all，则无须为user指定权限：

14.11.2　dav_methods指令

语法：dav_methods[off|put|delete|mkcol|copy|move]...

默认值：dav_methods off

使用环境：http, server, location

该指令用来设置允许指定的HTTP和WebDAV方法。如果设置为off，所有的方法将被禁止，并且忽略剩余的参数。

PUT方法的目的文件必须在相同分区的临时文件存储目录中存在，使用client_body_temp_path指令在section区域中设置。

当一个文件被使用PUT方法创建时，将使用Date头信息作为该文件的修改时间。

14.11.3　create_full_put_path指令

语法：create_full_put_path on|off

默认值：create_full_put_path off

使用环境：http, server, location

默认情况（off）下，PUT方法只能在已经存在的目录中创建文件。该指令允许Nginx创建目录。

14.12　Google Perftools模块

本模块允许使用Google公司开发的性能优化工具Google Performance Tools（http://code.google.com/p/google-perftools/）。该模块可在Nginx 0.6.29之后的版本中使用。

Google Performance Tools的安装步骤如代码14-15所示：

代码14-15

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

示例如下：

Profile将以/path/to/profile.<worker_pid>格式存储。

14.12.1　google_perftools_profiles指令

语法：google_perftools_profiles path

默认值：none

该指令用于指定profiles基础文件名，工作进程的PID将被添加到指定的文件中。

14.13　HTTP XSLT模块

XSLT是一种用于将XML文档转换为XHTML文档或其他XML文档的语言。本模块是通过一个或多个XSLT模板转换XML应答内容的过滤器。本模块适用于Nginx 0.7.8以后版本。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例如下：

14.13.1　xslt_entities指令

语法：xml_entities<path>

默认值：no

使用环境：http, server, location

用于指定DTD描述文件（XML实体）。DTD实际上可以看作一个或多个XML文件的模板，这些XML文件中的元素、元素的属性、元素的排列方式／顺序、元素能够包含的内容等，都必须符合DTD中的定义。此文件在配置阶段被编译。由于技术原因，不能对正在处理的XML文件指定实体，但是会用一个特别指定的文件来代替。在这个文件中，没有必要来描述处理XML的结构，只须说明必须的符号元素即可，例如：

14.13.2　xslt_stylesheet指令

语法：xslt_stylesheet template[parameter[[parameter...]]

默认值：no

使用环境：http, server, location

用于指定XSLT模板的参数。模板在配置阶段被编译。参数按照以下方法指定：

你可以为每行指定任何参数，或者使用“:”分割多个参数。如果参数自身包含字符“:”，请使用“％3A”转义。此外，如果参数包含非字母数字的字符，libxslt要求字符串参数应该用单引号或双引号引用。示例如下：

它可以使用变量作为参数，例如，参数值可以用一个变量来取代：

可以指定多个模板，在这种情况下，将按照它们的声明顺序链接在一起。

14.13.3　xslt_types指令

语法：xslt_types mime-type[mime-type...]

默认值：xslt_types text/xml

使用环境：http, server, location

允许处理除了“text/xml”之外的指定MIME类型。如果XSLT输出模式为HTML，应答的MIME类型可以更改为“text/HTML”。

14.14　HTTP Secure Link模块

本模块计算和请求需要安全性令牌的URL地址。在Nginx 0.7.18以上版本中可以使用本模块。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

配置示例代码如下：

14.14.1　secure_link_secret指令

语法：secure_link_secret secret_word

默认值：none

使用环境：location

该指令用于指定一个密码去校验请求。一个被保护链接的完整URL如下：

该指令将按照以下方式进行哈希计算：

prefix为location区块的位置范围，不能为“/”。secure_link只能用于非root路径。

配置示例代码如14-16：

代码14-16

假设有两个文件/data0/htdocs/www/download/demo.mp4和/data0/htdocs/www/download/video/demo.mp4，可通过PHP程序生成一个md5串：

执行该PHP程序得出：

通过以下URL访问Nginx，就可以下载这两个文件：

14.14.2　$secure_link变量

自动设置URL的基准部分，并与prefix和hash分开。如果hash错误，变量$secure_link的值将为空。

14.15　HTTP Image Filter模块

本模块是一个转换JPEG、GIF、PNG图片的过滤器。

本模块默认是不会编译进Nginx的，如果你要使用该模块，则要在编译安装Nginx时指定：

本模块需要操作系统安装libgd类库。

配置示例如代码14-17：

代码14-17

14.15.1　image_filter指令

语法：image_filter（test|size|resize width height|crop width height）

默认值：none

使用环境：location

它指定适用于图片的转换类型。

test：检查应答是否确实为一个图片格式JPEG、GIF、PNG，如果不是，返回415。

size：以JSON格式给出图片的信息，示例如下：

或者当一个错误发生时，返回：

resize：按比例缩小图片到指定的大小。

crop：按比例缩小图片到指定的大小，并裁减掉超过指定大小的图片区域。

14.15.2　image_filter_buffer指令

语法：image_filter_ buffer size

默认值：1M

使用环境：http, server, location

设置读取图片的最大值。

14.15.3　image_filter_jpeg_quality指令

语法：image_filter_jpeg_quality[0...100]

默认值：75

使用环境：http, server, location

设置处理JPEG图片的质量损耗比率。最大推荐者为95。

14.15.4　image_filter_transparency指令

语法：image_filter_transparency on|off

默认值：on

使用环境：http, server, location

该指令允许你在GIF和基于调色板的PNG禁止使用图片透明，从而提高图片质量。

不管这个指令如何设置，真彩色PNG alpha-channels总是存在。

注意：灰度PNG未经测验，但是能够被当成真彩色来处理。

第15章

Nginx的邮件模块

Nginx除了可用作HTTP服务器外，还可用作邮件代理，支持IMAP、POP3、SMTP协议。

IMAP（Internet Message Access Potocol）是一种用于邮箱访问的协议，使用IMAP协议可以在客户端管理服务器上的邮箱。它与POP不同，邮件是保留在服务器上而不是下载到本地，在这一点上IMAP是与Webmail相似的。但IMAP有比Webmail更好的地方，它比Webmail更高效和安全，可以离线阅读等。如果想用Outlook Express、Foxmail试试，只要配置好一个账号，将邮件接收服务器设置为IMAP服务器就可。此外，IMAP还提供了一个更好的方法供您从多个设备中访问邮件。不管您是在工作中检查邮件，或者通过手机检查邮件，还是在家里检查邮件，IMAP都能确保您从任何设备随时访问新邮件。总之，IMAP可从整体上为用户带来更为可靠的体验。虽然POP更易丢失邮件或多次下载相同的邮件，但IMAP通过邮件客户端与邮件服务器之间的双向同步功能很好地避免了这些问题。例如，Gmail、QQ邮箱都支持IMAP协议访问。

POP3（Post Office Protocol 3）即邮局协议的第3个版本，它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是Internet电子邮件的第一个离线协议标准，POP3允许用户从服务器上把邮件存储到本地主机（即自己的计算机）上，同时删除保存在邮件服务器上的邮件，而POP3服务器则是遵循POP3协议的接收邮件服务器，用来接收电子邮件的。

SMTP（Simple Mail Transfer Protocol）即简单邮件传输协议，它是一组用于由源地址到目的地址传送邮件的规则，由它来控制信件的中转方式。SMTP协议属于TCP/IP协议族，它帮助每台计算机在发送或中转信件时找到下一个目的地。通过SMTP协议所指定的服务器，可以把E-mail寄到收信人的服务器上，整个过程只要几分钟。SMTP服务器则是遵循SMTP协议的发送邮件服务器，用来发送或中转你发出的电子邮件。

Nginx使用外部的类HTTP服务器去获知应该连接到哪个IMAP/POP后端服务器。

Nginx在HTTP Header 头中传递认证信息如下：

正常的应答为：

在POP3中，为了避免发送明文口令的问题，有一种新的认证方法，命令为APOP，使用APOP，口令在传输之前被加密。当POP3认证使用APOP时，你必须返回Auth-Pass：

认证失败的应答结果为：

在本章的指令介绍中，指令的“使用环境”是该指令在Nginx配置文件中使用的位置，例如使用环境为“mail, server”，表示该指令可以在以下位置使用：

mail{......}大括号内；server{......}大括号内。

15.1　Nginx邮件核心模块

15.1.1　auth指令

从Nginx 0.5.15版本开始，该指令重命名为pop3_auth。

15.1.2　imap_capabilities指令

语法：imap_capabilities“capability1”[“capability2”..“capabilityN”]

默认值：“IMAP4”“IMAP4rev1”“UIDPLUS”

使用环境：main, server

在客户端发送IMAP命令CAPABILITY的时候，通过这个指令，你可以设置IMAP协议扩展列表。如果启用starttls指令，STARTTLS将被自动添加。

目前，标准的IMAP扩展发布在网站www.iana.org。imap_capabilities设置示例如下：

15.1.3　imap_client_buffer指令

语法：iimap_client_buffer size

默认值：4k/8k

使用环境：main, server

使用本指令可以设置IMAP命令的读取缓冲区。默认值等于页大小（该值取决于操作系统，为4k或8k）。

15.1.4　listen指令

语法：listen address:port[bind]

默认值：no

使用环境：server

该指令用于指定接收请求的服务器地址和端口。它也可以单一指定服务器地址或端口，此外，地址客户使用服务器名称，示例如下：

IPv6地址（Nginx 0.7.58以上版本支持）请在中括号中设置，示例如下：

在listen指令中，可以设置系统调用bind（2）。

15.1.5　pop3_auth指令

语法：pop3_auth[plain][apop][cram-md5]

默认值：plain

使用环境：main, server

该指令可以设置POP3客户端认证的许可方法：

plain——USER/PASS, AUTH PLAIN, AUTH LOGIN

apop——APOP

cram-md5——AUTH CRAM-MD5

15.1.6　pop3_capabilities指令

语法：pop3_capabilities“capability1”[“capability2”..“capabilityN”]

默认值：“TOP”“USER”“UIDL”

使用环境：main, server

在客户端发送POP3命令CAPA的时候，通过这个指令，你可以设置POP3协议扩展列表。如果你启用starttls指令，STLS将被自动添加。SASL将在auth指令中添加。

15.1.7　protocol指令

语法：protocol[pop3|imap|smtp]；

默认值：IMAP

使用环境：server

该指令用于设置虚拟主机server{...}块使用的协议。

15.1.8　server指令

语法：server{...}

默认值，no

使用环境：mail

该指令用于配置虚拟主机。这里没有明确区分基于IP地址的虚拟主机和基于域名的虚拟主机（客户端请求中Header头Host行的值）。该指令用于配置虚拟主机。在server{......}中，使用listen指令来为一个虚拟主机设置监听的IP和端口，使用server_name指令来设置不同的虚拟主机名称。

15.1.9　server_name指令

语法：server_name name fgdn_server_host

默认值：The name of the host, obtained through gethostname()

使用环境：mail, server

该指令用于设置虚拟主机的主机名，示例如下：

server_name参数中的第一个名称将成为服务器的基础名称。默认名称为被使用的服务器名称（hostname），你可以使用通配符“*”代替名称的首部分：

上述示例中的两个名称可以合并成以下的一个：

如果在客户端请求中没有Header头“Host”，或者Header头不匹配任何server_name，服务器的基础名称将被用于HTTP重定向。你可以使用“*”强制Nginx在HTTP重定向中使用Host头（注意：“*”不能作为虚拟主机的第一个名称，但是，你可以使用一个伪名称“_”来代替第一个名称）：

15.1.10　smtp_auth指令

语法：smtp_auth[login][plain][cram-md5]；

默认值：login plain

使用环境：main, server

该指令可以设置SMTP客户端认证的许可方法：

login——AUTH LOGIN

plain——AUTH PLAIN

cram-md5——AUTH CRAM-MD5

15.1.11　smtp_capabilities指令

语法：smtp_apabilities“capability1”[“capability2”..“capabilityN”]

默认值：no

使用环境：main, server

在客户端发送SMTP命令EHLO的时候，通过这个指令，你可以设置SMTP协议扩展列表。此列表通过smtp_auth指令启用的方法自动扩展。目前，标准的SMTP扩展发布在网站www.iana.org。

15.1.12　so_keepalive指令

语法：so_keepalive on|off；

默认值：off

使用环境：main, server

通过该指令，你可以为连接到IMAP/POP3后端服务器的套接字设置SO_KEEPALIVE选项。在FreeBSD中，keepalive选项将被用于所有的连接，它可以通过内核参数（见sysctlnet.inet.tcp.always_keepalive）关闭。

15.1.13　timeout指令

语法：timeout milliseconds；

默认值：60000

使用环境：main, server

通过该指令，你可以设置代理服务器连接到后端的超时时间。

15.2　Nginx邮件认证模块

Nginx邮件认证模块示例如下：

15.2.1　auth_http指令

语法：auth_http URL

默认值：no

使用环境：mail, server

通过该指令，你可以为认证设置URL到扩展的类HTTP服务器。

15.2.2　auth_http_header指令

语法：auth_http_header header value

默认值：no

使用环境：mail, server

通过该指令，你可以在身份认证的过程中添加一个HTTP头和它的值。这使得它可以使用一个共享的秘密字符串，确保请求是由Nginx应答。

示例如下：

15.2.3　auth_http_timeout指令

语法：auth_http_timeout milliseconds;

默认值：60000

使用环境：mail, server

通过该指令，你可以设置认证过程的超时时间。

15.3　Nginx邮件代理模块

Nginx可以代理IMAP、POP3、SMTP协议。

15.3.1　proxy指令

语法：proxy on|off

默认值：off

使用环境：mail, server

通过该指令，你可以开启或关闭邮件代理。

15.3.2　proxy_buffer指令

语法：proxy_buffer size

默认值：4k/8k

使用环境：mail, server

通过该指令，你可以设置代理连接的缓冲区大小。默认值等于页大小（该值取决于操作系统，为4k或8k）。

15.3.3　proxy_pass_error_message指令

语法：proxy_pass_error_message on|off

默认值：off

使用环境：mail, server

通过该指令，你可以传递从后端被代理服务器获取的错误信息给客户端。通常情况下，如果成功通过Nginx的认证，后端被代理服务器将不会传递错误信息给客户端。

但是在一些正确密码的应答过程中，POP3服务器错误属于正常的行为。例如CommuniGatePro通知用户关于邮箱存储空间满（或者其他事件）将在认证时周期性地发出错误信息。在这种情况下，有必要设置proxy_pass_error_message指令的参数为on。

15.3.4　proxy_timeout指令

语法：proxy_timeout time

默认值：24h

使用环境：mail, server

通过该指令，你可以设置代理连接的超时时间。

15.3.5　xclient指令

语法：xclient on|off

默认值：on

使用环境：mail, server

通过该指令，你可以允许或禁止连接SMTP后端服务器时使用XCLIENT命令。这将允许后端强制限制客户端连接基于IP/HELO/LOGIN。

如果xclient指令的参数为on, Nginx将首先传递以下信息给后端服务器：

然后：

15.4　Nginx邮件SSL模块

本模块为POP3/IMAP/SMTP提供SSL/TLS支持。配置几乎与HTTP SSL模块相同，但是不支持检查客户端证书。

15.4.1　ssl模块

语法：ssl on|off

默认值：ssl off

使用环境：mail, server

为所在虚拟主机启用或禁用SSL/TLS。

15.4.2　ssl_certificate指令

语法：ssl_certificate file

默认值：cert.pem

使用环境：mail, server

为所在虚拟主机指定PEM格式的证书文件。相同的文件客户包含其他的证书，并且密钥也是PEM格式。

15.4.3　ssl_certificate_key指令

语法：ssl_certificate_key file

默认值：cert.pem

使用环境：mail, server

为所在虚拟主机指定PEM格式的密钥文件。

15.4.4　ssl_ciphers指令

语法：ssl_ciphers file ciphers

默认值：ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP

使用环境：mail, server

指出允许的密码格式描述，密码被指定为OpenSSL支持的格式。

15.4.5　ssl_prefer_server_ciphers指令

语法：ssl_prefer_server_ciphers on|off

默认值：off

使用环境：mail, server

要求SSLv3和TLSv1协议的服务器密码优先于客户端的密码。

15.4.6　ssl_protocols指令

语法：ssl_protocols[SSLv2][SSLv3][TLSv1]

默认值：SSLv2 SSLv3 TLSv 1

使用环境：mail, server

该指令用于指定使用的SSL协议。

15.4.7　ssl_session_cache指令

语法：ssl_session_cache[builtin[:size[shared:name:size]

默认值：builtin:20480

使用环境：mail, server

该指令用于设置存储SSL会话的缓存类型和大小。缓存类型如下：

builtin——OpenSSL内建缓存，只能在一个工作进程中使用。缓存大小为会话数。

shared——缓存在所有工作进程中共享。缓存的大小以字节数指定，1MB的缓存客户容纳大约4000个会话。每个共享缓存必须有独自的名称，同名的缓存客户在不同的虚拟主机中使用。

可以同时使用两种缓存类型，例如：

然而，只使用共享缓存而不使用内建缓存要更有效。

15.4.8　ssl_session_timeout指令

语法：ssl_session_timeout time

默认值：5m

使用环境：mail, server

该指令用于设置客户端可以重复使用存储在缓存中的会话参数时间。

15.4.9　starttls指令

语法：starttls on|off|only

默认值：off

使用环境：mail, server

on——允许使用POP3的STLS命令和IMAP/SMTP的STARTTLS命令。

off——不允许使用命令STLS/STARTTLS。

only——开启STLS/STARTTLS支持，并且需要客户端使用TLS编码。

15.5　Nginx邮件模块配置实例

在这一节中，我们通过使用PHP脚本来进行后端认证，以展示如何配置Nginx邮件模块：

（1）假设你的POP3/IMAP邮件代理服务器Nginx运行在192.168.1.1。

（2）假设你有两台POP3/IMAP后端邮件服务器：192.168.22和192.168.33。

（3）假设你有一台认证和重定向服务器：192.168.1.44。

（4）认证脚本为：/mail/auth.php。

192.168.1.1服务器上的nginx.conf配置文件如代码15-1所示：

代码15-1

192.168.1.44服务器上的/mail/auth.php脚本内容如代码15-2所示：

代码15-2

注释

1　21世纪都来了，现在除了类似于百度的蜘蛛之类的东西不支持自解压，99.99％的浏览器基本上都支持gzip解压，所以可以不用设这个值，保持系统默认即可。

索　引

A

accept_mutex

accept_mutex_delay

access_log

add_after_body

add_before_body

add_header

addition_types

alias

allow

ancient_browser

ancient_browser_value

apache

arg_PARAMETER

args

auth

auth_basic

auth_basic_user_file

auth_http

auth_http_header

auth_http_timeout

autoindex

autoindex_exact_size

autoindex_localtime

B

binary_remote_addr

本地缓存

并发连接

补丁

C

CentOS

charset

charset_map

Chrome

client_body_buffer_size

client_body_in_file_only

client_body_in_single_buffer

client_body_temp_path

client_body_timeout

client_header_buffer_size

client_header_timeout

client_max_body_size

configure

content_length

content_type

cookie_COOKIE

create_full_put_path

错误日志

D

daemon

date_gmt

date_local

dav_access

dav_methods

debug_connection

debug_points

default_type

deny

directio

document_root

document_uri

宕机

端口

E

eAcelerator

empty_gif

env

epoll

error_log

error_page

eth0

expires

F

F5 BIG-IP

FastCGI

fastcgi_buffer_size

fastcgi_buffers

fastcgi_buffers

fastcgi_cache

fastcgi_cache_key

fastcgi_cache_methods

fastcgi_hide_header

fastcgi_ignore_client_abort

fastcgi_index

fastcgi_intercept_errors

fastcgi_max_temp_file_size

fastcgi_param

fastcgi_pass

fastcgi_pass_header

fastcgi_read_timeout

fastcgi_redirect_errors

fastcgi_split_path_info

Firefox

flv

fms

FreeBSD

反向代理

负载均衡

G

gcc

geo

geoip_city

geoip_country

google_perftools_profiles

gzip

gzip_buffers

gzip_comp_level

gzip_http_version

gzip_min_length

gzip_proxied

gzip_static

gzip_types

故障转移

关键帧

过滤

H

Header

http_HEADER

http_user_agent

https

后台

I

if_modified_since

ifconfig

IIS

image_filter

image_filter_buffer

image_filter_jpeg_quality

image_filter_transparency

imap_capabilities

imap_client_buffer

include

index

internal

is_args

J

jsp

JW Player

健康检查

节点

K

keepalive_requests

keepalive_timeout

kill

kqueue

开源协议

L

LAMP

large_client_header_buffers

lighttpd

limit_conn

limit_except

limit_rate

limit_rate_after

limit_req

limit_req_zone

limit_zone

listen

lock_file

log_format

log_format_combined

log_not_found

log_subrequest

连接数

流媒体

M

map

map_hash_bucket_size

map_hash_max_size

master_process

memcache

memcached_buffer_size

memcached_connect_timeout

memcached_next_upstream

memcached_pass

memcached_read_timeout

memcached_send_timeout

modern_browser

modern_browser_value

mono

msie_padding

msie_refresh

my.cnf

N

ncache

NetScaler

nginx.conf

nginx_version

内存消耗

O

open_file_cache

open_file_cache_errors

open_file_cache_min_uses

open_file_cache_valid

open_log_file_cache

openssl

Opera

optimize_server_names

OSI

override_charset

P

PCRE

Perl

perl_modules

perl_require

perl_set

php.ini

pid

pop3_auth

pop3_capabilities

port_in_redirect

protocol

proxy_add_x_forwarded_for

proxy_buffer

proxy_buffer_size

proxy_buffering

proxy_buffers

proxy_busy_buffers_size

proxy_cache

proxy_connect_timeout

proxy_headers_hash_bucket_size

proxy_headers_hash_max_size

proxy_hide_header

proxy_host

proxy_ignore_client_abort

proxy_ignore_headers

proxy_intercept_errors

proxy_max_temp_file_size

proxy_method

proxy_next_upstream

proxy_pass

proxy_pass_error_message

proxy_pass_header

proxy_pass_request_body

proxy_pass_request_headers

proxy_port

proxy_read_timeout

proxy_redirect

proxy_redirect_errors

proxy_send_lowat

proxy_send_timeout

proxy_set_body

proxy_set_header

proxy_store

proxy_store_access

proxy_temp_file_write_size

proxy_temp_path

proxy_timeout

proxy_upstream_fail_timeout

proxy_upstream_max_fails

平滑重启

Q

query_string

轻量级

R

random_index

rc.local

real_ip_header

realpath_root

recursive_error_pages

Red5

remote_addr

remote_port

remote_user

request_body

request_body_file

request_filename

request_method

request_uri

resolver

resolver timeout

Rewrite

root

route

rtmpt

日志

S

satisfy_any

scheme

secure_link

secure_link_secret

send_timeout

sendfile

server

server_name

server_name_in_redirect

server_names_hash_bucket_size

server_names_hash_max_size

server_port

server_protocol

server_tokens

set_real_ip_from

smtp_auth

smtp_capabilities

so_keepalive

source_charset

Squid

ssi

ssi_silent_errors

ssi_types

ssi_value_length

ssl

ssl_certificate

ssl_certificate_key

ssl_ciphers

ssl_client_certificate

ssl_crl

ssl_dhparam

ssl_engine

ssl_prefer_server_ciphers

ssl_protocols

ssl_session_cache

ssl_session_timeout

ssl_verify_client

ssl_verify_depth

starttls

stub_Status

sub_filter

sub_filter_once

sub_filter_types

swap

生产环境

视频

T

tcp_nodelay

tcp_nopush

timeout

timer_resolution

tomcat

try_files

types

U

UDP

upstream

uri

use

user

userid

userid_domain

userid_expires

userid_name

userid_p3p

userid_path

userid_service

V

valid_referers

VPS

W

worker_connections

worker_cpu_affinity

worker_priority

worker_processes

worker_rlimit_core

worker_rlimit_nofile

worker_rlimit_sigpending

working_directory

文件描述符

X

xclient

xslt_entities

xslt_stylesheet

xslt_types

系统负载

信号

虚拟主机

Y

Yamdi

yum

压力测试

压缩输出

Z

正则表达式

参考资料

1　Nginx官网维基

http://wiki.nginx.org/

2　NCache使用说明书

http://code.google.com/p/ncache/w/list

3　January 2009 Web Server Survey by Netcraft

http://news.netcraft.com/archives/2009/01/16/january_2009_web_server_survey.html

4　张宴．Nginx 0.8.x+PHP 5.2.10（FastCGI）搭建胜过Apache十倍的Web服务器．2009-4

http://blog.s135.com/post/366/

5　张宴．使用Nginx轻松实现开源负载均衡．2008-9

http://blog.s135.com/chinaunix_nginx/

6　张宴．高性能Web服务器Nginx及相关新技术的应用实践．2009-10

http://blog.s135.com/sd2c_nginx/

编辑手记

2008年9月，车东推荐了一个主题为“回忆未来”的博客，说值得关注，博客上关于Web服务器开发的内容很多。我们当时正打算组织PHP开发方面的选题，便给博主发了封邮件。

隔天收到了对方的回复。他叫张宴，当时在新浪播客担任系统工程师。

后来在MSN上和张宴聊天，才知道他毕业不久，本科读的是国际经济与贸易，母校是武汉的中南民族大学。学校离我们公司不过两三站路，我每天上下班打他学校门口过，没准以前两人还撞见过。在武汉生活的经历，让我们有了更多的话题。那时他才不过24岁，我很好奇一个刚毕业的文科生怎么会在新浪担任系统工程师。他说自己1995年（小学五年级）开始接触386计算机与DOS系统，1999年接触互联网与HTML网页制作，2003年（大学一年级）开始涉足Linux、Apache、PHP、MySQL编程，同时开始做互联网应用，先是做民大经济学院网站，后来又先后做过民大新闻网、民大就业信息网、民大学生信息管理系统、民大论坛实名制改造、民大主站等项目，几乎把民大的网站做了个遍。

大约一个月后，我去北京出差，约他在第三极书店碰面，商量写书的细节。刚见面时，他比较腼腆，话不多，不像在MSN上那么健谈，后来聊到技术话题，他才渐渐放开。他当时已经离开新浪，去赶集网推广Nginx的应用。我是第一次听说Nginx。他于是饶有兴致地向我介绍他在新浪做的Nginx开源项目，以及他积累的Nginx反向代理、负载均衡、内容分发等方面的经验。当时各大门户网站都已经开始使用Nginx。但是Nginx的中文资料几乎没有，全靠大家自己摸索。于是我们决定暂时放下PHP开发的选题，着手做一本Nginx实战应用的书。

我们先列出简单的目录大纲，然后邀请业界专家为目录提建议。第九城市的吴捷、豆瓣的技术负责人洪强宁、猫扑前技术总监李俊麟先后对目录提出了修改建议，经过几轮修改，最后形成现在的目录结构。初稿完成后，我们又请吴捷试读了一部分，他反馈了很多细致的建议。在此向这些专家表示感谢！

写作的过程中，张宴完成了赶集网的工作目标，随后加入金山逍遥网担任架构师。由于逍遥网新游戏上线公测，他工作任务变得非常繁重，有时加班到夜里12点，但他仍然笔耕不辍，坚持完成了书稿。这种毅力着实让我们钦佩。衷心祝愿他今后为读者写出更多的作品。

在周筠老师持续的鼓励支持及同事的协助下，我们顺利地完成了书稿的后期制作。设计总监杨小勤为这本书设计了精美的封面，统稿编辑陈元玉认真细致地处理了书稿的细节，在此向他们表示感谢。希望这本博文的又一本原创图书能在春天里带给读者阅读的快乐。

徐定翔

2010年2月于武汉

《实战Nginx：取代Apache的高性能Web服务器》读者交流区

尊敬的读者：

感谢您选择我们出版的图书，您的支持与信任是我们持续上升的动力。为了使您能通过本书更透彻地了解相关领域，更深入的学习相关技术，我们将特别为您提供一系列后续的服务，包括：

1．提供本书的修订和升级内容、相关配套资料；

2．本书作者的见面会信息或网络视频的沟通活动；

3．相关领域的培训优惠等。

您可以任意选择以下四种方式之一与我们联系，我们都将记录和保存您的信息，并给您提供不定期的信息反馈。

1．在线提交

登陆www.broadview.com.cn/10247，填写本书的读者调查表。

2．电子邮件

您可以发邮件至jsj@phei.com.cn或editor@broadview.com.cn。

3．读者电话

您可以直接拨打我们的读者服务电话：010-88254369。

4．信件

您可以写信至如下地址：北京万寿路173信箱博文视点，邮编：100036。

您还可以告诉我们更多有关您个人的情况，及您对本书的意见、评论等，内容可以包括：

（1）您的姓名、职业、您关注的领域、您的电话、E-mail地址或通信地址；

（2）您了解新书信息的途径、影响您购买图书的因素；

（3）您对本书的意见、您读过的同领域的图书、您还希望增加的图书、您希望参加的培训等。

如果您在后期想停止接收后续资讯，只需编写邮件“退订＋需退订的邮箱地址”发送至邮箱：market@broadview.com.cn即可取消服务。

同时，我们非常欢迎您为本书撰写书评，将您的切身感受变成文字与广大书友共享。我们将挑选特别优秀的作品转载在我们的网站（www.broadview.com.cn）上，或推荐至CSDN.NET等专业网站上发表，被发表的书评的作者将获得价值50元的博文视点图书奖励。

更多信息，请关注博文视点官方微博：http://t.sina.com.cn/broadviewbj。

我们期待您的消息！

博文视点愿与所有爱书的人一起，共同学习，共同进步！

通信地址：北京万寿路173信箱　博文视点（100036）　　电话：010-51260888

E-mail：jsj@phei.com.cn，editor@broadview.com.cn

勃勃生机，潇洒开源

——设计手记

为何技术书就不能人文一点呢？

这是我们经常反思的一个问题，前面出版的一本设计模式方面的书就在此问题上做了大胆的尝试。这次我们心更大，要拿出一溜人文气息的作品来。挑战很大，我也很高兴接到这样的任务。不懈努力下，此系列开始陆续面世。博文的LAMP系列封面之前都是在植物底纹基础上做的设计（参见本书后勒口那本紫红色图书），新系列一改之前的低调隐晦，在画面上大胆秀出植物的芳彩，体态优美，潇洒大方。LAMP系列的所有图书封面都会运用统一风格的系列花卉植物形态，以表现LAMP领域各个方向的核心技术。再加上局部印金、亚光膜等工艺，有品质而不张扬。

为《实战Nginx：取代Apache的高性能Web服务器》进行封面设计时，一株鲜红色的花朵吸引了我，后来知道这花叫做“红掌”。红掌花鲜艳华丽，色彩浓郁，是世界名贵花卉。

红掌希腊文名之“安世莲”，译意为“有尾的花”。它有如一只伸开的红色手掌，在掌心上竖起一小条金黄色的肉穗，学名叫做“佛焰苞”。

希望这一束束生机勃勃的花朵，在貌似沉闷的技术书海中，能够带给广大读者朋友不一样的阅读体验。

杨小勤

2010年2月1日

博文视点设计团队博客：http://bvbook-design.blogbus.com

杨小勤博客：http://yangziqiu.blog.163.com

反侵权盗版声明

电子工业出版社依法对本作品享有专有出版权。任何未经权利人书面许可，复制、销售或通过信息网络传播本作品的行为，歪曲、篡改、剽窃本作品的行为，均违反《中华人民共和国著作权法》，其行为人应承担相应的民事责任和行政责任，构成犯罪的，将被依法追究刑事责任。

为了维护市场秩序，保护权利人的合法权益，我社将依法查处和打击侵权盗版的单位和个人。欢迎社会各界人士积极举报侵权盗版行为，本社将奖励举报有功人员，并保证举报人的信息不被泄露。

举报电话：（010）88254396；（010）88258888

传　　真：（010）88254397

E-mail：dbqq@phei.com.cn

通信地址：北京市万寿路173信箱

电子工业出版社总编办公室

邮　　编：100036

实战Nginx：

取代Apache的高性能Web服务器

Nginx是俄罗斯人lgor Sysoev编写的一款高性能的HTTP和反向代理服务器。Nginx选择了epoll和kqueue作为网络I/O模型，在高连接并发的情况下，Nginx是Apache服务器不错的替代品，它能够支持高达50000个并发连接数的响应，运行稳定，且内存、CPU等系统资源消耗非常低。

本书主要分为4个部分：

◆第1部分为基础篇，介绍了Nginx服务器的安装与配置

◆第2部分为进阶篇，重点介绍了Nginx的配置优化方法、Nginx与PHP/Ruby/Python/JSP/Pert/Memcached的结合配置方法、Nginx HTTP反向代理与负载均衡的配置与优化、Nginx模块开发等，最后还分析了新浪的开源软件项目——基于Nginx的NCACHE网页缓存系统；

◆第3部分为实战篇，分析了Nginx在国内知名网站（如新浪播客、搜狐博客等）中的应用案例；

◆第4部分为模块篇，对Nginx的基本模块和第三方模块进行了集中介绍。

本书是为对配置管理Nginx服务器感兴趣的读者准备的，适用于以前没有接触过Nginx，或者对Nginx有一些了解并希望能够进一步深入学习的专业系统工程师、个人网站站长及Linux/Unix从业人员。

2008年年底张宴加入了金山逍遥网，作为逍遥网技术部平台组组长，张宴带领组员重新设计了逍遥网的系统架构并加以实施。新系统架构用Nginx替换了原来所有的Apache服务器，既减少了服务器数量和带宽，又提高了整个平台的性能及易维护性。逍遥网全新的系统架构，充分展现了Nginx处理高并发的能力和易维护等特性。

——张鹏翼，金山逍遥网技术部经理

策划编辑：徐定翔

责任编辑：周　筠

责任美编：杨小勤