深入理解nginx读书笔记1——研究 Nginx 前的准备工作

摘自《深入理解nginx》的一些信息,作为以后的查看资料。

 

        2012 年,Nginx 荣获年度云计算开发奖(2012 Cloud Award for Developer of the Year),并成长为世界第二大 Web 服务器。全世界流量最高的前 1000 名网站中,超过 25% 都使用Nginx 来处理海量的互联网请求。Nginx 已经成为业界高性能 Web 服务器的代名词。

 

         Nginx 的竞争对手—Apache、Lighttpd、Tomcat、Jetty、IIS,它们都是 Web 服务器,或者叫做 WWW(World Wide Web)服务器。

        由于 Nginx 使用基于事件驱动的架构能够并发处理百万级别的 TCP 连接,高度模块化的设计和自由的许可证使得扩展 Nginx 功能的第三方模块层出不穷,而且优秀的设计带来了极佳的稳定性,因此其作为 Web 服务器被广泛应用到大流量的网站上,包括腾讯、新浪、网易、淘宝等访问量巨大的网站。

 

        Nginx 是一个跨平台的 Web 服务器,可运行在 Linux、FreeBSD、Solaris、AIX、MacOS、Windows 等操作系统上,并且它还可以使用当前操作系统特有的一些高效 API 来提高自己的性能。

        例如,对于高效处理大规模并发连接,它支持 Linux 上的 epoll(epoll 是 Linux 上处理大并发网络连接的利器,9.6.1 节中将会详细说明 epoll 的工作原理)、Solaris 上的 event ports和 FreeBSD 上的 kqueue 等。又如,对于 Linux,Nginx 支持其独有的 sendfile 系统调用,这个系统调用可以高效地把
硬盘中的数据发送到网络上(不需要先把硬盘数据复制到用户态内存上再发送),这极大地减少了内核态与用户态数据间的复制动作。

Nginx 具有以下特点:
(1)更快
这表现在两个方面 :一方面,在正常情况下,单次请求会得到更快的响应 ;另一方面,在高峰期(如有数以万计的并发请求),Nginx 可以比其他 Web 服务器更快地响应请求。实际上,本书第三部分中大量的篇幅都是在说明 Nginx 是如何做到这两点的。


(2)高扩展性
Nginx 的设计极具扩展性,它完全是由多个不同功能、不同层次、不同类型且耦合度极低的模块组成。这种低耦合度的优秀设计,造就了 Nginx 庞大的第三方模块,当然,公开的第三方模块也如官方发布的模块一样容易使用。


(3)高可靠性
高可靠性是我们选择 Nginx 的最基本条件,因为 Nginx 的可靠性是大家有目共睹的,很多家高流量网站都在核心服务器上大规模使用 Nginx。Nginx 的高可靠性来自于其核心框架代码的优秀设计、模块设计的简单性 ;另外,官方提供的常用模块都非常稳定,每个 worker进程相对独立,master 进程在 1 个 worker 进程出错时可以快速“拉起”新的 worker 子进程提供服务。


(4)低内存消耗
一般情况下,10 000 个非活跃的 HTTP Keep-Alive 连接在 Nginx 中仅消耗 2.5MB 的内存,这是 Nginx 支持高并发连接的基础。从第 3 章开始,我们会接触到 Nginx 在内存中为了维护一个 HTTP 连接所分配的对象,届时将会看到,实际上 Nginx 一直在为用户考虑(尤其是在高并发时)如何使得内存的消耗更少。


(5)单机支持 10 万以上的并发连接
这是一个非常重要的特性!随着互联网的迅猛发展和互联网用户数量的成倍增长,各大公司、网站都需要应付海量并发请求,一个能够在峰值期顶住 10 万以上并发请求的 Server,无疑会得到大家的青睐。理论上,Nginx 支持的并发连接上限取决于内存,10 万远未封顶。当然,能够及时地处理更多的并发请求,是与业务特点紧密相关的。


(6)热部署
master 管理进程与 worker 工作进程的分离设计,使得 Nginx 能够提供热部署功能,即可以在 7×24 小时不间断服务的前提下,升级 Nginx 的可执行文件。当然,它也支持不停止服务就更新配置项、更换日志文件等功能。


(7)最自由的 BSD 许可协议
这是 Nginx 可以快速发展的强大动力。BSD 许可协议不只是允许用户免费使用 Nginx,它还允许用户在自己的项目中直接使用或修改 Nginx 源码,然后发布。这吸引了无数开发者继续为 Nginx 贡献自己的智慧。


以上 7 个特点当然不是 Nginx 的全部,拥有无数个官方功能模块、第三方功能模块使得Nginx 能够满足绝大部分应用场景,这些功能模块间可以叠加以实现更加强大、复杂的功能,有些模块还支持 Nginx 与 Perl、Lua 等脚本语言集成工作,大大提高了开发效率。这些特点促使用户在寻找一个 Web 服务器时更多考虑 Nginx。

 

 

使用 Nginx 的必备软件

(1)GCC 编译器

GCC(GNU Compiler Collection)可用来编译 C 语言程序。

(2)PCRE 库
PCRE(Perl Compatible Regular Expressions,Perl 兼容正则表达式)是由 Philip Hazel开发的函数库,目前为很多软件所使用,该库支持正则表达式。如果我们在配置文件 nginx.conf 里使用了正则表达式,那么在编译 Nginx 时就必须把PCRE 库编译进 Nginx,因为 Nginx 的 HTTP 模块要靠它来解析正则表达式。

(3)zlib 库
zlib 库用于对 HTTP 包的内容做 gzip 格式的压缩,如果我们在 nginx.conf 里配置了 gzipon,并指定对于某些类型(content-type)的 HTTP 响应使用 gzip 来进行压缩以减少网络传输量。

(4)OpenSSL 开发库
如果我们的服务器不只是要支持 HTTP,还需要在更安全的 SSL 协议上传输 HTTP,那么就需要拥有 OpenSSL 了。另外,如果我们想使用 MD5、SHA1 等散列函数,那么也需要安装它。

上面所列的 4 个库只是完成 Web 服务器最基本功能所必需的。
Nginx 是高度自由化的 Web 服务器,它的功能是由许多模块来支持的。而这些模块可根据我们的使用需求来定制,如果某些模块不需要使用则完全不必理会它。同样,如果使用了某个模块,而这个模块使用了一些类似 zlib 或 OpenSSL 等的第三方库,那么就必须先安装这些软件。

 

 磁盘目录
要使用 Nginx,还需要在 Linux 文件系统上准备以下目录。
(1)Nginx 源代码存放目录
该目录用于放置从官网上下载的 Nginx 源码文件,以及第三方或我们自己所写的模块源代码文件。


(2)Nginx 编译阶段产生的中间文件存放目录
该目录用于放置在 configure 命令执行后所生成的源文件及目录,以及 make 命令执行后生成的目标文件和最终连接成功的二进制文件。默认情况下,configure 命令会将该目录命名为 objs,并放在 Nginx 源代码目录下。


(3)部署目录
该目录存放实际 Nginx 服务运行期间所需要的二进制文件、配置文件等。默认情况下,该目录为 /usr/local/nginx。


(4)日志文件存放目录
日志文件通常会比较大,当研究 Nginx 的底层架构时,需要打开 debug 级别的日志,这个级别的日志非常详细,会导致日志文件的大小增长得极快,需要预先分配一个拥有更大磁盘空间的目录。

 

Linux 内核参数的优化
由于默认的 Linux 内核参数考虑的是最通用的场景,这明显不符合用于支持高并发访问的 Web 服务器的定义,所以需要修改 Linux 内核参数,使得 Nginx 可以拥有更高的性能。在优化内核时,可以做的事情很多,不过,我们通常会根据业务特点来进行调整,当Nginx 作为静态 Web 内容服务器、反向代理服务器或是提供图片缩略图功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使 Nginx 支持更多并发请求的 TCP 网络参数做简单说明。


首先,需要修改 /etc/sysctl.conf 来更改内核参数。例如,最常用的配置:
fs.file-max = 999999
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.ip_local_port_range = 1024 61000
net.ipv4.tcp_rmem = 4096 32768 262142
net.ipv4.tcp_wmem = 4096 32768 262142
net.core.netdev_max_backlog = 8096
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 2097152
net.core.wmem_max = 2097152
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn.backlog=1024


然后执行 sysctl -p 命令,使上述修改生效。
上面的参数意义解释如下:
file-max :这个参数表示进程(比如一个 worker 进程)可以同时打开的最大句柄数,
这个参数直接限制最大并发连接数,需根据实际情况配置。


tcp_tw_reuse:这个参数设置为 1,表示允许将 TIME-WAIT 状态的 socket 重新用于新的 TCP 连接,这对于服务器来说很有意义,因为服务器上总会有大量 TIME-WAIT 状态的连接。


tcp_keepalive_time:这个参数表示当 keepalive 启用时,TCP 发送 keepalive 消息的频度。默认是 2 小时,若将其设置得小一些,可以更快地清理无效的连接。


tcp_fin_timeout :这个参数表示当服务器主动关闭连接时,socket 保持在 FIN-WAIT-2状态的最大时间。

tcp_max_tw_buckets:这个参数表示操作系统允许 TIME_WAIT 套接字数量的最大值,如果超过这个数字,TIME_WAIT 套接字将立刻被清除并打印警告信息。该参数默认为 180 000,过多的 TIME_WAIT 套接字会使 Web 服务器变慢。

tcp_max_syn_backlog:这个参数表示 TCP 三次握手建立阶段接收 SYN 请求队列的最大长度,默认为 1024,将其设置得大一些可以使出现 Nginx 繁忙来不及 accept 新连接的情况时,Linux 不至于丢失客户端发起的连接请求。

ip_local_port_range:这个参数定义了在 UDP 和 TCP 连接中本地(不包括连接的远端)端口的取值范围。

net.ipv4.tcp_rmem :这个参数定义了 TCP 接收缓存(用于 TCP 接收滑动窗口)的最小值、默认值、最大值。

net.ipv4.tcp_wmem :这个参数定义了 TCP 发送缓存(用于 TCP 发送滑动窗口)的最小值、默认值、最大值。

netdev_max_backlog :当网卡接收数据包的速度大于内核处理的速度时,会有一个队列保存这些数据包。这个参数表示该队列的最大值。

rmem_default:这个参数表示内核套接字接收缓存区默认的大小。

wmem_default:这个参数表示内核套接字发送缓存区默认的大小。

rmem_max:这个参数表示内核套接字接收缓存区的最大大小。

wmem_max:这个参数表示内核套接字发送缓存区的最大大小。

 

tcp_syncookies:该参数与性能无关,用于解决 TCP 的 SYN 攻击。

你可能感兴趣的:(源码解析,Nginx)