《深入理解Nginx:模块开发与架构解析(第2版)》阅读笔记1 ——基础、静态Web服务器与反向代理服务器
1.基础
1.1 安装
1.安装依赖:参考ubuntu下安装nginx时PCRE库、zlib库、OpenSSL库的安装,具体如下:
sudo apt-get install libpcre3 libpcre3-dev
sudo apt-get install zlib1g-dev
sudo apt-get install openssl libssl-dev
2.准备四个目录:
- Nginx源代码存放目录
- Nginx编译阶段产生的中间文件存放目录。默认情况下,configure命令会将该目录命名为objs,并放在Nginx源代码目录下。
- 部署目录:该目录存放实际Nginx服务运行期间所需要的二进制文件、配置文件等。默认情况下,该目录为/usr/local/nginx。
- 日志文件存放目录:日志文件可能很大,所以分配一个大一点的磁盘。
3.修改Linux内核参数的优化,以实现高并发访问的Web服务器。修改/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
上述参数的含义,具体见书中,这里就不抄录了。
书中将net.ipv4.tcp_max_syn_backlog
不小心写成了net.ipv4.tcp_max_syn.backlog
。
执行sudo sysctl -p
让配置生效。
sudo sysctl -a
查询linux的内核参数。
4.下载安装
获取Nginx源码:http://nginx.org/en/download.html ,下载最新的稳定版就行。
下载:
wget http://nginx.org/download/nginx-1.22.1.tar.gz
tar -xvzf nginx-1.22.1.tar.gz
编译和安装:
./configure --prefix=PATH # 检测操作系统内核和已经安装的软件 生成makefile文件等。-prefix=指定安装路径
make # 根据Makefile文件编译Nginx工程,并生成目标文件、最终 的二进制文件
make install #根据configure执行时的参数将Nginx部署到指定的安装目录,包括相关目 录的建立和二进制文件、配置文件的复制
1.2 configure详解
- configure的命令参数:参数分为了四大类型,我们现在知道有这些参数,如果使用nginx的过程中,出现问题再来重新安装相关功能或模块即可。
- configure文件介绍:configure加载配置文件、加载第三方模块、生成编译所需的Makefile等文件。
执行./configure
以后,生成了Makefile和ngx_modules.c等文件,其中ngx_modules.c指明了每个模块在Nginx中的优先级,当一个请求同时符合多个模块的处理规则时,将按照它们在ngx_modules数组中的顺序选择最靠前的模块优先处理。对于HTTP过滤模块而言则是相反的。
1.3 Nginx的命令行控制(nginx命令后跟着的参数)
Nginx的命令行控制,大致介绍了nginx后面可以跟着下面几种参数:指定配置文件、测试和显示配置信息、(优雅)停止服务、日志回滚、升级而不停止服务。有需要了过来去书里查阅就可以。
1.4 nginx配置使用第三方模块、
nginx中有master和worker进程:
- master进程用于管理worker进程,包括诸如启动服务、停止服务、重载配置文件、平滑升级程序等
- worker进程数一般与CPU核心数相等,每个worker进程可以处理多个HTTP请求。
这样做的好处:
- master管理worker,当一个worker出问题以后,可以调用其他worker对请求进行处理。
- 多个worker接收并处理请求,提高了处理请求的效率。
1.5Nginx配置的通用语法与Nginx服务的基本配置
Nginx配置的通用语法:
- 块配置项:
块配置项名 {}
,或块配置项名/xxx {}
。内外层配置发生冲突时,以内层还是外层配置为准,不同的模块由不同的处理方法。 - 配置项:
配置项名 配置项值1 配置项值2 ...;
,以空格作为分隔符,配置项值可以是数字、字符串、正则表达式。
【注】如果配置项值中包括语法符号,比如空格符,那么需要使用单引号或双引号括住配置项值。 - 注释:使用
#
作为注释 - 配置项的单位:空间单位(k,m等),时间单位(ms,s,m,h等)
- 配置文件中的变量:使用
$
作为前缀进行表示。只有少数模块支持解析这种变量。
Nginx服务的基本配置:Nginx运行时至少要配置的配置项,当然有些配置项有默认值可以不需要手动进行配置。
- 用于调试进程和定位问题的配置项
daemon on | off; # off以后使其在终端运行,方便输出调试信息
master_process on| off;
# off关闭了master_process方式,就不会fork出worker子进程来处理请求,而是用master进程自身来处理请求。
error_log /path/file level;
# 设置error日志输出到哪个文件中,已经日志的输出等级
debug_points [stop| abort]
# 如果设置了debug_points 为stop,那么Nginx的代码执行到这些调试点时就会发出SIGSTOP信号以用于调试。
# 如果debug_ points 设置为abort,则会产生一个coredump文件,可以使用gdb来查看Nginx当时的各种信息。
# 通常不会使用这个配置项。
debug_connection [IP | CIDR] # 设置哪些IP的请求才会输出debug级别的请求
worker_rlimit_core size; # 限制coredump核心转储文件的大小。
# 在Linux系统中,当进程发生错误或收到信号而终止时,系统会将进程执行时的内存内容(核心映像)写入
# 一个文件(core文件),以作为调试之用,这就是所谓的核心转储
working_directory path; # 指定coredump文件生成目录
- 正常运行的配置项
env VAR|VAR=VALUE # 定义系统的环境变量
include /path/file # 导入其他配置文件
pid path/file; # 保存master进程ID的pid文件存放路径。
user username [groupname]; # Nginx worker进程运行的用户及用户组
worker_rimit_nofile limit; # 指定Nginx worker进程可以打开的最大句柄描述符个数
worker_rlimit_sigpending limit; # 设置每个用户发往Nginx的信号队列的大小
- 优化性能的配置项
worker_processes number; # 设置Nginx worker进程个数。
# 如果这些模块确认不会出现阻塞式的调用,那么,有多少CPU内核就应该配置多少个进程;反
# 之,如果有可能出现阻塞式调用,那么需要配置稍多一些的worker进程。
worker_cpu_affinity cpumask[cpumask...] # 绑定Nginx worker进程到指定的CPU内核。调用linux系统调用sched_setaffinity()实现
ssl_engine device # 设置SSL硬件加速设备,加快SSL协议处理速度
timer_resolution t; # 设置gettimeofday执行频率。gettimeofday:实现用内核的时钟来更新Nginx中的缓存时钟。
worker_priority nice; # Nginx worker进程优先级设置
- 事件类配置项
accept_mutex [on| off] # 是否打开acept锁。打开以后,TCP连接会均匀分给各个worker进程,从而实现负载均衡
lock_file path/file; # Nginx不支持原子锁的时候,lock_file指定的lock文件才会生效。
accept_ mutex_delay Nms; # 如果有一个worker进程试图取accept锁而没有取到,它至少要等acceptmutexdelav定义的时间间隔后才能再次试图取锁。
multi_accept [ on | off ]; # 当事件模型通知有新连接时,尽可能地对本次调度中客户端发起的所有TCP请求都建立连接。
use [ kqueue | rtsig | epoll | /dev/poll| select| poll | eventport ]; # 选择事件模型。可供选择的事件驱动模型有poll、select、 epoll 三种。epoll效率最高。
worker_ connections number; # 每个worker的最大连接数
2.静态Web服务器与反向代理服务器
2.1 用HTTP核心模块配置一个静态Web服务器
参考:Nginx快速入门
static_web.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
## 新服务(静态网站)
server {
listen 8081;
location / {
root /home/ubuntu/softwares/nginx/myfile/www;
}
location /images/ {
root /home/ubuntu/softwares/nginx/myfile;
}
}
}
/home/ubuntu/softwares/nginx/myfile/www下放入一个index.html,index.html的内容如下:
<h2> New Static WebSite Demo.</h2>
/home/ubuntu/softwares/nginx/myfile/images下放入一个名为logo.png的文件。
运行:
./nginx -c /home/ubuntu/softwares/nginx/conf/static_web.conf
-c
指定static_web.conf的路径。
浏览器输入:
127.0.0.1:8081
既可以访问到index.html
127.0.0.1:8081/images/logo.png
既可以访问到logo.png
2.1.1 HTTP配置项
HTTP配置项分为了八个类,下面进行逐一介绍:
1.虚拟主机与请求的分发:多个主机域名对应着同一个IP地址,每个主机域名对应一个server块,一个server块只处理与之相对应的主机域名请求。下面对书中的部分配置项进行摘录:
-
listen address:port; 决定Nginx服务如何监听端口。下面介绍部分listen后可以跟着的参数。
default/default server:设置本server块为默认server块。当一个请求无法匹配配置文件中的所有主机域名时,就会使用默认server块进行处理。没有这个参数,那么第一个server块为默认server块。
backlog num:表示TCP中backlog队列的大小。在进行三次握手的过程中,如果有新的客户试图通过三次握手建立新的连接,此时新客户的请求会被放入backlog队列。backlog队列满了就不能再接收客户请求了。
defered:设置此参数后,三次握手时,不会调用worker进程。只有用户真的发送请求数据时(内核已经在网卡中收到请求数据包)。内核才会唤醒worker进程处理这个连接。
ssl:在当前监听的端口,上建立的连接必须基于SSL协议。 -
server_name name […]; 在开始处理一个HTTP请求时,Nginx会取出header头中的Host,与每个server中的server_name 进行匹配,以此决定到底由哪一个server块来处理这个请求。
-
server_names_hash_bucket_size:设置散列桶占用内存的大小。散列桶代表每个key对应的链表。
server_names_hash_max_size:应该是指最大可存储多少个key值。 -
server_name_in_redirect on| off; 该配置需要配合server_name使用。在使用on打开时,表示在重定向请求时会使用server_name里配置的第一个主机名代替原先请求中的Host头部,而使用off关闭时,表示在重定向请求时使用请求本身的Host头部。默认为on。
-
location [=|~|~*|^~|@] /uri/ { ... } 用户请求的uri匹配哪个location就用哪个location处理请求。
2.文件路径的定义
alias和root:
alias:直接将uri中的前缀替换为本地路径,alias只能放置到location块,alias后面还可以添加正则表达式。
root:将uri加到本地路径后面,root可以放置到http、server、 location 或if块中。
如下:
location /download/ {
root /opt/web/html/;
}
URI是/download/index/test.html,按照上面的配置,返回的是/opt/web/html/download/index/test.html。
如果将location中的root换成alias时,URI是/download/index/test.html,则返回/opt/web/html/index/test.html。
访问首页:index file1 file2... fileN,从fileN开始依次访问,只要有一个可以访问,那么就不会再访问下一个了。
根据HTTP返回码重定向页面:error_ page,就是说遇到某个返回码就跳转到某个页面
是否允许递归使用error_page:recursive_ error_ pages
try_files path1 [path2] uri; 依次访问每个path,如果没有访问成功,就重定向到uri
3.内存及磁盘资源的分配
- http的body存储在内存还是磁盘,分配多大的内存、存储在磁盘中时,如何命名文件名的。
- http的header应该分配多大的内存,当header很大时应该如何分配内存
- 给TCP连接分配的内存池大小
- 给HTTP连接分配的内存池大小
4.网络连接的设置
- 设置读取body、header的超时时间、发送响应的超时时间
- keepalive等各种超时时间
5.设置MIME type与文件扩展名的映射
浏览器通常使用 MIME 类型(而不是文件扩展名)来确定如何处理URL,因此 We b服务器在响应头中添加正确的 MIME 类型非常重要。如果配置不正确,浏览器可能会无法解析文件内容,网站将无法正常工作,并且下载的文件也会被错误处理。(参考:链接)
6.对客户端请求的限制:限制http方法、body大小、客户端每秒传输的字节数。
7.文件操作的优化:
- 加速对文件的访问:sendfile、aio、directio
- 文件在内存中的缓存:设置缓存的文件数量、多久没被访问就淘汰、检验缓存有效性等。
8.对客户端请求的特殊处理:见书
9.ngx_http_core_ module 模块提供的变量
2.2 配置一个反向代理服务器
可直接参考:配置一个反向代理服务器
反向代理服务器:用于接收互联上的请求,并将请求转发给局域网中的服务器进行处理。
nginx一般用于向客户端提供静态文件服务和作为反向代理服务器,对于复杂、多变的业务不适合放到Nginx服务器上,这时会用Apache、Tomcat等服务器来处理。
与反向代理服务器Squid相比,nginx反向代理服务器有如下特点:
-
nginx反向代理服务器会将完整的请求缓存下来(包括http的body部分),然后在将请求发送到上游服务器。而Squid等代理服务器则采用一边接收客户端请求,一边转发到上游服务器的方式。
-
缺点:延长了一个请求的处理时间,并增加了用于缓存请求内容的内存和磁盘空间。
优点:降低了上游服务器的负载,尽量把压力放在Nginx服务器上。起到如上作用的原因:公网上的请求发送到Nginx服务器速度比较慢,所以连接需要维持的时间比较久。Nginx服务器与内网服务器之间的通信一般会比较快,所以连接需要维持的时间比较短。所以Nginx反向代理服务器降低上游服务器的并发压力,即上游服务器可以很快的接收到Nginx反向代理服务器发送的请求。
2.2.1 负载均衡的基本配置
负载均衡:尽量把请求平均地分布到每一 台上游服务器上
负载均衡的基本配置项:
- upstream块:定义了一个上游服务器的集群,便于反向代理中的proxy pass使用。upstream块中使用server指定一个上游服务器的名称。
- ip_hash; 使得同一个用户的请求始终落在一个上游服务器上。
- 记录日志时支持的变量
2.2.2 反向代理的基本配置
- proxy_ pass:为当前的请求指定上游服务器
- 隐藏头部字段、确定是否向上游服务器转发body和header
- proxy_redirect:重定向到别的服务器
- proxy_next_upstream:发生超时、错误等情况时,重新找一个上游服务器处理请求
3.开发一个简单的HTTP模块
HTTP模块:
- worker进程检测到请求以后,会根据nginx.conf的配置将请求交给HTTP框架处理,HTTP框架解析头部后,根据URI和nginx.conf里的location配置项,将请求分发给HTTP模块进行处理。
- HTTP模块会将响应发送给HTTP过滤模块进行处理,比如压缩响应。
- 处理完毕以后,如果设置了subrequest,,那么HTTP框架还会继续异步地调用适合的HTTP模块处理子请求。
ngx_http_access_module模块用于过滤非法IP。
编写config文件指定模块名和模块代码路径,就可以使用configure --add-module=PATH
将模块编译进nginx源码中。