chaoz的杂货铺

生命有息、学无止境、折腾不止

0%

Nginx-进阶笔记

目录结构

源码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@localhost nginx-1.2.0]# ls -F
auto/ CHANGES CHANGES.ru conf/ configure* contrib/ html/ LICENSE man/ README src/
<!-- more -->
auto/:包含了很多会在执行configure进行编译配置时调用的检测代码。
CHANGES:Nginx的版本更新细节记录。英文版。
CHANGES.ru:Nginx的版本更新细节记录。俄文版。
conf/:Nginx提供的一些默认配置文件。
configure*:根据系统环境设定Nginx编译选项的执行脚本。
contrib/:网友贡献的一些有用脚本。
ps: cp -r contrib/vim/* ~/.vim/ 可以使vim支持nginx配置语言的语法。
html/:提供了两个默认html页面,比如index.html的Welcome to nginx!。
LICENSE:声明的Nginx源码许可协议。
man/:Nginx的Man手册,本文文件,可直接用vi或记事本打开。
README:读我文件,内容很简单,通告一下官网地址。
src/:Nginx源码,分门别类,比如实现事件的event等,很清晰。
执行configure脚本后将生成Makefile文件和objs目录,这是根据当前系统环境生成的相关编译配置。Nginx并没有使用Autoconf1和Automake2等这样的自动化工具来做这个工作,而都是手动编码实现的。比如当Nginx判断当前Linux系统是否支持epoll时,它采用的方法就是编写一款小应用程序,并在其中调用epoll_create()函数,然后再根据它是否可被正常编译执行来做这个判断。具体可参考文件nginx-1.2.0/auto/os/linux和nginx-1.2.0/auto/feature内相关代码。


编译参数问题:

./configure --help | more 查看有哪些参数
参数类型:
第一类:目录
第二类:使用哪些模块(with 默认编译不带该模块)、不使用哪些模块(without 默认编译带该模块)
第三类:优化参数、debug日志、第三方模块

中间文件 :objs 目录
ngx_modules.c : 被编译进的模块会在一个文件中,并且存为一个数组。

应用结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@www ~]# tree /application/nginx/
/application/nginx/
|-- client_body_temp
|-- conf               #这是Nginx所有配置文件的目录,极其重要
| |-- fastcgi.conf            #fastcgi相关参数的配置文件
| |-- fastcgi.conf.default            #fastcgi.conf的原始备份
| |-- fastcgi_params           #fastcgi的参数文件
| |-- fastcgi_params.default
| |-- koi-utf
| |-- koi-win
| |-- mime.types              #媒体类型,
| |-- mime.types.default
| |-- nginx.conf              #这是Nginx默认的主配置文件
| |-- nginx.conf.default
| |-- scgi_params             #scgi相关参数文件,一般用不到
| |-- scgi_params.default
| |-- uwsgi_params        #uwsgi相关参数文件,一般用不到
| |-- uwsgi_params.default
| `-- win-utf
|-- fastcgi_temp          #fastcgi临时数据目录
|-- html                    #这是编译安装时Nginx的默认站点目录,类似
Apache的默认站点htdocs目录
| |--50x.html #错误页面优雅替代显示文件,例如:出现502错误时会调用此页面
#error_page 500502503504 /50x.html;
| `-- index.html #默认的首页文件,首页文件名字是在nginx.conf中事先定义好的。
|-- logs #这是Nginx默认的日志路径,包括错误日志及访问日志
| |-- access.log #这是Nginx的默认访问日志文件,使用tail -f access.log,可以实时观看网站用户访问情况信息
| |-- error.log #这是Nginx的错误日志文件,如果Nginx出现启动故障等问题,一定要看看这个错误日志
| `-- nginx.pid #Nginx的pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
|-- proxy_temp #临时目录
|-- sbin #这是Nginx命令的目录,如Nginx的启动命令nginx
| `-- nginx #Nginx的启动命令nginx
|-- scgi_temp #临时目录
`-- uwsgi_temp #临时目录
9 directories,21 files

命令行

nginx -s reload
帮助:-? -h
使用指定的配置文件:-c
指定配置指令:-g
指定运行目录: -p
发送信号:-s

  • 立即停止:stop
  • 优雅的停止:quit
  • 重载配置:reload
  • 重新开始记录日志文件: reopen

测试配置文件是否有语法错误:-t -T
打印nginx的版本信息、编译信息等:-v -V

nginx 的新版本热部署

先 cp nginx 新版本的二进制文件 :cp nginx nginx.old
USR2 信号:kill -USR2 $pid : 新老nginx进程都在运行
WINCH 信号:kill -WINCH $pid :老版本的work进程已经关闭,但是master进程还在运行,这样方便快速回退。

nginx 日志切割

首先将日志cp一份;
然后 nginx -s reopen 重新生成一份新的日志。当然 向 pid 发送 USR1 信号是一样的

写一个脚本放在 crontab 中,方便定时运行。

nginx 配置文件说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
user nginx nginx;                #定义Nginx运行的用户和用户组
worker_processes 1;         #nginx进程数,建议设置为等于CPU总核心数。
error_log /var/log/nginx/error.log info;   #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
pid /var/run/nginx.pid;             #进程文件
worker_rlimit_nofile 1024;    #一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以#建议与ulimit -n的值保持一致

events
{
use epoll;    #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,
                如果跑在FreeBS  #D上面,就用kqueue模型。

worker_connections 65535;     #单个进程最大连接数(最大连接数=连接数*进程数)
}



http                  #HTTP区块开始
{
include mime.types;                   #Nginx支持的媒体类型库文件
default_type application/octet-stream;       #默认媒体类型
#charset utf-8;                     #默认编码
server_names_hash_bucket_size 128;         #服务器名字的hash表大小
client_header_buffer_size 32k;            #上传文件大小限制
large_client_header_buffers 4 64k;          #设定请求缓
client_max_body_size 8m;                #设定请求缓
sendfile on;       #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为o  #ff,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
autoindex on;                #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on;               #防止网络阻塞
tcp_nodelay on;              #防止网络阻塞
keepalive_timeout 120;          #连接超时,单位是秒

#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;


#gzip模块设置
gzip on;                    #开启gzip压缩输出
gzip_min_length 1k;              #最小压缩文件大小,小于就不压缩了
gzip_buffers 4 16k;            #压缩缓冲区
gzip_http_version 1.0;            #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2;              #压缩等级
gzip_types text/x-javascript text/css application/xml;     #压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#limit_zone crawler $binary_remote_addr 10m;   #开启限制IP连接数的时候需要使用



#虚拟主机的配置
server
{

listen 80;                      #监听端口

server_name localhost;               #提供服务的域名主机名
location / {                    #第一个location区块开始
root html;                      #站点的根目录,相当于Nginx的安装目录
index index.html index.htm index.jsp;     #默认的首页文件,多个用空格分开
}                          #第一个location区块结果



#图片缓存时间设置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 10d;
}


#JS和CSS缓存时间设置
location ~ .*\.(js|css)?$
{
expires 1h;
}


#日志格式设定
log_format access '$remote_addr - $remote_user [$time_local] "$request" 'log_ #access这种格式可以自定义作为标识。
'$status $body_bytes_sent "$http_referer" ' # remote_addr 代表远端地址,time_local 当时时间,status 状态码,内置变量以及第三方模块提供的变量
'"$http_user_agent" $http_x_forwarded_for';

access_log /var/log/nginx/access_$(data+%F -d -1day).log access;    #定义本虚拟主机的访问日志,采用access的这种格式



location / {                        #对 "/" 启用反向代理
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;        #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP,做限制什么的不然就限制代理服务地址了。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

#以下是一些反向代理的配置,可选
proxy_set_header Host $host; #
client_max_body_size 10m;              #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k;          #缓冲区代理缓冲用户端请求的最大字节数,
proxy_connect_timeout 90;            #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90;              #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90;            #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k;              #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k;              #proxy_buffers缓冲区,网页平均在32k以下的设置
proxy_busy_buffers_size 64k;          #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k;          #设定缓存文件夹大小,大于这个值,将从upstream服务器传

}

#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;       #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。

}

#本地动静分离反向代理配置
#所有jsp的页面均交由tomcat或resin处理
location ~ .(jsp|jspx|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
}


#所有静态文件由nginx直接读取不经过tomcat或resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{ expires 15d; }
location ~ .*.(js|css)?$
{ expires 1h; }
}
}

nginx 配置静态资源服务器

1
2
3
4
5

location /{
autoindex on; #访问的url以 / 结尾时,显示当前文件夹下的文件结构
set $limit_rate 1k #限制访问的使用度,每秒传输1k
}

配置反向代理

listen 127.0.0.1:8080 仅支持本地访问,通过反向代理来访问该资源。

upstream local {
server 127.0.0.1:8080
}

配置缓存服务器

upstream local {
server 127.0.0.1:8080
}
mark
ps: key 目的时对应不同的用户有着不同的资源。
proxy_cache_path /tmp/nginx cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

用GoAccess实现可视化并实时监控access日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1、GoAccess下载地址:https://goaccess.io/download

2、yum方式安装GoAccess所需软件包:
# yum install GeoIP-devel ncurses ncurses-devel wget epel-release

3、编译安装GoAccess:
# wget https://tar.goaccess.io/goaccess-1.3.tar.gz
# tar -xf goaccess-1.3.tar.gz -C /usr/src
# cd /usr/src/goaccess-1.3
# ./configure --prefix=/usr/local/goaccess --enable-utf8 --enable-geoip
# make && make install

4、配置环境变量:
# vim /etc/profile.d/goaccess.sh
export PATH=/usr/local/goaccess/bin:$PATH
# . /etc/profile.d/goaccess.sh
# goaccess -V

5、修改nginx.conf配置文件:
# vim /etc/nginx/nginx.conf,确认如下配置默认已启用:
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 /var/log/nginx/access.log main;

6、修改goaccess.conf配置文件:
# cd /usr/local/goaccess/etc/goaccess/
# cp goaccess.conf{,.bak}
# vim goaccess.conf

mark

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 7、控制台运行GoAccess:
# goaccess /var/log/nginx/access.log

8、后台实时生成数据到GoAccess界面,并将分析结果保存为HTML:
# goaccess -p /usr/local/goaccess/etc/goaccess/goaccess.conf

或# goaccess /var/log/nginx/access.log --time-format='%H:%M:%S' --date-format='%d/%b/%Y' --log-format=COMBINED -o /usr/share/nginx/html/goaccess.html --addr=192.168.0.121 --real-time-html --daemonize
# ps -ef | grep goaccess
# ss -tunlp | grep 7890
备注:如果需要输出实时HTML,需要打开防火墙7890端口

9、浏览器访问http://ip/goaccess.html

10、使用ab命令进行压测,模拟访问,观察页面数值是否实时变化:
# yum -y install httpd-tools
# ab -n 500000 -c 20 http://ip/

官方帮助文档
参考博客

SSL相关

mark
mark

对称加密算法和非对称加密区别:

mark
mark

mark

证书链:
根证书-二级证书-主证书
mark

上证书:

1
2
3
4
5
yum install python2-certbot-nginx
certhot --nginx --nginx-server-root=/usr/local/openresty/nginx/conf/ -d 域名

ps:根据提示,输入相关资料后,即可在/etc/letsencrypt/archive目录下得到证书文件。
或者:也可以直接使用以下命令直接生成。注意xxx需要替换为自己的东西。

certbot 自动化脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot可以获取并安装HTTPS/TLS/SSL证书。默认情况下
它将尝试使用Web服务器来获取和安装
证书。最常见的子命令和标志是:

obtain, install, and renew certificates:
(default) run 在当前Web服务器中获取并安装证书
certonly 获取或续订证书,但不要安装它
renew 更新所有以前获得的证书
expiry
enhance 为现有配置添加安全增强
-d DOMAINS 要获取证书的域的逗号分隔列表

(未安装certbot apache插件)
--standalone 运行独立的Web服务器进行身份验证
--nginx 使用Nginx插件进行身份验证和安装
--webroot 将文件放在服务器的webroot文件夹中进行身份验证
--manual 以交互方式获取证书,或使用shell脚本
hooks

-n 非交互运行
--test-cert 从登台服务器获取测试证书
--dry-run 在不保存任何证书的情况下测试“renew”或“certonly”
to disk

manage certificates:管理证书
certificates 显示有关您从Certbot获得的证书的信息
revoke Revoke a certificate (supply --cert-path or --cert-name)吊销证书(提供--证书路径或--证书名称)
delete Delete a certificate

manage your account:
register Create an ACME account 创建ACME帐户
unregister Deactivate an ACME account
update_account Update an ACME account
--agree-tos Agree to the ACME server's Subscriber Agreement 同意ACME服务器的订户协议
-m EMAIL Email address for important account notifications 重要帐户通知的电子邮件地址

More detailed help:

-h, --help [TOPIC] print this message, or detailed help on a topic;打印此消息或有关某个主题的详细帮助
the available TOPICS are: 可用的主题有

all, automation, commands, paths, security, testing, or any of the
subcommands or plugins (certonly, renew, install, register, nginx,
apache, standalone, webroot, etc.)
-h all print a detailed help page including all topics
--version print the version number
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

mark
mark
ssl_session_catch ; #1M 大约4000个连接
ssl_session_timeout 1440m; #断开链接后大概多久内免再次握手
ssl_protocols : #nginx 支持哪些版本的安全协议
ssl_prefer_server_ciphers #决定使用哪些协议
ssl_ciphers: #有哪些协议

nginx请求处理流程

mark

nginx 进程结构/管理

mark

就是向 master 主进程发送信号

mark

reload流程

1、向 master 进程发送HUP信号(reload)
2、master进程校验配置语法是否正确
3、master进程打开新的监听端口
4、master进程用新配置启动新的worker子进程
5、master进程向老worker子进程发送QUIT信号 (极端情况老进程处理时间太长,会有个模块让它强制退出)
6、老worker进程关闭监听句柄,处理完当前连接后结束进程

热升级流程

1、将旧的nginx文件换为新的nginx文件(注意备份)
2、向master进程发送USR2信号
3、master进程修改pid文件名,加后缀.oldbin
4、master进程用新的nginx文件启动新的master进程
5、向老master进程发送QUIT信号,关闭老master进程
6、回滚:向老master发送HUP,向新master发送QUIT

老 master 进程到底退出没?

优雅的关闭work进程

1、设置定时器(worker_shutdown_timeout)
2、关闭监听句柄(保证不会处理新的连接)
3、关闭空闲连接(为了保证资源的利用最大化,会保留空闲连接)
4、在循环中等待全部连接关闭(每当发现有连接处理完毕则关闭一个,但是当达到一个定时器时间会立即关闭所有)
5、退出进程

网络收发与nginx的链路关系

mark
mark

nginx 事件循环

epoll

nginx 请求切换

同步&异步、阻塞&非阻塞之间的区别

阻塞调用

mark

非阻塞调用

mark

底层调用?

非阻塞调用之下的同步与异步

mark

nginx 模块

提供哪些配置项
模块何时被使用
提供哪些变量

查看 nginx 临时文件目录中的 nginx_***_module.c 文件
.c module 的源代码中都有一个 ngc_command_t 唯一的结构体,是个数组,包含所有的指令名。

mark

mark

流量复制

Nginx流量复制

喜欢这篇文章?打赏一下作者吧!

欢迎关注我的其它发布渠道