翻译了nginx的开始部分,以后有时间继续。



开始指南

Nginx有一个主进程和多个工作进程。主进程的目的是读取和评估配置并维护工作进程。工作进程处理请求任务。各个工作进程使用基于事件的模式和依赖操作系统机制在他们之间有效分发请求。工作进程数量在配置文件中定义。可以是固定的也可以更加cpu内核数量动态调整。

默认配置文件位置/usr/local/nginx/conf,/etc/nginx/usr/local/etc/nginx名字为nginx.conf

Nginx –s signal

Signal参数有以下几种

stop ---快速退出

quit---平稳退出(等待工作进程完成当前请求后退出)

reload ----重新加载配置文件(更改配置文件必须重新加载一下)

reopen---重新打开日志文件

得到nginx进程列表 ps –ef|grep nginx

配置文件结构

Nginx由一些模块组成。


服务静态内容

Web服务一个重要任务是发布文件(如图像和静态html网页)。举例:有两个目录中文件需发布/data/www,/data/p_w_picpaths则需要在http块中加一个包含两个locationserver块。

http{

server {

}

}

多个server块通过端口或server names区分。

server {
    location / {
        root /data/www;
    }
    location /p_w_picpaths/ {
        root /data;
    }
}

查询出错原因请查看 access.log error.log在目录/usr/local/nginx/var/log/nginx


设置一个简单的代理服务器

在配置文件中添加如下内容:

server {
    listen 8080;
    root /data/up1;
    location / {
    }
}

这是一个代理服务和被代理服务在同一服务器上的实例。

也可以用如下方式:

server {
    location / {
        proxy_pass http://localhost:8080;
    }
    location /p_w_picpaths/ {
        root /data;
    }
}

还可以使用正则表达式指定文件类型以~开始。

server {
    location / {
        proxy_pass http://localhost:8080/;
    }
    location ~ \.(gif|jpg|png)$ {
        root /data/p_w_picpaths;
    }
}

设置fastcgi代理

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/p_w_picpaths;
    }

Query_string参数:被用来传递请求参数。









控制nginx

Nginx主进程id默认被写入文件/usr/local/nginx/logs/nginxpid

更改配置

nginx –s HUP(新请求用更改后配置,未结束请求继续用旧配置,所有请求结束后都开始用新配置)

连接处理方法

Nginx会自动选择最有效的连接处理方法,也可以使用 use指令明确指定。有如下方法支持。

select:标准方法。支持模块被自动构建。用—with-select_module—without-select_module启用和禁用模块。

poll:标准方法。--with-poll_module —without-poll_module

kqueue :freebsd4.1+OpenBSD 2.9 NetBSD 2.0 mac os x上用

epoll :有效方法用在linux 2.6+

rtsig:实时信号。用在linux 2.2.19+上有效。默认系统范围事件队列默认限制1024个信号。在高负载机器上需要增加它的限制可在/proc/sys/kernel/rtsig-maxkernel parameter中更改。在linux2.6.6-mm2中已没有此参数。每个进程有他自己的队列。每个队列大小被RLIMIT_SIGPENDING限制。可用worker_rlimit_sigpending参数更改。

/dev/poll/ Solaris711/99+ HP/UX 11.22+ IRIX 6.5.15= andtru64 unix 5.1A+上有效。

Eventport solaris10上有效。




配置hashes

Nginx使用hash tables处理如 server namesmap directive’s 值,mime types 请求头字符串名。Server names hash server_names_hash_max_size server_name_hash_bucker_size

Hash bucketsize 和一个处理器的缓存大小的倍数匹配。它可以加速key搜索,减少内存访问次数。如果hash bucket大小等于处理器缓存大小那么在最糟糕的情形下在搜索key的内存访问次数是两次。1.计算bucket地址,2。在bucket中搜索key。因此,如果nginx发出信息增加的话要么增加hash max size 要么增加bucket size 第一个参数首先被增加。

调试日志

支持debugging log 在编译时加上 --with-debug

./configure –with-debug

设置error_log 调试等级

error_log/path/to/log debug

重新定义log时不指定bebuglevel将会禁用调试日志功能。

error_log /path/to/log debug;
http {
    server {
        error_log /path/to/log;

表明在server块中禁用调试日志。

还可以指定日志服务器地址为debug level

error_log /path/to/log;
events {
    debug_connection 192.168.1.1;
    debug_connection 192.168.10.0/24;
}
                   Nginx如何处理一个请求
server {
    listen      80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      80;
    server_name example.com www.example.com;
    ...
}
上面配置文件根据请求头的域“host”决定请求被路由到那个服务器。如果都不匹配则路由到第一个服务器(默认)。也可以明确指定那个是默认服务器。
server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}
如何定义阻止未定义的请求
server {
    listen      80;
    server_name "";
    return      444;
}
这样未定义的host,将被丢弃。
0.8.48以后版本这是默认配置。



基于名字和ip的虚拟服务

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

在此配置中nginx先匹配请求中ip地址和端口,然后是“host”域。如果没找到,请求被默认服务器处理。

一个默认服务是一个合适的侦听端口,不同的端口可定义不同的默认服务器。

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}


一个简单的php站点配置

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;
    location / {
        index   index.html index.php;
    }
location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }
    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

Nignx首先搜索prefix location,不管列出顺序如何。上面配置文件仅有的prefixlocation是“/”,由于它匹配任何请求,所以被最后执行。Nginx检查列表中location的正则表达式,找到第一个匹配的表达式就会停止搜索,nginx会使用这个location。如果没有匹配的,nginx用先前找到的特定的prefixlocation

注意:location测试的是URI请求行的一部分,没有参数。

1.一个请求“/logo.gif”首先匹配 prefix location,然后匹配表达式“\.(gif|jpg|png)$”,因此被后一个location处理。使用指令root /data/www请求被映射到文件/data/www/logo.gif,然后被发送到客户端。

2.一个请求/index.php同样首先匹配prefix location/“,然后匹配表达式\.(php)$。因此,被后一个表达式处理。请求被发送到fastcgiserver 本机的localhost:9000.Thefastcgi_param指令设置FastCGI 参数SCRIPT_FILENAMEto “/data/www/index.php”,变量$document_root匹配root指令的值。变量$fastcgi_script_name匹配请求的URI,/index.php”.

3.请求/about.html只匹配prefixlocation,所以只被这个location处理。请求被映射到/data/www/about.html

4.处理请求“/“较复杂。他只匹配prefixlocation。因此只被这个location处理。然后index指令检查index文件是存在,如果/data/www/index.html不存在,/data/www/index.php存在,那么指令会做一个内部重定向到/index.php并被fastcgiserver 处理。

优化

1.完整的名字,2.以通配符开始的名字,3.以通配符结束的名字被存储在绑定到端口的三张hash 表中。Hash 表大小可调。目的是名字能更快被找到。三张表按序搜索。含通配符名字hash表搜索较慢。正则表达式最慢而且不可扩展。

如果有大量服务名被定义,或不常用的长服务名被定义,调整server_names_hash_max_sizeandserver_names_hash_bucket_size指令httplevel中是有帮助的。可以是3264或其他值,取决于cpu 缓存大小。如果默认值是32server name被定义成too.long.server.name.example.org” nginx 未能启动并显示如下信息:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32

这个例子中指令值应被增加

http {
    server_names_hash_bucket_size  64;
...
如果出现如下信息;
could not build the server_names_hash,
you should increase either server_names_hash_max_size: 512
or server_names_hash_bucket_size: 32
这个例子中,首先尝试设置server_names_hash_max_size的数量server names相当。如果没有效果,或nginx启动时间不可接受尝试增加server_names_hash_bucket_size.


配置https服务器

配置https服务器,ssl参数必须被激活在serverlisteningsockets。服务器位置证书和私钥应该被指定。

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ...
}

服务器证书是一个公共实体。它被发送给每个客户端。私钥是安全实体应该被保存在一个受限制文件中。它必须可被master主进程读取。私钥可以和证书一起存储在一个相同的文件中

ssl_certificate     www.example.com.cert;
    ssl_certificate_key www.example.com.cert;

这个例子中文件权限应该被约束,只有证书可以被发送到客户端。

https优化

ssl操作消耗更多的cpu资源。一个多处理系统有多个worker进程被运行数量不少于可用cpu内核数。Cpu集中操作在ssl握手期间。有两种方法可以最小化操作和每个客户端握手的数量。1.使keepalive连接可用,通过一个连接发送多个请求。2.为并行的和后来的连接重新使用ssl session 参数避免ssl多次握手。Sessions被存储于ssl session缓存中。被多个workers进程共享。在ssl_session_cache指令中配置。1m字节缓存可包含4000sessions。默认缓存超时是5分中。可在ssl_sessioni_timeout中设置。下面是一个简单配置为一个多核系统包含10m共享session 缓存的系统优化。

worker_processes auto;
http {
ssl_session_cache  shared:SSL:10m;
ssl_session_timeout 10m;
    server {
        listen              443 ssl;
        server_name         www.example.com;
keepalive_timeout  70;
        ssl_certificate     www.example.com.crt;
        ssl_certificate_key www.example.com.key;
        ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ...

Ssl证书链

一些浏览器可能拒绝一个众所周知的证书权威机构签发的证书,而其他浏览器没有问题。可以使用证书链解决。服务器证书应该在bundle.crt之前。

$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt

文件应该被用在ssl_certificate指令:

server {
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.chained.crt;
    ssl_certificate_key www.example.com.key;
    ...
}

如果顺序错了,nignix就不能启动,显示如下信息:

SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
   (SSL: error:0B080074:x509 certificate routines:
    X509_check_private_key:key values mismatch)

确信服务器发送完全的证书链,使用openssl命令:

$ openssl s_client -connect www.godaddy.com:443
...
Certificate chain
 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
     /OU=MIS Department/CN=www.GoDaddy.com
     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
   i:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
     /OU=ValiCert Class 2 Policy Validation Authority
     /CN=http://www.valicert.com//emailAddress=info@valicert.com
...

这个例子中www.godaddy.com对象(“s”)服务证书#0被一个发布人(i)签发,它自己的证书对象是#1,它的证书被证书是#2对象签发。#2证书被众所周知的发行人valicert公司签发。他的证书被存储在浏览器中。

如果证书链未被最加,仅有服务器证书#0被显示。



单个http/https server

server {
    listen              80;
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ...
}

基于名字的https server

server {
    listen          443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
    ...
}
server {
    listen          443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
    ...
}

这个配置中浏览器接受默认服务器证书。www.example.com不管请求的服务名。这是由于ssl proctol 脚本缘故。ssl 连接在浏览器发送http请求之前并且nginx不知道请求服务的名字。因此,它只可能提供默认服务证书。

解决这个问题最老的方法是制定单独的ip为每个https server

server {
    listen          192.168.1.1:443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
    ...
}
server {
    listen          192.168.1.2:443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
    ...
}


一个ssl证书和多个服务名

还有其他方法允许共享单个ip在多个https服务器之间。但是它们都有缺陷。

一个较好的方法是在配置文件中http level放置一个证书文件和他的私钥文件,在所有服务中继承它们单个内存拷贝。

ssl_certificate     common.crt;
ssl_certificate_key common.key;
server {
    listen          443 ssl;
    server_name     www.example.com;
    ...
}
server {
    listen          443 ssl;
    server_name     www.example.org;
    ...
}

服务名参考

一个更通用的在单个ip上运行多个https服务的方法是TLS Server NameIndication extension(SNI, RFC6066),它允许浏览器在握手期间传递一个请求服务名,因此,服务器知道要使用那个证书。当前只在下列浏览器中支持。

  • Opera 8.0;

  • MSIE 7.0 (but only on Windows Vista or higher);

  • Firefox 2.0 and other browsers using Mozilla Platform rv:1.8.1;

  • Safari 3.2.1 (Windows version supports SNI on Vista or higher);

  • and Chrome (Windows version supports SNI on Vista or higher, too).

使用sni,必须在nginxbuiltopenssl库支持sni,同时在运行时动态链接。open ssl 0.9.8f已默认支持。使用下列命令查看nginx是否支持sni

$ nginx -V
...
TLS SNI support enabled
...

但是如果nginx动态链接到不支持sniopenssl会出现如下错误。

nginx was built with SNI support, however, now it is linked
dynamically to an OpenSSL library which has no tlsext support,
therefore SNI is not available