昨天解决了一个 nginx 的问题,原因是本地配置文件中没指定某域名的访问,此时访问此域名会随机选某个配置文件导致了非预期行为。以前总是觉得这个难以理解,当晚看了一下 nginx 的官方文档,似乎是受到了 enlightenment 一看就明白了。其实他们就是工具,把它们想得简单一点后,并没什么难的。
本文的解释只是基础使用,可参考原文档 Beginner's Guide。
简单介绍
nginx 是一种 web server,是内容分发者。就是将过来的请求按配置分发到其他地方。
它有一个主进程和多个工作进程。
主进程负责读和评估配置文件,以及维护工作进程;
工作进程做实际的处理请求工作。
配置文件默认名为 nginx.conf
,位置在 /usr/local/nginx/conf
, /etc/nginx
, 或 /usr/local/etc/nginx
中。(其中的 include 命令可导入多个 server)
运行,停止和重新加载
nginx -s signal
signal 可以为:
- stop: fast shutdown
- quit: graceful shutdown
- reload: reload the configuration file
- reopen: reopen the log files
配置文件的结构
nginx 的模块(modules)是由 指令 (directives)组成的。
指令分为 简单指令 (simple directives)和 块指令(block directives)。
简单指令 以空格分隔参数,以分号结尾。
块指令 是有大括号({}
)括住的,且可以嵌套指令。
当块指令嵌套其他指令时,称之为 上下文(context)。例如: events
,http
,server
,location
。
放在任何上下文之外的指令称之为 主上下文(main context)。
即:
- events
和 http
位于主上下文中
- server
在 http
中
- location
在 server
中
(可以参考下面的例子)
静态文件的访问
nginx 可以直接将 静态文件请求 指定到某个静态目录下。
例如,服务器上设了两个专门用于放静态文件的目录 /data/www
和 /data/images
http {
server {
listen 80; # 因为是默认端口,本句可省略
server_name robin.com; # 监听访问域名
location / { # 匹配请求 uri
root /data/www; # 设为请求根目录
}
location /images/ {
root /data;
}
}
}
解释:
- 上面的配置监听了请求域名
robin.com
的80
端口(默认端口),也即当访问robin.com
的80
端口时,会走这个配置。 - location 后面的
/
和/images/
是 url 匹配,首选最长匹配 进行命中,所以上面的例子中,/
的 location 一定是最后匹配中的 - 当命中
/
的location
时会将/data/www
设为此请求的根位置。 - 当请求 url 为
/images/xxx
时,则会命中/images/
,命中后,将/data
作为根目录进行访问。即访问/data/images/xxx
代理服务器
比如:
- 我本地起了一个服务挂在本地端口
8080
上,所以用127.0.0.1:8080
可访问此服务。 - 但后来我想通过自定义域名来访问。那么可以在文件
/etc/hosts
中加一句127.0.0.1 robin.com
,此时则可以用robin.com:8080
来访问。 - 但我想把端口号也去掉,即通过
robin.com
就访问此服务,这时就需要用到 nginx 的代理功能。 - 代理服务器,即服务器将请求传入代理服务器,从代理服务器中拿到返回,并返回给客户端。
server {
server_name robin.com; # 监听域名
location / {
proxy_pass http://localhost:8080; # 转到 8080 端口
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
上面例子实现了:
- 在客户端访问
robin.com
时,将请求重新定位到本机端口 8080 的服务上来,获得结果返回给客户端。 - 第二个 location 块中,
~
代表通过正则匹配,此块将以.gif
或.jpg
或.png
结尾的 request 转发到/data/images/
的目录下
设置 FastCGI 代理
什么是 FastCGI
首先 CGI 是一种协议,规定了 web server (nginx 就是一种) 传过来的数据格式。FastCGI 是一种更高级的方式,用来提高 CGI 性能的。
比如你想访问一个文件 /icon.png
时,你知道这是个静态文件,可能不会有疑问,但当你要访问的是 /index.php
时呢,如果是静态文件一样的访问,显然不是我们希望的,这时 FastCGI 就用得上了。
当 web server 收到 index.php
的请求后,要启动 CGI 程序,这里就是 PHP 的解析器。接下来,PHP 解析器会解析 php.ini 文件,初始化执行环境,处理请求,再以 CGI 规定的格式返回结果,退出进程。web server 再把结果返回给浏览器。
CGI 针对每个 http 请求都会 fork 一个进程,处理完后,随之退出。进程频繁的启动和退出十分低效。
而 FastCGI 会先 fork 出一个 master,再 fork 出多个 worker,当请求过来时,master 负责分发请求到 worker 上。并且 master 还可以根据配置调节 worker 的多少,在效率和性能间达到平衡。
这里有必要再提一下 php-fpm。它是一个实现了 FastCGI 协议的程序,用来调度 FastCGI 起的进程。
Nginx 的 FastCGI
指令 fastcgi_pass
指定代理的 FastCGI 服务。(与 proxy_pass
并列的一个命令)
指令 fastcgi_param
用来设置传入 FastCGI 的参数。
server {
location / {
fastcgi_pass localhost:9000; # FastCGI 服务于 9000 端口
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
解释:
-
SCRIPT_FILENAME
是一个参数,用于指定脚本名。 -
QUERY_STRING
用于传入 request 参数。
网友评论