Nginx的最佳实践
一. Nginx的简介
1. 什么是nginx
- Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”, 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器。Nginx是由俄罗斯人 Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,它已经在该站点运行超过两年半了。Igor Sysoev在建立的项目时,使用基于BSD许可。自Nginx 发布来,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
2. Ninx的优点
1. 高并发连接:
官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。
2. 内存消耗少:
在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)。
- 3. 配置文件非常简单:
风格跟程序一样通俗易懂。
- 4. 成本低廉:
Nginx为开源软件,可以免费使用。而购买F5 BIG-IP、NetScaler等硬件负载均衡交换机则需要十多万至几十万人民币。
- 5. 支持Rewrite重写规则:
能够根据域名、URL的不同,将 HTTP 请求分到不同的后端服务器群组。
- 6. 内置的健康检查功能:
如果 Nginx Proxy 后端的某台 Web 服务器宕机了,不会影响前端访问。
- 7. 节省带宽:
支持 GZIP 压缩,可以添加浏览器本地缓存的 Header 头。
- 8. 稳定性高:
用于反向代理,宕机的概率微乎其微。
Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率 。它支持内 核Poll模型,能经受高负载的考验,有报告表明能支持高达 50,000个并发连接数。 Nginx具有很高的稳定性,其它HTTP服务器当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应只能重启服务器。例如当前Apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。Nginx官方表示保持 10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对Nginx来说基本上是毫无用处的。就稳定性而言,nginx比lighttpd更胜一筹。 Nginx支持热部署,它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运 行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。 Nginx采用master-slave模型,能够充分利用SMP的优势,且能够减少工作进程在磁 盘I/O的阻塞延迟。 Nginx代码质量非常高,代码很规范,手法成熟, 模块扩展也很容易。 Nginx采用了一些os提供的最新特性如对sendfile (Linux2.2+),accept-filter(FreeBSD4.1+),TCP_DEFER_ACCEPT (Linux 2.4+)的支持,从而大大提高了性 能。
二. Nginx的配置文件
1. Nginx的配置文件详解
1.1 认识配置文件
Linux 下基本上每个服务都会有它的主配置文件,该文件会定义服务应该如果去运行,
使用些什么参数,启用些什么功能,相关会涉及到的一些操作文件在哪,所以主配置文件对 服务是至关重要的。下面我们来分析一下 Nginx 的主配置文件。
Nginx的主配置文件默认情况下位于/usr/local/nginx/nginx.conf 以下为Nginx
#指定使用的用户
#user nobody;
#启动进程,通常设置成和cpu的数量相等
worker_processes 1;
#全局错误日志
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#PID文件--存放进程号的文件
#pid logs/nginx.pid;
#工作模式及连接数上限
events {
#单个后台worker process进程的最大并发链接数
worker_connections 1024;
#并发总数是 worker_processes 和 worker_connections 的乘积
#Nginx支持如下处理连接的方法(I/O复用方法),这些方法可以通过 use指令指定。
#use [ kqueue | rtsig | epoll | /dev/poll | select | poll ];
#use epoll; #使用 epoll(linux2.6的 性能方式 )
#select - 标准方法。 如果当前平台没有更有效的方法,它是编译时默认的方法。你可以使用配置参数 –with-select_module 和 –without-select_module 来启用或禁用这个模块。
#poll - 标准方法。 如果当前平台没有更有效的方法,它是编译时默认的方法。你可以使用配置参数–with-poll_module 和 –without-poll_module 来启用或禁用这个模块。
#kqueue - 效的方法,使用于 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X. 使用双处理器的 MacOS X系统使用 kqueue可能会造成内核崩溃。
#epoll - 效的方法,使用于Linux内核2.6版本及以后的系统。在某些发行版本中,如 SuSE 8.2,有让2.4版本的内核支持epoll的补丁。
#rtsig - 可执行的实时信号,使用于Linux内核版本 2.2.19以后的系统。可是从Linux内核版本2.6.6-mm2开始,这个参数就不再使用了.
#/dev/poll - 效的方法,使用于 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+.
#eventport - 效的方法,使用于 Solaris 10. 为了防止出现内核崩溃的问题, 有必要安装 这个 安全补丁。
}
http {
#设定mime类型,类型由mime.type文件定义
include mime.types;
default_type application/octet-stream;
#设定日志格式
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
#对于普通应用,必须设为 on,
#如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
#以平衡磁盘与网络I/O处理速度,降低系统的uptime.
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#连接超时时间
#keepalive_timeout 0;
keepalive_timeout 65;
#开启gzip压缩
#gzip on;
#设定虚拟主机配置
server {
#侦听80端口
listen 80;
#定义使用 www.nginx.cn访问
server_name localhost;
#定义服务器的默认网站根目录位置
root html;
#设置编码
#charset koi8-r;
#设定本虚拟主机的访问日志
#access_log logs/host.access.log main;
#默认请求
location / {
root html;
#定义首页索引文件的名称
index index.html index.htm;
}
# 定义错误提示页面
#error_page 404 /404.html;
#redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#PHP脚本转给apache处理
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
# 禁止访问 .htxxx 文件
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
1.2 nginx的配置文件结构
- nginx.conf由多个块组成,最外面的块是main,main包含events和http,http包含多个upstream和多个server,server又包含多个location:
- main(全局设置)、server(虚拟主机设置)、upstream(负载均衡服务器设置)和 location(URL匹配特定位置的设置)。
- main块设置的指令将影响其他所有设置;
- server块的指令主要用于指定主机和端口;
- upstream指令主要用于负载均衡,设置一系列的后端服务器;
- location块用于匹配网页位置。
- 这四者之间的关系式:server继承main,location继承server,upstream既不会继承其他设置也不会被继承。
- 在这四个部分当中,每个部分都包含若干指令,这些指令主要包含Nginx的主模块指令、事件模块指令、HTTP核心模块指令,同时每个部分还可以使用其他HTTP模块指令,例如Http SSL模块、HttpGzip Static模块和Http Addition模块等。
1.3 Nnginx的全局配置
#指定使用的用户和组
#user nginx nginx;
#启动进程,通常设置成和cpu的数量相等
worker_processes 1;
#全局错误日志
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#PID文件--存放进程号的文件
#pid logs/nginx.pid;
创建全局配置中nginx需要的运行用户
groupadd nginx
useradd -g nginx nginx
2. events配置
服务器为linux时, 请讲use epoll打开. 利用linux的内核提供性能优化方案
#工作模式及连接数上限
events {
#单个后台worker process进程的最大并发链接数
worker_connections 1024;
#并发总数是 worker_processes 和 worker_connections 的乘积
#Nginx支持如下处理连接的方法(I/O复用方法),这些方法可以通过 use指令指定。
#use [ kqueue | rtsig | epoll | /dev/poll | select | poll];
use epoll; #使用 epoll(linux2.6的 性能方式 )
}
3. http的配置
http {
#Nginx对HTTP服务器相关属性的配置
include mime.types;
default_type application/octet-stream;
#设定虚拟主机配置
server {
#侦听80端口
listen 80;
#定义使用 www.itsource.cn访问
server_name www.itsource.cn;
location {
}
location {
}
…..
}
server {
#侦听80端口
listen 80;
#定义使用 www.example.cn访问
server_name www.example.cn;
location {
}
location {
}
…..
}
}
include是个主模块指令,实现对配置文件所包含的文件的设定,可以减少主配置文件的复杂度。类似于Apache中的include方法。
default_type属于HTTP核心模块指令,这里设定默认类型为二进制流,也就是当文件类型未定义时使用这种方式,例如在没有配置PHP环境时,Nginx是不予解析的,此时,用浏览器访问PHP文件就会出现下载窗口。
server块的指令主要用于指定主机和端口(虚拟主机);
location部分主要用于匹配网页位置,设置不同的功能特征. 比如:缓存,重定向等…
4. nginx重要指令之location
location部分主要用于匹配网页位置,设置不同的功能特征. 比如:缓存,重定向等…
实例:
- 有扩展名以.gif、.jpg、.jpeg、.png、.bmp、.swf结尾的静态文件都交给nginx处理,而expires用来指定静态文件的过期时间,这里是30天
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
root /wwwroot/www.itsource.com;
expires 30d;
}
- upload和html下的所有文件都交给nginx来处理,当然,upload和html目录包含在/web/wwwroot/www.itsource.cn目录中
location ~ ^/(upload|html)/ {
root /web/wwwroot/www.itsource.com;
expires 30d;
}
- location是对此虚拟主机下动态网页的过滤处理,也就是将所有以.php为后缀的文件都交给本机的8080端口处理
location ~ .*.php$ {
index index.php;
proxy_pass http://localhost:8080;
}
location的语法:
~ #波浪线表示执行一个正则匹配,区分大小写
~ #表示执行一个正则匹配,不区分大小写*
^~ #^~表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录
= #进行普通字符精确匹配
location中可以接受一下的语法规则
location = / {
# 只匹配"/".
[ configuration A ]
}
location / {
# 匹配任何请求,因为所有请求都是以"/"开始
# 但是更长字符匹配或者正则表达式匹配会优先匹配
[ configuration B ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开始的请求,并停止匹配 其它location
[ configuration C ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配以 gif, jpg, or jpeg结尾的请求.
# 但是所有 /images/ 目录的请求将由 [Configuration C]处理.
[ configuration D ]
}
优先级:
=前缀的指令严格匹配这个查询。如果找到,停止搜索。
所有剩下的常规字符串,最长的匹配。如果这个匹配使用^〜前缀,搜索停止。
正则表达式,在配置文件中定义的顺序。
如果第3条规则产生匹配的话,结果被使用。否则,如同从第2条规则被使用。
请求URI例子:
/ -> 符合configuration A
/documents/document.html -> 符合configuration B
/images/1.gif -> 符合configuration C
/documents/1.jpg ->符合 configuration D
三. Nginx中的rewrite
1. 什么是rewrite
Rewrite对称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。比如http://www.123.com/news/index.asp?id=123 使用URLRewrite 转换后可以显示为 http://www.123.com/news/123.html
对于追求完美主义的网站设计师,就算是网页的地址也希望看起来尽量简洁明快。形如http://www.123.com/news/index.asp?id=123的网页地址,自然是毫无美感可言,而用UrlRewrite技术,你可以轻松把它显示为 http://www.123.com/news/123.html。
理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,UrlRewrite可以让我们网站的网页更容易被搜索引擎所收录。
从安全角度上讲,如果在url中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的url地址可以给我们带来更高的安全性。
2. rewrite的命令的作用域和优先级
- 作用域:server,location.
- rewrite指令可以写在server和location中.
nginx rewrite指令执行顺序:
执行server块的rewrite指令(这里的块指的是server关键字后{}包围的区域,其它xx块类似)
执行location匹配
执行选定的location中的rewrite指令
如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件
例如:
四. Nginx的虚拟主机
1. 什么是Nginx的虚拟主机
- 虚拟主机是用来映射网站目录和网站代码文件夹的关系.它可以通过server配置, 每个server表示一个虚拟机主机.
2. 标准的虚拟主机配置
http {
#默认的虚拟机主机
server {
listen 80 default;
server_name _ *;
access_log logs/default.access.log main;
location / {
index index.html;
root /var/www/default/htdocs;
}
}
#www.domain1.com对应的虚拟主机
server {
listen 80;
server_name www.domain1.com;
access_log logs/domain1.access.log main;
location / {
index index.html;
root /var/www/domain1.com/htdocs;
}
}
#www.domain2.com对应的虚拟主机
server {
listen 80;
server_name www.domain2.com;
access_log logs/domain2.access.log main;
location / {
index index.html;
root /var/www/domain2.com/htdocs;
}
}
}
3. 规划虚拟主机的配置文件
以上全部配置在主配置文件中可能不小心修改掉配置文件导致nginx.conf文件出错. 可以使用include指令将每个虚拟主机放在一个单独的配置文件中.
将nginx服务器目录结构设置为:
nginx
nginx.conf
vhost
– www.domain1.com.conf
– www.domain2.com.conf
- 每个.conf结尾的文件中保存一个虚拟主机(server)的配置信息.在nginx.conf中通过include指令包含这些配置文件.
- 在nginx/config/nginx.conf中的配置:
http {
#默认的虚拟机主机
server {
listen 80 default;
server_name _ *;
access_log logs/default.access.log main;
location / {
index index.html;
root /var/www/default/htdocs;
}
}
include vhost/*.conf;
}
- 在nginx/config/vhost/www.domain1.com.conf中的配置:
server {
listen 80;
server_name www.domain1.com;
access_log logs/domain1.access.log main;
location / {
index index.html;
root /var/www/domain1.com/htdocs;
}
}
- 在nginx/config/vhost/www.domain2.com.conf中的配置:
server {
listen 80;
server_name www.domain2.com;
access_log logs/domain2.access.log main;
location / {
index index.html;
root /var/www/domain2.com/htdocs;
}
}
五. 动静分离
- 当用户请求js,css等静态资源时有当前nginx服务器处理, 请求php动态脚本代码时由其他的服务器处理(反向代理).
#配置Nginx动静分离,定义的静态页面直接从Nginx发布目录读取。
location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
{
root /data/www/wugk;
#expires定义用户浏览器缓存的时间为3天,如果静态页面不常更新,可以设置更长,这样可以节省带宽和缓解服务器的压力
expires 3d;
}
#动态页面交给其他服务器处理
location ~ .*\.(php|jsp|cgi)?$
{
#发送给其他服务器处理
}
- 容量符号缩写
k,K | 千字节 |
---|---|
m,M | 兆字节 |
- 时间符号缩写
ms | 毫秒 |
---|---|
s | 秒 |
m | 分钟 |
h | 小时 |
d | 日 |
w | 周 |
M | 一个月, 30天 |
y | 年, 365 天 |
六. Nginx的反向代理
1. 什么是反向代理
- 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连的 客户端,此时代理服务器对外就表现为一个服务器。
2. 明确两个概念
- web前端服务器: 代理服务器可以作为前端服务器处理静态资源
- web后端服务器: web前端服务器无法处理的动态请求发送给后台web服务器处理.
3. 特点
反向代理又称为Web服务器加速,是针对Web服务器提供加速功能的。它作为代理
Cache,但并不针对浏览器用户,而针对一台或多台特定Web服务器(这也是反向代理名
称的由来)。代理服务器可以缓存一些web的页面,降低了web服务器的访问量,所以可
以降低web服务器的负载。web服务器同时处理的请求数少了,响应时间自然就快了。同
时代理服务器也存了一些页面,可以直接返回给客户端,加速客户端浏览。
4. 反向代理的配置
- 当用户放到php文件时,将该请求交给apache服务器处理php文件
server {
#侦听192.168.8.x的80端口
listen 80;
server_name www.itsource.cn;
#对php后缀的进行请求
location ~ .*\.php$ {
#定义服务器的默认网站根目录位置
root /root;
#定义首页索引文件的名称
index index.php index.html index.htm;
#请求转向apache服务器,apache服务器运行在81端口上
proxy_pass http://localhost:81;
#以下是一些反向代理的配置可删除.
proxy_redirect off;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#允许客户端请求的最大单文件字节数
client_max_body_size 10m;
#缓冲区代理缓冲用户端请求的最大字节数,
client_body_buffer_size 128k;
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
#连接成功后,后端服务器响应时间(代理接收超时)
proxy_read_timeout 90;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffer_size 4k;
#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
}
}
5. 可以将代理配置单独放在一个配置文件中
- 存放代理配置的nginx/conf/proxy.conf: 其他的server虚拟主机都可以使用该配置.
#以下是一些反向代理的配置可删除.
proxy_redirect off;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#允许客户端请求的最大单文件字节数
client_max_body_size 10m;
#缓冲区代理缓冲用户端请求的最大字节数,
client_body_buffer_size 128k;
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
#连接成功后,后端服务器响应时间(代理接收超时)
proxy_read_timeout 90;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffer_size 4k;
#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
- 使用代理配置文件:
server {
listen 80;
server_name www.itsource.cn;
#对php后缀的进行请求
location ~ .*\.php$ {
#定义服务器的默认网站根目录位置
root /root;
#定义首页索引文件的名称
index index.php index.html index.htm;
#请求转向apache服务器,apache服务器运行在81端口上
proxy_pass http://localhost:81;
#以下是一些反向代理的配置可删除.
include proxy.conf;
}
}
七. Nginx的负载均衡
1. 什么是负载均衡
- 后台服务器组成了一个服务器集群(多台服务器). 有中间服务器(nginx)接受到请求分发给不同的服务器后台. 该nginx就是一个负载均衡服务器.
2. 负载均衡的优点
- 分散后台服务器的压力
- 自动去掉挂掉的后台服务器
- 缓存后台服务器响应内容
3. 负载均衡的分配策略
- nginx 的 upstream目前支持 4 种方式的分配
a. 轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。b. weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。c. ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
d. fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
e. url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
4. 负载均衡配置
- 在http节点里添加:
#定义负载均衡设备的 ip及设备状态
upstream myServer {
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
[ip_hash | fair | url_hash]
}
- 在需要使用负载的server节点下添加
proxy_pass http://myServer;
- upstream 每个设备的状态:
down 表示单前的server暂时不参与负载
weight 默认为1.weight越大,负载的权重就越大。
max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
fail_timeout:max_fails 次失败后,暂停的时间。
backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。