本文简单介绍 nginx conf 文件的结构,已经如何进行配置:
Nginx 进程模型:1 个主进程,n 个工作进程,主进程负责配置和工作进程的管理,实际的请求由工作进程进行处理。Nginx 是基于事件驱动和多路复用的工作模型。
nginx 的启动可以直接执行 nginx 的 bin 文件, 当 nginx 启动后,可以通过 - s 参数来控制 nginx
- nginx - s reload#重新加载配置文件nginx - s reopen#重新打开log文件nginx - s stop#快速关闭nginx服务nginx - s quit#优雅的关闭nginx服务,等待工作进程处理完所有的请求
Nginx 重新加载配置文件的过程:主进程接受到加载信号后:
在第二步,旧的工作进程收到终止信号后,会停止接收新的连接请求,知道所有现有的请求处理完,然后退出。
nginx 的配置由特定的标识符 (指令符) 分为多个不同的模块。
指令符分为简单指令和块指令。
conf 文件中,所有不属于块指令的简单指令都属于 main 上下文的,http 块指令属于 main 上下文,server 块指令 http 上下文。
web server 很重要一部分工作就是提供静态页面的访问,例如 images, html page。nginx 可以通过不同的配置,根据 request 请求,从本地的目录提供不同的文件返回给客户端。
打开安装目录下的 nginx.conf 文件,默认配置文件已经在 http 指令块中创建了一个空的 server 块,在 nginx-1.8.0 中的 http 块中已经创建了一个默认的 server 块。内容如下:
- server {
- listen 80;
- server_name localhost;
- location / {
- root html;
- index index.html index.htm;
- }
- error_page 500 502 503 504 / 50x.html;
- location = /50x.html {
- root html;
- }
- } /
通常情况下,conf 文件存在多个 server 块,通过 listen 的端口 (默认是 80 端口) 和 server_name 进行区分, 对不同的请求提供不同的服务,如下:
- server {
- listen 80;
- server_name a.example.org;...
- }
listen 指令的格式如下:
Note | Description |
---|---|
Syntax: | listen address[:port][default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen port[default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [so_keepalive=on|off |
Default: | listen *:80 | *:8000; |
Context: | server |
listen 指令的参数:可以是 ip, hostname, ip/hostname:port, port, UNIX-domain socket. 例如:
- listen 127.0.0.1 : 8000;
- listen 127.0.0.1;
- listen 8000;
- listen * :8000;
- listen localhost: 8000;
- listen unix: /var/run / nginx.sock;
server 块内部的 listen 和 server_name 不能和其他 server 块的完全相同,否则启动加载配置的时候会出现如下错误:
- server {
- listen 80;
- server_name a.example.org;...
- }
- server {
- listen 80;
- server_name a.example.org;...
- }#nginx - s reload nginx: [warn] conflicting server name "a.example.org"on 0.0.0.0 : 80,
- ignored
当 nginx 决定了哪一个 server 处理客户端请求后,nginx 会解析 request header 中 URI(这里以及后面提到的大部分都是指相对 URI),然后匹配 server 块中的 location 指令的参数,匹配规则下一节会介绍。例如下例:
- server {
- listen 80;
- server_name localhost;
- location / {
- root html;
- index index.html index.htm;
- }
- }
location 块指令会用其参数与客户端请求的 URI 进行匹配,匹配的 URI 请求会被定向到 root 指令定义的特殊本地文件系统目录中,重定向规则为:将 URI 添加到 root 参数后面,生成一个本地文件路径,即:root 参数 + URI 请求。这里示例参数 "/" 会匹配所有的请求,一般都会默认存在。示例定位后的目录为 html/,默认是定位到安装目录的路径下的 html/。这里 location 块指令内部的两个简单指令的含义是:
默认的在 nginx 安装目录下都会存在一个 html 目标,在我电脑中为:/usr/local/nginx-1.8.0/html, 然后里面存在默认的 nignx 的欢迎界面,例如我安装 nginx 后直接启动 nginx bin 文件,然后访问对应的域名就得到了如下的页面:
如果有多个 location 指令块匹配到,nginx 的选择策略是 the longest prefix 最长前缀匹配原则。
例如,当上述的 server 中再增加一个 location 块,匹配参数为 "/htdocs/",重定向的资源路径为如下配置,
- server {
- listen 80;
- server_name localhost;
- location / {
- root html;
- index index.html index.htm;
- }
- location / htdocs {
- root / home / anonymalias;
- index index.html;
- }
- }
当访问,就会匹配到 / home/anonymalias/htdocs/index.html
nginx 的 location 指令是配置的核心,用于匹配 client 请求 uri 的 path 部分,然后对不同的请求提供不同的静态内容,或者通过反向代理重定向到内部的 server。
对于 client 的 request, nginx 会进行预处理,nginx 首先对采用 '%XX'(uri 采用 %+ 十六进制格式用于在浏览器和插件中显示非标准的字母和字符) 格式文本编码的 uri 进行解码。然后处理 path 中的相对路径符号'.'和'..',然后对于含有两个及以上的'/'压缩成一个'/'。 这样处理完后会得到一个干净的 path,然后会用这个 path 会在 server 的 location 指令的参数进行匹配。
- location语法:location[ = |~ | ~ * |^~] uri {...
- }
- location@name {...
- }
location 指令的参数:
- location~ * \. (gif | jpg | jpeg) $ { [configuration A]
- }
- location~\. (gif | jpg | jpeg) $ { [configuration B]
- }
若请求 URI 为 / images/a.JPG,只能匹配 A。
location 匹配的过程:
1. 首先 nginx 会把 request 的 uri 在 location 正常字符串参数中匹配出符合的最长字符串,并保存这个结果;
2. 如果最长前缀匹配结果前面有 "^~" 修饰符,那么停止继续搜索;
3. 如果最长匹配结果前有 "=" 修饰符,也会停止继续搜索;
4. 接下来,去匹配参数为正则表达式的所有 location,根据 location 的配置顺序,在匹配到第一个正则表达式时,即停止搜索其他的正则表达式;
所以如官网上的下例:
- location = / {
- [ configuration A ]
- }
- location / { [configuration B]
- }
- location / documents / { [configuration C]
- }
- location ^ ~ / images / { [configuration D]
- }
- location~ * \. (gif | jpg | jpeg) $ { [configuration E]
- }
nginx 使用很频繁的另一个服务就是作为代理服务器,提供将外部 client 的请求反向代理给内部被代理的 server, 然后接收 proxied server 的响应,并回包给 client。
proxy server 的配置和上面配置提供静态 web 服务的结构都是一致的。proxy server 的作用就是将一个 request 转发到一个 internal server,然后将 internal server 的 response 回传给 client。关于如何将 internal server 的回包转发给 client 是 nignx 底层做的事情,不需要要进行相关的配置,在配置层面上,我们要做的事情就是如何将一个 client 请求转发给 internal server。
下面是 nginx 官方最简单的一个 proxy server 的配置示例:
- server {
- location / {
- proxy_pass http: //localhost:8080/;
- }
- location~\. (gif | jpg | png) $ {
- root / data / images;
- }
- }
配置的含义:所有 URI 中已. gif, .jpg, .png 结尾的请求都会被映射到 / data/images 本地磁盘目录,把所有其他的 URI 请求透传给配置的被代理的 server: 。
nginx 反向代理模块有以下几个很重要的参数:
- location / name / {
- proxy_pass http: //127.0.0.1/remote/;
- }
说明:1.1.12 之前,如果 proxy_pass 指令不含有 URI,那么原始请求中的 URI 在某些情况下会被处理后再传递给 proxy server。
在某些情况下, 请求 URI 部分是否被替换是不能确定:
1. 在 location 指令的参数是一个正则表达式的时候;这个情况下,proxy_pass 的参数应该不喊 URI 部分。
2. 当 URI 在 location 指令模块中被 rewrite 指令改变后,???
该指令用于特定的 http header 从 proxy server 传回给 client。因为默认情况下有些 header 是不会回传给 client 的。默认情况下,nginx 不会把 proxy server 传回的参数中的 "Data", "Server", "X-Pad", "X-Accel-…" 回传给 client。其中 proxy_hide_header 指令,用于限定哪些 header 不回传给 client。
- proxy_set_header Accept - Encoding "";
默认情况下,只有以下两个字段会被重新定义:
- proxy_set_header Host $proxy_host;
- proxy_set_header Connection close;
其实默认定义往往不是我们期望要的,例如:Host header 被置为了 proxy_pass 指令设置的代理 server 的 url 和 port。但在实际应用中,我们往往是 Host 保留 client 的信息:
- proxy_set_header Host $host;
一般情况下 proxy server 的 location 会进行以下基本的设置:
- proxy_redirect off;
- proxy_set_header Host $host;
- proxy_set_header X - Real - IP $remote_addr;
- proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
什么是 CGI:
CGI 全称:通用网关接口 (Common Gateway Interface),是 Web 服务器与外部应用程序(CGI 程序) 之间的接口,说的那么晦涩其实 CGI 就是:Web 服务器与 CGI 程序通信的协议标准。很多人以及网上的很多文章都没有分清 CGI 和 CGI 程序这两个不同的概念。
CGI1.1 RFC3875 文档有详细的 CGI 协议的标准,.
Web Server 在 CGI 程序调用过程中,扮演着应用程序网关的角色。Web 服务器在收到客户端请求后,会将 client 的 http 请求根据 CGI 标准转换成一个 CGI 请求,然后将这个 CGI 请求交给 CGI 程序,CGI 程序处理完后,Web 服务器会将 CGI 的回包 (符合 CGI 标准) 转换成一个 client 的 http 回包,下发给 client。
关于 CGI 请求,有 2 种传递数据的途径:the meta-variables and message-body.
对应于上面两种 CGI 数据传输途径,有两种对应 request 方法,由 Meta-variable 中的系统变量 REQUEST_METHOD 的值来决定:
* GET 方法对应 Meta-variable 方式的数据传输;
* POST 方法对应 Message-body 方式的数据传输;
当然 REQUEST_METHOD 还有其他方法,这里不在阐述,在 CGI1.1 RFC3875 文档的 P10 Chapter4:The CGI Request 中有详细讲解。
CGI 程序执行的流程如下,fork-and-execute 模式 :
1.web 服务器收到客户端(浏览器)的请求 Http Request,启动 CGI 程序,并通过环境变量、标准输入传递数据
2.cgi 进程启动解析器、加载配置(如业务相关配置)、连接其它服务器(如数据库服务器)、逻辑处理等
3.cgi 程将处理结果通过标准输出、标准错误,传递给 web 服务器
4.web 服务器收到 cgi 返回的结果,构建 Http Response 返回给客户端,并杀死 cgi 进程
前面已经介绍过 web 服务器与 cgi 程序之间:通过环境变量、标准输入、标准输出、标准错误互相传递数据。
说了那么多 CGI 是什么以及 CGI 程序工作方式,那么现在该说什么是 FastCGI 了,
FastCGI:快速通用网关接口 (Fast Common Gateway Interface) 是通用网关接口(CGI)的改进 FastCGI 很简单,因为它实际上是在 CGI 基础上增加了一些的扩展,所以它同样是 Web 服务器与 CGI 程序通信的协议标准,只不过,它是一个建议标准。FastCGI 致力于减少 Web 服务器与 CGI 程式之间互动的开销,从而使服务器可以同时处理更多的 Web 请求。与使用 CGI 时,为每个请求创建一个新的进程不同,FastCGI 使用持续的进程来处理一连串的请求。这些进程由 FastCGI 进程管理器管理,而不是 web 服务器。
FastCGI 的开发商都致力于传播的 FastCGI 作为一个开放的标准。为此,对于当下流行且免费的 web server,FastCGI 开发者提供了免费 FastCGI 应用程序库(C / C ++,Java,Perl,TCL)和升级模块(Apache,ISS,lighttpd)。
FastCGI 的执行流程:
1.Web 服务器启动时载入初始化 FastCGI 执行环境 。 例如 IIS ISAPI、apache mod_fastcgi、nginx ngx_http_fastcgi_module、lighttpd mod_fastcgi
2.FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程并等待来自 Web 服务器的连接。启动 FastCGI 进程时,可以配置以 ip 和 UNIX 域 socket 两种方式启动。
3.当客户端请求到达 Web 服务器时, Web 服务器将请求采用 socket 方式转发到 FastCGI 主进程,FastCGI 主进程选择并连接到一个 CGI 解释器。Web 服务器将 CGI 环境变量和标准输入发送到 FastCGI 子进程。
4.FastCGI 子进程完成处理后将标准输出和错误信息从同一 socket 连接返回 Web 服务器。当 FastCGI 子进程关闭连接时,请求便处理完成。
5.FastCGI 子进程接着等待并处理来自 Web 服务器的下一个连接。
由于 FastCGI 程序并不需要不断的产生新进程,可以大大降低服务器的压力并且产生较高的应用效率。它的速度效率最少要比 CGI 技术提高 5 倍以上。它还支持分布式的部署, 即 FastCGI 程序可以在 web 服务器以外的主机上执行。
总结:CGI 就是所谓的短生存期应用程序,FastCGI 就是所谓的长生存期应用程序。FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,不会每次都要花费时间去 fork 一次(这是 CGI 最为人诟病的 fork-and-execute 模式)。
由于 nginx 不能像 apache 那样直接执行外部可执行程序,所以 nginx 不直接支持 CGI 程序,但 nginx 可以支持 FastCGI 代理,因为 nignx 支持反向代理, nginx FastCGI 代理的简单配置和反向代理类似,只是指令不一样,如下:
- server {
- location / {
- fastcgi_pass localhost: 9000;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- fastcgi_param QUERY_STRING $query_string;
- }
- location~\. (gif | jpg | png) $ {
- root / data / images;
- }
- }
[1]
[2]
[3]
[4]
[5]
[6]
[8]
来源: http://lib.csdn.net/article/liveplay/44518