第1章 源码分析的准备工作

从Nginx(读作engine x)的官方网站http://www.nginx.org/en/,我们可以看到如下介绍:Nginx是Igor Sysoevhttp://sysoev.ru/en/编写的一款HTTP和反向代理服务器,另外它也可以当作邮件代理服务器。它一直被众多流量巨大的俄罗斯网站所使用,例如Yandexhttp://www.yandex.ru/、Mail.Ruhttp://www.mail.ru/、VKontaktehttp://vkontakte.ru/以及Ramblerhttp://www.rambler.ru/等。据Netcraft统计,截止到2012年8月份,世界上最繁忙的网站中有11.48%http://news.netcraft.com/archives/2012/08/02/august-2012-web-server-survey.html在使用Nginx作为其服务器或者代理服务器。部分典型成功案例有:Netflixhttps://signup.netflix.com/openconnect/software、Wordpress.comhttp://www.nginx.com/cs/nginx-automattic.html和FastMail.FMhttp://blog.fastmail.fm/2007/01/04/webimappop-frontend-proxies-changed-to-nginx/。鉴于Nginx的强大性能与稳定性,在国内也有大量的高压力网站在使用Nginx,如新浪、网易、腾讯、CSDN、酷六、水木社区、豆瓣等。

1.1 主要特性

作为轻量级HTTP服务的典型代表,Nginx除了具备体积小、配置灵活、并发能力强、稳定等众所周知的特点以外,在官方网站还详细列出了Nginx的一些主要特性,我们来详细了解一下http://www.nginx.org/en/

1. HTTP服务基本特性

● 处理静态页面请求;

● 处理index首页请求;

● 对请求目录进行列表显示;

● 支持多进程间的负载均衡;

● 对打开文件描述符进行缓存(提高性能);

● 对反向代理进行缓存(加速);

● 支持FastCGI、uwsgi、SCGI和memcached多种后端服务器;

● 支持gzip、ranges、chunked、XSLT、SSI以及图像缩放;

● 支持SSL、TLS SNI。

2. HTTP服务高级特性

● 基于名称的虚拟主机;

● 基于IP的虚拟主机;

● 支持Keep-alive和pipelined连接;

● 灵活和方便的配置;

● 在更新配置和升级执行程序时提供不间断服务;

● 可自定义客户端访问的日志格式;

● 带缓存的日志写操作(提高性能);

● 支持快速的日志文件切换;

● 支持对3xx-5xx错误代码进行重定向;

● URI重写支持正则表达式;

● 根据客户端地址执行不同的功能;

● 支持基于客户端IP地址的访问控制;

● 支持基于HTTP基本认证机制的访问控制;

● 支持HTTP referer验证;

● 支持HTTP协议的PUT、DELETE、MKCOL、COPY以及MOVE方法;

● 支持FLV流和MP4流;

● 支持限速机制;

● 支持单客户端的并发控制;

● 支持Perl脚本嵌入。

3. 邮件代理服务特性

● 使用外部HTTP认证服务器将用户重定向到IMAP/POP3服务器;

● 使用外部HTTP认证服务器将用户重定向到内部SMTP服务器;

● 支持的认证方式。

◆ POP3:USER/PASS、APOP、AUTH LOGIN/PLAIN/CRAM-MD5。

◆ IMAP:sLOGIN、AUTH LOGIN/PLAIN/CRAM-MD5。

◆ SMTP:AUTH LOGIN/PLAIN/CRAM-MD5。

● 支持SSL;

● 支持STARTTLS和STLS。

4. 架构和扩展性

● 一个主进程和多个工作进程配合服务的工作模型;

● 工作进程以非特权用户运行(安全性考虑);

● 支持的事件机制有:kqueue(FreeBSD 4.1+)、epoll(Linux 2.6+)、rt signals(Linux 2.2.19+)、/dev/poll(Solaris 7 11/99+)、event ports(Solaris 10)、select和poll;

● 支持kqueue的众多特性,包括EV_CLEAR、EV_DISABLE(临时禁止事件)、NOTE_LOWAT、EV_EOF等;

● 支持sendfile(FreeBSD 3.1+、Linux 2.2+、Mac OS X 10.5+)、sendfile64(Linux 2.4.21+)和sendfilev(Solaris 8 7/01+);

● 支持异步文件IO(FreeBSD 4.3+、Linux 2.6.22+);

● 支持DIRECTIO(FreeBSD 4.4+、Linux 2.4+、Solaris 2.6+、Mac OS X);

● 支持Accept-filters(FreeBSD 4.1+、NetBSD 5.0+)和TCP_DEFER_ACCEPT(Linux 2.4+);

● 10000个非活跃HTTP keep-alive连接仅占用约2.5MB内存;

● 最少程度的数据拷贝操作。

5. 已测试过的操作系统和平台

● FreeBSD 3~10/i386、FreeBSD 5~10/amd64;

● Linux 2.2~3/i386、Linux 2.6~3/amd64;

● Solaris 9/i386、sun4u、Solaris 10/i386、amd64、sun4v;

● AIX 7.1/powerpc;

● HP-UX 11.31/ia64;

● Mac OS X/ppc、i386;

● Windows XP、Windows Server 2003。

从上面列表可以看到Nginx功能的丰富与强悍。当然,这里给出的还只是Nginx功能的简单描述,而对于每项功能的具体使用以及是如何实现的,我们还不得而知,而这也正是本书将要展开叙述的全部内容。

1.2 源码下载

Nginx的源码可通过官网提供的下载地址http://nginx.org/en/download.html找到,截止当前的最新版本是Nginx 1.2.0,也就是本书所针对的版本。虽然官网下载页没有提供Nginx旧版源码的下载链接,但Nginx的所有版本源码包都是放在目录http://nginx.org/download/下的,所以包括Nginx 0.1.0版本在内的Nginx源码都能下载到。

由于Nginx背后有公司运作,所以其更新速度比较快,相关资料也比较齐全,下面是一些有用的网址。

● 官方主页:http://nginx.org/

● 使用手册:http://nginx.org/en/docs/

● 配置指令:http://wiki.nginx.org/DirectiveIndex

● 版本任务:http://trac.nginx.org/nginx/report/2

● 开发路线图:http://trac.nginx.org/nginx/roadmap

● 邮件讨论组:http://mailman.nginx.org/mailman/listinfo

所有相关信息基本都能从官方主页链入,如果想找什么资料,建议先去官网看看。

1.3 源码目录结构

将Nginx源码包解压后,目录文件如下所示。

        [root@localhost nginx-1.2.0]# ls -F
        auto/ CHANGES CHANGES.ru conf/ configure* contrib/ html/ LICENSE man/ README src/

其中

● auto/:包含了很多会在执行configure进行编译配置时调用的检测代码。

● CHANGES:Nginx的版本更新细节记录。英文版。

● CHANGES.ru:Nginx的版本更新细节记录。俄文版。

● conf/:Nginx提供的一些默认配置文件。

● configure*:根据系统环境设定Nginx编译选项的执行脚本。

● contrib/:网友贡献的一些有用脚本。

● html/:提供了两个默认html页面,比如index.html的Welcome to nginx!。

● LICENSE:声明的Nginx源码许可协议。

● man/:Nginx的Man手册,本文文件,可直接用vi或记事本打开。

● README:读我文件,内容很简单,通告一下官网地址。

● src/:Nginx源码,分门别类,比如实现事件的event等,很清晰。

执行configure脚本后将生成Makefile文件和objs目录,这是根据当前系统环境生成的相关编译配置。Nginx并没有使用Autoconfhttp://www.gnu.org/software/autoconf/和Automakehttp://www.gnu.org/software/automake/等这样的自动化工具来做这个工作,而都是手动编码实现的。比如当Nginx判断当前Linux系统是否支持epoll时,它采用的方法就是编写一款小应用程序,并在其中调用epoll_create()函数,然后再根据它是否可被正常编译执行来做这个判断。具体可参考文件nginx-1.2.0/auto/os/linux和nginx-1.2.0/auto/feature内相关代码。

1.4 源码分析工具

对于Windows平台,首选Source Insighthttp://www.sourceinsight.com/源码阅读工具。该工具功能强大,根据其官方网介绍,Source Insight是一款面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++、C#和Java等程序的分析功能。Source Insight能自动分析和动态维护源码工程的符号数据库,并在用户查看代码时显示有用的对应上下文信息。

如果是在Linux平台下,则可以利用Vihttp://vim.sourceforge.net/、Taglisthttp://vim-taglist.sourceforge.net/、Cscopehttp://cscope.sourceforge.net/以及Ctaghttp://ctags.sourceforge.net/这几个工具来组合成Nginx源码的环境。它们的组合也许要费一段功夫,但磨刀不误砍柴工,为了更方便快捷地阅读Nginx源码,花这点时间还是比较值得的。

当然,我们还有另外一个更方便简单的选择:Source Navigator http://sourcenav.sourceforge.net/。Source Navigator(Sourcenav)是由Red Hat推出的一款查看和分析源代码的强大图形界面工具,可以与前面介绍的Source Insight相媲美,而且Sourcenav是开源的。除了提供源代码的编辑、查看功能,Sourcenav同时还支持编译器和调试器的集成,因此可以构建成一套完整的IDE开发环境。Sourcenav针对Windows和UNIX/Linux,提供两种版本,在Windows下的版本,解压即可以使用,但是要注意解压路径不能包含空格以及中文字符。图1-1所示是Sourcenav在Ubuntu 8.10平台下的运行界面。

图1-1 Sourcenav在Ubuntu 8.10平台下的运行界面

不管是在Windows平台下还是在Linux平台下,搭建一个得心应手的源码阅读环境,是我们阅读源码达到事半功倍效果的有力保证。

1.5 测试辅助工具

我们将在第2章里介绍如何对Nginx进行跟踪与调试,除了对Nginx进程进行直接的跟踪与调试的工具以外,还会用到另外两个HTTP测试工具:wgethttp://www.gnu.org/software/wget/与curlhttp://curl.haxx.se/。关于这两个工具的差别,可以看这里http://daniel.haxx.se/docs/curl-vs-wget.html,要注意的主要是wget 1.12及以前的版本仅支持HTTP 1.0协议(虽然也包括部分HTTP 1.1的特性),所以在测试HTTP 1.1的相关特性时,最好使用wget-1.13以后版本或curl。另外,通过给wget加上--debug选项或给curl加上-v选项能看到它们请求的详细信息http://lenky.info/?p=1841,这对我们的测试提供的帮助也非常大。

我用到的其他测试辅助工具主要还有如下几个。

● Wiresharkhttp://www.wireshark.org/:抓包使用。

● Nchttp://netcat.sourceforge.net/:网络工具中的瑞士军刀,短小精悍,功能强大http://linux.die.net/max/I/nc

● Firefoxhttp://www.mozilla.org/en-US/firefox/fx/#desktop:结合firebughttps://getfirebug.com/看HTTP请求响应内容。

● Operahttp://www.opera.com/:浏览器,测试HTTP。

● Hexdumpftp://ftp.kernel.org/pub/linux/utils/util-linux/:看十六进制数据。

1.6 编译与执行

Nginx的编译安装很简单,使用Linux下通用的三板斧即可:./configure、make、make install。当然,这样做的话,那么一切都是使用的默认配置,如果要做修改,则必须在执行configure时指定,比如对Nginx加上调试功能。

      [root@localhost nginx-1.2.0]# ./configure --with-debug

修改默认安装路径。

      [root@localhost nginx-1.2.0]# ./configure --prefix=/usr/gqk/

所有这些配置选项可以通过命令查看。

      [root@localhost nginx-1.2.0]# ./configure -help

在默认情况下,Nginx被安装在/usr/local/nginx/目录下,而其他目录也大都以此为父目录,比如Web根目录为/usr/local/nginx/html/,日志记录在文件/usr/local/nginx/logs/access.log和/usr/local/nginx/logs/error.log内。

编译好后的Nginx,执行它很简单,一般我们只需指定配置文件即可。

      [root@localhost ~]# /home/gqk/nginx-1.2.0/objs/nginx -c /usr/local/nginx/conf/ nginx.conf.test

如果不指定配置文件,那么默认就是安装目录下的nginx.conf文件,比如:/usr/local/nginx/conf/nginx.conf。通过ps命令可以看到Nginx是否已正常执行。

        [root@localhost ~]# ps auxf | grep nginx | grep -v grep
        root     3949  0.0  0.1  5216  572   ?  Ss  Oct05  0:00  nginx:  master  process  /home/gqk/nginx-1.2.0/objs/nginx -c /usr/local/nginx/conf/nginx.conf.test
        nobody 3950 0.0 0.354041236 ? T  Oct05 0:00  \_ nginx: worker process

查看Nginx对应的监听套接口。

        [root@localhost ~]# netstat -natp | grep nginx
        tcp  0  0 0.0.0.0:80  0.0.0.0:*  LISTEN  3949/nginx

1.7 其他准备

本书主要针对的是Nginx的Web服务器功能,这其中牵扯到很多的国际标准协议,比如说HTTP协议、URL标准、HTML标准等。因此,把与之相关的RFC文档准备好是必不可少的。这里列出几个站点,方便查阅。

http://www.rfc.net RFC的官方站点要查阅rfc文档直接访问http://www.ietf.org/rfc/rfc----.txt或http://tools.ietf.org/html/rfc----,将横线换成rfc文档的对应序号,比如:http://www.ietf.org/rfc/rfc2616.txt或http://tools.ietf.org/html/rfc2616。,可以检查RFC最及时的更新情况。

http://www.ietf.org 最重要的Internet组织之一。

http://sunsite.dk RFC查询非常强大(可以以FTP登录下载全部RFC文档)。

http://www.iso.ch ISO-国际标准化组织。

http://standards.ieee.org IEEE-电气与电子工程师协会。

http://web.ansi.org ANSI-美国国家标准化组织。

http://www.itu.int ITU-国际电信同盟。

http://www.rfc-editor.org/ RFC归档搜索网。

http://www.faqs.org/rfcs/ RFC归档搜索网。

http://www.cnpaf.net/ 中国协议分析网。