第1章 Nginx技术深入剖析
1.1 Nginx软件功能模块说明
1.1.1 Nginx核心功能模块
Nginx核心功能模块负责Nginx的全局应用,主要对应主配置文件的Main区块和Events区块区域,这里有很多Nginx必须的全局参数配置。
1.1.2 标准的http功能模块
Nginx http功能模块 | 模块说明 |
ngx_http_core_module | 包括一些核心http参数配置,对应Nginx的配置为HTTP区块部分 |
ngx_http_access_module | 访问控制模块,用来控制网站用户对Nginx的访问 |
ngx_http_gzip_module | 压缩模块,对Nginx返回的数据压缩,属于性能优化模块 |
ngx_http_fastcgi_module | FastCGI模块,和动态应用相关的模块,例如PHP |
ngx_http_proxy_module | proxy代理模块 |
ngx_http_upstream_module | 负载均衡模块,以实现网站的负载均衡功能及节点的健康检查 |
ngx_http_rewrite_module | URL地址重写模块 |
ngx_http_limit_conn_module | 限制用户并发连接数及请求数模块 |
ngx_http_limit_req_module | 根据定义的key限制Nginx请求过程的速率 |
ngx_http_log_module | 访问日志模块,以指定的格式记录Nginx客户访问日志等信息 |
ngx_http_auth_basic_module | Web认证模块,设置Web用户通过账号、密码访问Nginx |
ngx_http_ssl_module | SSL模块,用于加密的HTTP连接,如https |
ngx_http_stub_status_module | 记录Nginx基本访问状态信息等的模块 |
1.2 Nginx目录结构说明
[root@web01 nginx]# tree /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 #错误页面优雅替代显示文件 │ └── index.html #默认的首页文件,首页文件名字在nginx.conf中事先定义好的 ├── logs #这是Nginx默认的日志路径,包括错误日志及访问日志 │ ├── access.log #默认访问日志文件 │ ├── error.log #错误日志文件 │ └── nginx.pid #Nginx的Pid文件,进程启动后,会将所有进程的ID号写入这里 ├── proxy_temp #临时目录 ├── sbin #Nginx命令的默认目录,只有nginx一条命令 │ └── nginx ├── scgi_temp #临时目录 └── uwsgi_temp #临时目录 9 directories, 21 files
提示:所有结尾为default的文件都是备份文件。
1.3 Nginx主配置文件nginx.conf
它位于Nginx安装目录下的conf目录中,整个配置文件以区块的形式组织的。
1.3.1 nginx.conf配置文件详解
1.3.2 Nginx其他配置文件
如果是配合动态服务(例如PHP服务),Nginx软件还会用到扩展的FastCGI相关配置文件,这个配置是通过在nginx.conf主配置文件中嵌入include命令来实现的,不过默认情况是注释状态,不会生效。
[root@web01 conf]# cat fastcgi.conf fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
第2章 Nginx location
2.1 location作用
location指令的作用是根据用户请求的URI来执行不同的应用。其实就是根据用户请求的网站地址URL进行匹配,匹配成功即进行相关操作。
2.2 location语法
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } Default: — Context: server, location
2.2.1 语法说明
location | [=|~|~*|^~|@] | uri | {...} |
指令 | 匹配标识 | 匹配的网站网址 | 匹配URI后要执行的配置段 |
- 其中URI可以是普通的字符串地址路径或者是正则表达式,匹配成功则执行后面大括号里的相关指令。
- “~”用于区分大小写(大小写敏感)的匹配,“!~”表示取反
- “~*”用于不区分大小写的匹配,“!~*”表示取反
- “^~”在进行常规的字符串匹配检查之后不做正则表达式的检查
2.3 location匹配示例
location = / { #用户请求/时,配置configuration A [ configuration A ] } location / { #用户请求/index.html时,配置configuration B [ configuration B ] } location /documents/ { #用户请求/documents/document.html时,配置configuration C [ configuration C ] } location ^~ /images/ { #用户请求/images/1.gif时,配置configuration D [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { #用户请求/documents/1.jpg时,配置configuration E [ configuration E ] }
- 不同URI对应的配置情况:
用户请求的URI | 完整的URL地址 | 匹配的配置 |
/ | http://blog.leon.com/ | configuration A |
/index.html | http://blog.leon.com /index.html | configuration B |
/documents/document.html | http://blog.leon.com /documents/document.html | configuration C |
/images/1.gif | http://blog.leon.com /images/1.gif | configuration D |
/documents/1.jpg | http://blog.leon.com /documents/1.jpg | configuration E |
2.4 location配置实战
2.4.1 编辑www.conf配置文件
[root@web01 extra]# vim www.conf server { listen 80; server_name www.leon.com www.leon.shadow.com; root html/www; location / { return 401; } location = / { return 402; } location /documents/ { return 403; } #匹配任何以/images/开头的查询并且停止搜索。任何正则表达式匹配将不会被检查。 #“^~”的作用是在常规的字符串匹配检查之后不做正则表达式的检查,即如果最明确的那个字符串匹配的location配置中由此前缀,那么不做正则表达式的检查。 location ^~ /images/ { return 404; } #匹配任何以gif、jpg或jpeg结尾的请求 location ~* \.(gif|jpg|jpeg)$ { return 500; } access_log logs/access_www.log main; }
2.4.2 检查并重启配置
[root@web01 extra]# nginx -t nginx: the configuration file /application/nginx-1.10.3/conf/nginx.conf syntax is ok nginx: configuration file /application/nginx-1.10.3/conf/nginx.conf test is successful [root@web01 extra]# nginx -s reload
2.4.3 测试结果
[root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com 402 [root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com/ 402 [root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com/index.html 401 [root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com/documents/document.html 403 [root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com/images/1.gif 404 [root@web01 extra]# curl -s -o /dev/null -I -w "%{http_code}\n" www.leonshadow.com/documents/1.jpg 500
2.5 用户请求的URI说明
用户请求的URI | 设置的状态码 | 说明 |
当为空或/时 | 返回402,匹配了
location = / { return 402; } 与configuration A一致 |
=的精确匹配优先级最高,无论放置的顺序如何,它都将优先被匹配并执行。 |
/index.html或任意不匹配其他location的字符串 | 返回401,匹配了
location / { return 401; } 与configuration B一致 |
/为默认匹配,即如果没有匹配上其他的location则最后匹配“默认匹配”部分 |
/documents/document.html | 返回403,匹配了
location /documents/ { return 403; } 与configuration C一致 |
此部分为路径匹配,即匹配了路径/documents/,注意后面的/documents/1.jpg表示没有匹配此处的location,而是匹配了结尾的1.jpg |
/images/1.gif | 返回404,匹配了
location ^~ /images/ { return 404; } 与configuration D一致 |
此部分为路径匹配,但是前面增加了特殊字符^~,所以优先匹配路径,而没有匹配结尾的1.gif |
/documents/1.jpg | 返回500,匹配了
location ~* \.(gif|jpg|jpeg)$ { return 500; } 与configuration E一致 |
此部分匹配了1.jpg,属于扩展名匹配,虽然有/documents/,但还是匹配了扩展名 |
2.5.1 URI匹配顺序说明
顺序 | 不同的URI及特殊字符组合匹配 | 匹配说明 |
1 | location = / { | 精确匹配/ |
2 | location ^~ /images/ { | 匹配常规字符串,不做正则匹配检查 |
3 | location ~* \.(gif|jpg|jpeg)$ { | 匹配正则 |
4 | location /documents/ { | 匹配常规字符串,如果有正则则优先匹配正则 |
5 | location / { | 所有location都不能匹配后的默认匹配 |
第3章 Nginx rewrite
3.1 什么是Nginx rewrite
Nginx rewrite的主要功能也是实现URL地址重写。Nginx的rewrite规则需要PCRE软件的支持,即通过Perl兼容正则表达式语法进行规则匹配。默认参数编译时Nginx就会安装支持rewrite的模块,但是也要有PCRE(pcre、pcre-devel)软件的支持。
3.2 Nginx rewrite语法
指令语法:rewrite <em>regex</em> replacement [<em>flag</em>]; 默认值:none 应用位置:server、location、if
rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容重定向到replacement部分内容,结尾是flag标记。
- URL rewrite跳转示例
rewrite ^/(.*) http://blog.leonshadow.com/$1 permanent;
- 命令说明:
- rewrite:固定关键字,表示开启一条rewrite匹配规则
- ^/(.*):regex部分,表示匹配所有
- http://blog.leon.com/$1:表示匹配成功后跳转的位置,$1是取regex部分括号里的内容
- permanent:是永久301重定向标记
3.3 正则表达式说明
字符 | 描述 |
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个后向引用。
例如:“\n”匹配一个换行符,序列“\\”和“\$”则匹配“$” |
^ | 匹配输入字符串的起始位置,如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置 |
$ | 匹配输入字符串的结束位置,如果设置了RegExp对象的Mulitiline属性,$也匹配“\n”或“\r”之前的位置 |
* | 匹配前面的字符零次或多次。例如:ol*能匹配“o”及“olll”,*等价于{0,} |
+ | 匹配前面的字符一次或多次。例如:ol+能匹配“ol”及“oll”,但不能匹配“o”,.+等价于{1,} |
匹配前面的字符一次或多次。例如:“do(es)+”可以匹配“do”或“does”中的“do”,. 等价于{0,1}
当该字符紧跟在任何一个其他限制符(*,+ ,{n},{n},{n,m})的后面时,匹配模式是费贪婪模式的,非贪婪模式会尽可能少地匹配搜索的字符串,而默认的贪婪模式会尽可能多地匹配所搜索的字符串。例如:对于字符串“oooo”,“o+ ”将匹配单个“o”,而“o+”将匹配所有“o” |
|
. | 匹配除“\n”之外的任何单个字符,要匹配包括“\n”在内的任何字符,可以使用像“[.\n]”这样的模式 |
(pattern) | 匹配括号内的pattern,并可以在后面获取对应的匹配,常用$0...$9属性获取小括号中的匹配内容。要匹配圆括号字符,可以使用“\(”或“\)” |
3.4 rewrite指令flag标记说明
flag标记符号 | 说明 |
last | 本条规则匹配完成后,继续向下匹配新的location URI规则 |
break | 本条规则匹配完成即终止,不再匹配后面的任何规则 |
redirect | 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址 |
permanent | 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址 |
last和break用来实现URL重写,浏览器地址栏的URL地址不变,但在服务端访问的路径发生了变化;redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址。
- last和break标记的区别:
- 使用alias指令时必须使用last标记,使用proxy_pass指令时要使用break标记
- last标记在本条rewrite规则执行完毕后,会对其所在的server{......}标签重新发起请求,而break标记则会在本条规则匹配完成后终止匹配,不再匹配后面的规则
3.5 Nginx rewrite的企业应用场景
- 可以调整用户浏览的URL,使其看起来更规范,合乎开发及产品人员的需求
- 为了让搜索引擎收录网站内容,并让用户体验更好,企业会将动态URL地址伪装成静态地址提供服务
- 网站换新域名后,让旧域名的访问跳转到新的域名上。例如:京东360buy。com跳转到com上
- 根据特殊变量、目录、客户端的信息进行URL跳转等
3.6 Nginx rewrite跳转实例
3.6.1 Nginx rewrite 301 跳转
- 方法一:使用新的server区块解决死循环问题
[root@web01 extra]# vim www.conf server { listen 80; server_name www.leon.shadow.com; rewrite ^/(.*) http://www.leonshadow.com/$1 permanent; } server { listen 80; server_name www.leonshadow.com; location / { root html/www; index index.html index.htm; autoindex on; } access_log logs/access_www.log main; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 方法二:使用If判断语句解决死循环问题
server { listen 80; server_name www.leon.com; if ($host ~* "^www.leon.shadow.com$") { #此处如果不使用if判断,会产生死循环错误 rewrite ^/(.*) http://www.leonshadow.com/$1 permanent; } location / { root html/www; index index.html index.htm; autoindex on; } access_log logs/access_www.log main; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 测试结果:
[root@web01 extra]# curl www.leon.shadow.com <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.10.3</center> </body> </html> [root@web02 ~]# curl -Lv www.leon.shadow.com #追踪结果,没有产生死循环 * About to connect() to www.leon.shadow.com port 80 (#0) * Trying 10.0.0.8... connected * Connected to www.leon.shadow.com (10.0.0.8) port 80 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: www.leon.shadow.com > Accept: */* > < HTTP/1.1 301 Moved Permanently < Server: nginx/1.10.3 < Date: Wed, 13 Sep 2017 07:28:23 GMT < Content-Type: text/html < Content-Length: 185 < Connection: keep-alive < Location: http://www.leon.com/ < * Ignoring the response-body * Connection #0 to host www.leon.shadow.com left intact * Issue another request to this URL: 'http://www.leon.com/' * About to connect() to www.leon.com port 80 (#1) * Trying 10.0.0.8... connected * Connected to www.leon.com (10.0.0.8) port 80 (#1) > GET / HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: www.leon.com > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.3 < Date: Wed, 13 Sep 2017 07:28:23 GMT < Content-Type: text/html < Content-Length: 10 < Last-Modified: Tue, 12 Sep 2017 11:23:10 GMT < Connection: keep-alive < ETag: "59b7c39e-a" < Accept-Ranges: bytes < www web01 * Connection #1 to host www.leon.com left intact * Closing connection #0 * Closing connection #1
3.6.2 实现不同域名的URL跳转
实现访问http://blog.leonshadow.com时跳转到http://www.leonshadow.com/blog/leon.html。
- 配置blog站点
[root@web01 extra]# vim blog.conf server { listen 80; server_name blog.leon.com; location / { root html/blog; index index.html index.htm; } if ( $http_host ~* "^(.*)\.leon\.com" ) { set $domain $1; rewrite ^(.*) http://www.leon.com/$domain/leon.html break; } access_log logs/access_blog.log main; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
- 配置leon.com/blog/leon.html地址对应的站点
[root@web01 extra]# cd ../../html/www/ [root@web01 www]# mkdir blog #创建要跳转到的blog目录 [root@web01 www]# cd blog [root@web01 blog]# vim leon.html #创建要访问的leon.html文件 <html> <title>Leon's Blog</title> <body> <h1 align="center">Leon's Logo</h1> <p style="text-align: center;"><img src=logo.png alt="Leon's logo" /></p> </body> </html>
- 实验结果
[root@web01 blog]# curl blog.leon.com <html> <head><title>302 Found</title></head> <body bgcolor="white"> <center><h1>302 Found</h1></center> <hr><center>nginx/1.10.3</center> </body> </html>
3.7 rewrite特殊标记last与break的说明
- 在根location(即location/{……})中或server{……}标签中编写rewrite规则,建议使用last标记;
- 普通的location(例location/leon/{……}或if{})中编写rewrite规则,则建议使用break标记。
第4章 Nginx访问认证
4.1 什么是Nginx访问认证
在实际工作中企业会要求我们为网站设置访问账号和密码权限,这样操作后只有拥有站好密码的用户才可以访问网站内容。
4.2 Nginx访问认证的应用
这种使用账号密码才能访问网站的功能主要应用在企业内部人员访问的地址上。例如:企业网站后台、MySQL客户端phpmyadmin、企业内部CRM、WIKI网站平台等。
4.3 Nginx访问认证的语法及参数
- auth_basic:
Syntax: auth_basic string | off; Default: auth_basic off; Context: http, server, location, limit_except
- auth_basic_user_file:
Syntax: auth_basic_user_file file; Default: — Context: http, server, location, limit_except
file文件格式:
# comment name1:password1 name2:password2:comment name3:password3
可以使用Apache自带的“htpasswd”或“openssl passwd”命令设置用户和密码到认证文件里,密码是加密的。
参考资料: http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html。
4.4 Nginx访问认证配置
4.4.1 配置www虚拟主机
[root@web01 extra]# vim www.conf server { listen 80; server_name www.leonshadow.com; location / { root html/www; index index.html index.htm; auth_basic "leon test"; #设置认证提示字符串“leon test” auth_basic_user_file /application/nginx/conf/htpasswd; #用于设置认证的密码文件 } }
4.4.2 生成认证账号密码
[root@web01 extra]# yum install -y httpd [root@web01 extra]# htpasswd -bc /application/nginx/conf/htpasswd leon 123456 Adding password for user leon [root@web01 extra]# chmod 400 /application/nginx/conf/htpasswd [root@web01 extra]# chown www /application/nginx/conf/htpasswd [root@web01 extra]# cat /application/nginx/conf/htpasswd leon:nfNYxfnwPJ32A
4.4.3 检查并重新加载配置
[root@web01 extra]# nginx -t nginx: the configuration file /application/nginx-1.10.3/conf/nginx.conf syntax is ok nginx: configuration file /application/nginx-1.10.3/conf/nginx.conf test is successful [root@web01 extra]# nginx -s reload
4.4.4 测试结果
- Windows客户端:
- Linux客户端:
[root@web01 extra]# curl www.leon.com <html> <head><title>401 Authorization Required</title></head> #提示需要认证才能访问 <body bgcolor="white"> <center><h1>401 Authorization Required</h1></center> <hr><center>nginx/1.10.3</center> </body> </html> [root@web01 extra]# curl -uleon <a href="http://www.leon.com">www.leon.com</a> #以leon用户身份访问网站 Enter host password for user 'leon': www web01 [root@web01 extra]# curl -uleon:123456 <a href="http://www.leon.com">www.leon.com</a> #以leon用户带密码直接访问网站 www web01
第5章 Nginx相关问题解答
5.1 Tengine和Nginx是什么关系
Tengine是淘宝开源Nginx的分支,官方站点为http://tengine.taobao.org/。
5.2 访问Nginx时出现“403 forbidden”的原因
5.2.1 出现403错误的情况:
- Nginx配置文件里没有配置默认首页参数
- 站点目录下没有配置文件指定的首页文件
- 站点目录或内部的程序文件没有Nginx用户的访问权限
- Nginx配置文件中设置了allow、deny等权限控制,导致客户端没有访问权限
5.2.2 nginx出403错误解决方式
参考资料:http://oldboy.blog.51cto.com/2561410/1633952。
[root@web01 conf]# cat nginx.conf worker_processes 3; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; autoindex on; #当找不到首页文件时,会展示目录结构,这个功能一般不要用除非有需求。 include extra/www.conf; include extra/blog.conf; include extra/bbs.conf; }

说明:显示的目录结构中,有些信息点击就是下载,有的点击就是显示,因为扩展名称不一样,根本在于nginx软件是否能够进行解析(根据媒体资源类型决定的)。
