一、操作系统
首先我们需要一个内核为Linux2.6及以上版本的操作系统,因为Linux2.6及以上内核才支持 epoll,而在Linux上使用select或poll来解决事件的多路复用,是无法解决高并发压力问题的。我们可以使用uname-a命令来查询Linux内核版本,例如:
wesinx@ecm-eb97:/$ uname -a
Linux ecm-eb97 5.4.0-171-generic #189-Ubuntu SMP Fri Jan 5 14:23:02 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
二、使用 Nginx 的必备软件
(1)GCC 编译器
GCC(GNU Compiler Collection)可用来编译C语言程序。Nginx不会直接提供二进制可执行程序(1.2.x版本中已经开始提供某些操作系统上的二进制安装包了,不过,本书探讨如何开发Nginx模块是必须通过直接编译源代码进行的),这有许多原因,本章后面会详述我们可以使用最简单的yum方式安装GCC,例如:
yum install y gcc
GCC是必需的编译工具。后续会提到如何使用C++来编写Nginx HTTP模块,这时就需要用到 G++编译器了。G++ 编译器也可以用 yum 安装,例如:
yum install y gcc-c++
Linux上有许多软件安装方式,yum 只是其中比较方便的一种,其他方式这里不再赘述。
(2)PCRE 库
PCRE(Perl Compatible Regular Expressions, Perl 兼容正则表达式)是由 Philip Hazel 开发的函数库,目前为很多软件所使用,该库支持正则表达式。它由RegEx演化而来,实际上,Perl 正则表达式也是源自于 Henry Spencer 写的 RegEx。
如果我们在配置文件nginx.conf里使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx,因为Nginx的HTTP模块要靠它来解析正则表达式。当然,如果你确认不会使用正则表达式,就不必安装它。其yum安装方式如下:
yum instally pcre pcre-devel
pcre-devel是使用PCRE做二次开发时所需要的开发库,包括头文件等,这也是编译Nginx 所必须使用的。
(3)zlib库
zlib 库用于对 HTTP包的内容做 gzip格式的压缩,如果我们在nginx.conf里配置了gzip并指定对于某些类型(content-type)的HTTP响应使用gzip来进行压缩以减少网络传输on,量,那么,在编译时就必须把zlib 编译进Nginx。其yum 安装方式如下:
yum insta1l y zlib zlib-devel
同理,zlib 是直接使用的库,zlib-devel是二次开发所需要的库。
(4)0penSSl开发库
如果我们的服务器不只是要支持HTTP,还需要在更安全的SSL协议上传输HTTP,那么就需要拥有 OpenSsL了。另外,如果我们想使用MD5、SHA1等散列函数,那么也需要安装它。其yum 安装方式如下:
yum instally openssl openssl-devel
上面所列的4个库只是完成Web服务器最基本功能所必需的,Ngnx 是高度自由化的 Wb服务器,它的功能是由许多模块来支持的。而这些模块可根据我们的使用需求来定制,如果某些模块不需要使用则完全不必理会它。同样,如果使用了某个模块,而这个模块使用了一些类似zlib或 OpenSsL等的第三方库,那么就必须先安装这些软件。
三、磁盘目录
要使用Nginx,还需要在Linux文件系统上准备以下目录。
(1)Nginx 源代码存放目录
该目录用于放置从官网上下载的Nginx源码文件,以及第三方或我们自己所写的模块源代码文件。
(2)Nginx编译阶段产生的中间文件存放目录
该目录用于放置在 configure 命令执行后所生成的源文件及目录,以及make 命令执行后生成的目标文件和最终连接成功的二进制文件。默认情况下,configure命令会将该目录命名为objs,并放在 Nginx源代码目录下。
(3)部署目录
该目录存放实际Nginx服务运行期间所需要的二进制文件、配置文件等。默认情况下,该目录为 /usr/localnginx。
(4)日志文件存放目录
日志文件通常会比较大,当研究Nginx的底层架构时,需要打开debug级别的日志,这个级别的日志非常详细,会导致日志文件的大小增长得极快,需要预先分配一个拥有更大磁盘空间的目录。
四、Linux 内核参数的优化
由于默认的Linux内核参数考虑的是最通用的场景,这明显不符合用于支持高并发访问的 Web服务器的定义,所以需要修改 Linux内核参数,使得Nginx 可以拥有更高的性能。在优化内核时,可以做的事情很多,不过,我们通常会根据业务特点来进行调整,当Nginx作为静态 Web内容服务器、反向代理服务器或是提供图片缩略图功能(实时压缩图片)的服务器时,其内核参数的调整都是不同的。这里只针对最通用的、使Nginx支持更多并发请求的 TCP 网络参数做简单说明。
首先,需要修改/etc/sysctl.conf来更改内核参数。例如,最常用的配置:
fs.file-max=999999
这个参数表示进程(比如一个worker 进程)可以同时打开的最大句柄数。这个参数直接限制最大并发连接数,需根据实际情况配置。
net.ipv4.tcp_tw_reuse=1
这个参数设置为1,表示允许将TIME-WAIT 状态的 socket 重新用于新的TCP连接,这对于服务器来说很有意义,因为服务器上总会有大量TIME-WAIT 状态的连接。
net.ipv4.tcp_keepalive_time=600
这个参数表示当keepalive启用时,TCP 发送 keepalive 消息的频度。默认是2小时,若将其设置得小一些,可以更快地清理无效的连接。
net.ipv4.tcp_fin_timeout=30
这个参数表示当服务器主动关闭连接时,socket保持在FIN-WAIT-2状态的最大时间。
net.ipv4.tcp_max_tw_buckets=5000
这个参数表示操作系统允许 TIME_WAIT 套接字数量的最大值。如果超过这个数字,TIME_WAIT 套接字将立刻被清除并打印警告信息。该参数默认为180000,过多的TIME_WAIT套接字会使 Web服务器变慢。
net.ipv4.ip_local_port_range =1024 61000
这个参数定义了在 UDP和TCP 连接中本地(不包括连接的远端)端口的取值范围。
net.ipv4.tcp_rmem=4096 32768 262142
这个参数定义了TCP接收缓存(用于TCP接收滑动窗口)的最小值、默认值、最大值。
net.ipv4.tcp_wem=4096 32768 262142
这个参数定义了TCP发送缓存(用于TCP发送滑动窗口)的最小值、默认值、最大值。
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
该参数与性能无关,用于解决 TCP的 SYN 攻击。
net .ipv4.tcp_max_syn.backlog=1024
这个参数表示 TCP 三次握手建立阶段接收 SYN 请求队列的最大长度,默认为1024,将其设置得大一些可以使出现Nginx繁忙来不及accept新连接的情况时,Linux不至于丢失客户端发起的连接请求。
然后执行 sysctl -p命令,使上述修改生效。