Nginx
标签 : nginx
Nginx
nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 25.64% busiest sites in April 2016. Here are some of the success stories: Netflix, Wordpress.com, FastMail.FM.
The sources and documentation are distributed under the 2-clause BSD-like license.
Commercial support is available from Nginx, Inc.
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,由俄罗斯工程师Igor Sysoev开发,供俄国大型入口网站及搜索引擎Rambler使用.其源代码以BSD-like协议发布. 其特点是内存占用少,并发能力强, 因此被国内很多大型网站(如京东/淘宝)采用.
(主页/介绍/文档).
编译安装
wget http://nginx.org/download/nginx-1.10.0.tar.gz
tar -zxvf nginx-1.10.0.tar.gz
./configure --prefix=/usr/local/nginx
configure阶段可能会遇到缺少依赖库的提示(如
pcre
/zlib
),此时需要安装这些依赖才能继续:yum install pcre pcre-devel
yum install zlib zlib-devel
make && make install
安装完成后可在/usr/local/nginx/目录下生成如下文件夹:
目录 | 描述 |
---|---|
conf | nginx配置文件 |
html | 网页文件 |
logs | nginx日志文件 |
sbin | nginx可执行文件 |
/usr/local/nginx/sbin/nginx
启动, Nginx默认占用80
端口,可在nginx.conf中更改.
Nginx信号
关于Linux信号相关知识, 可参考系列博客Linux信号实践, 在此, 我们仅介绍Nginx捕获的几个信号.
nginx can be controlled with signals.
Kill -信号名 PID
信号名 | 作用 |
---|---|
TERM /INT |
fast shutdown |
QUIT |
graceful shutdown |
HUP |
changing configuration, keeping up with a changed time zone , starting new worker processes with a new configuration, graceful shutdown of old worker processes |
USR1 |
re-opening log files |
USR2 |
upgrading an executable file |
WINCH |
graceful shutdown of worker processes |
以上信号作用亦可通过编译出的nginx
二进制文件实现:
To start nginx, run the executable file. Once nginx is started, it can be controlled by invoking the executable with the -s parameter. Use the following syntax:
nginx -s signal
配置
- nginx.config
#运行服务的用户及用户组
#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 {
# 采用epoll进行IO复用
# use epoll;
# 单进程所允许的最大连接数
worker_connections 1024;
}
http {
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"';
#access_log logs/access.log main;
#是否激活sendfile()函数
sendfile on;
#将HTTP响应头压缩到一个包中发送,仅在sendfile开启时才能使用
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#开启gzip模块
#gzip on;
#设定虚拟主机,默认监听80端口,可配置多个
server {
listen 80;
server_name localhost;
#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
#
#location ~ .php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#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
#
#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;
# }
#}
}
Server
在Nginx内可配置虚拟主机, 只需在nginx.conf中添加一个server元素:
server {
listen 801;
server_name www.feiqing.me;
location / {
root /www.feiqing.me/;
index index.html index.htm;
}
}
Log
- 自定义log_format
log_format fq_log_format '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
servlet
内引用
access_log logs/www.feiqing.me.access.log fq_log_format;
启用log log位置 log格式
- 示例
为www.feiqing.meserver
单独配置一个log
:
server {
listen 801;
access_log logs/www.feiqing.me.access.log main;
server_name www.feiqing.me;
location / {
root /www.feiqing.me/;
index index.html index.htm;
}
}
Location
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location
Sets configuration depending on a request URI.
Nginx允许自定义location
块,通过指定的模式与客户端请求的URI相匹配,Nginx可将网站根据URI进行划分,将网站的不同部分定位到不同的处理方式上:
server {
server_name www.feiqing.me;
location /admin/ {
# The configuration you place here only applies to http://www.feiqing.me/admin/
}
}
- location修饰符
location
第一个可选参数是一个符号,用来定义Nginx的匹配模式:
修饰符 | 描述 |
---|---|
@ |
指定一个命名的location ,一般只用于内部重定向请求 |
= |
精确匹配模式: URI的定位必须与指定的模式精确匹配 |
(无) |
一般匹配模式: URI的定位必须以指定模式开始, 不可以使用正则表达式 |
~ |
区分大小写的正则匹配模式: 客户端请求URI与指定正则表达式匹配必须区分大小写 |
~* |
不区分大小写的正则匹配模式 |
^~ |
类似于(无) 模式的行为, URI的定位必须以指定模式开始, 不同的是, 如果模式匹配, 那么Nginx就停止搜索其他模式 |
!~ /!~* |
分别为区分大小写不匹配和不区分大小写不匹配的正则 |
/ |
通用匹配, 任何请求都会匹配到 |
有多个
location
配置情况下的匹配顺序:- 带有
=
修饰符的location
: 如果指定pattern
与URI 精确匹配, 则Nginx使用该location
设置. - 没有修饰符的
location
: 如果指定pattern
与URI 精确匹配,则使用之. - 带有
^~
修饰符的location
: 如果指定pattern
与URI 开始匹配, 则使用之. - 带有
~
/~*
修饰符的location
: 如果指定pattern
与URI 匹配, 则使用之. - 没有修饰符的
location
: 如果指定pattern
与URI 开始匹配, 则使用之. - 通用匹配
/
.
- 带有
示例:
location ~* ^/w*adminw*/ {
root /var/www/regexp/;
index index.html;
}
关于
location
详细内容可参考Nginx-ngx_http_core_module模块文档.
Rewrite
Rewrite用于实现URI重写, URI重写可以让我们在改变网站结构时,无需修改原先暴露出去的URL, 并且在一定程度上提高网站安全性;
The ngx_http_rewrite_module module is used to change request URI using regular expressions, return redirects, and conditionally select configurations.
Nginx的Rewrite的实现依赖于PCRE(Perl Compatible Regular Expressions:Perl兼容正则表达式)库, 因此在编译Nginx前, 需要确保系统中已经包含该依赖.
注意: 正则表达式的元字符
{
与}
会与nginx.conf中block定界符{ ... }
有冲突, 如果需要在nginx.conf内写一个包含花括号的正则表达式,需要将表达式放在单引号/双引号之间.
- Rewrite指令执行顺序:
- 执行
server
块rewrite
指令; - 执行
location
匹配; - 执行选定
location
中的rewrite
指令;
- 执行
如果其中某步URI被重写,则重新循环执行1-3步,直到找到真实存在的文件. 但循环次数不能超过10次, 否则Nginx返回
500-Internal Server Error
.
指令
if 指令
Syntax: if (condition) { ... }
Default: —
Context: server, location
- The specified condition is evaluated. If true, this module directives specified inside the braces are executed, and the request is assigned the configuration inside the if directive. Configurations inside the if directives are inherited from the previous configuration level.
if
条件可以是如下内容:
condition | 描述 |
---|---|
一个变量名 | 只有该变量是空字符串或者以0开始的字符串, 才为false |
使用= /!= |
比较一个变量和字符串 |
使用~ /~* |
变量与正则表达式进行匹配的变量 |
使用-f /!-f |
检查一个文件是否存在 |
使用-d /!-d |
检查一个目录是否存在 |
使用-e /!-e |
检查一个文件、目录、符号链接是否存在 |
使用-x /!-x |
检查一个文件是否可执行 |
- 示例
location ~* ^/w*adminw*/ {
if ($request_method = GET) {
return 405;
}
root /var/www/regexp/;
index index.html;
}
- 其他
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
if ($request_method = POST) {
return 405;
}
if ($slow) {
limit_rate 10k;
}
if ($invalid_referer) {
return 403;
}
break 指令
Syntax: break;
Default: —
Context: server, location, if
- Stops processing the current set of
ngx_http_rewrite_module
directives(停止执行当前虚拟主机的后续rewrite
指令).
return 指令
Syntax: return code [text];
return code URL;
return URL;
Default: —
Context: server, location, if
- Stops processing and returns the specified code to a client. The non-standard code 444 closes a connection without sending a response header(停止处理并返回指定状态码给客户端,非标准状态码444表示关闭连接且不给客户端发送响应头).
该指令用于直接向客户端返回响应状态码,从0.8.42版本起,return
支持响应URL重定向(对于301/302/303/307),或者文本响应(对于其他状态码).
注意: 对于302/307, 返回的URL中应包含
"http://"
/"https://"
.对于文本或者URL重定向可以包含变量.
if ($http_user_agent ~ Chrome) {
return 302 http://www.baidu.com;
}
set 指令
Syntax: set $variable value;
Default: —
Context: server, location, if
- Sets a value for the specified variable. The value can contain text, variables, and their combination.
rewrite 指令
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if
- If the specified regular expression matches a request URI, URI is changed as specified in the replacement string(如果一个URI匹配指定的正则表达式, URI就按照
replacement
形式重写). The rewrite directives are executed sequentially in order of their appearance in the configuration file. It is possible to terminate further processing of the directives using flags(rewrite按配置文件中出现的顺序执行, 但flags标志可以停止继续处理). If a replacement string starts with “http://” or “https://”, the processing stops and the redirect is returned to a client.
注意: 接收到的URI不包含host地址(如example.com), 也不包含URL中的请求参数(如?arg1=value1&arg2=value).
实例-伪静态化
使用Rewrite功能将JavaWeb中的动态URL(xx.do?arg1=xx&arg2=xx)以静态URL替换(xx-xx-xx.html).
server {
listen 800;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location ~* (/javis/teacher/).*(.html)$ {
rewrite /javis/teacher/(w+)-(w+)-(w+).html /javis/teacher/$1.do?name=$2&password=$3;
}
location ~* .(do|jsp|jspx)?$ {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://10.45.156.170:80;
}
}
location ~* (/javis/teacher/).*(.html)$ { ... }
会拦截所有/javis/teacher/ 目录下以.html
结尾的静态URL,将其重写为.do
结尾的动态URL(/javis/teacher/login-new_name-password.html -> /javis/teacher/login.do?name=new_name&password=password ), 然后location ~* .(do|jsp|jspx)?$ { ... }
提供反向代理功能,将所有以.do
结尾的URL转发到http://10.45.156.170:80地址, 由Java的后端Server提供真正的服务(反向代理相关知识可参考我的下一篇Nginx博客).
Gzip
Gzip(GNU-ZIP)是一种压缩技术,经压缩后的页面可能只有原大小的30%,大大减小了网络传输开销,浏览器加载网页的速度也会提升不少,但这项技术需要浏览器的配合(在服务端对网页进行压缩, 在浏览器对其解压并解析),由于现代浏览都支持很多种解压缩的方式(如Chrome: Accept-Encoding:gzip, deflate, sdch
), 因此浏览器方面不需要我们担心.
Nginx的gzip模块是内置的, 由ngx_http_gzip_module 模块实现, 可在nginx.conf中配置使用:
The ngx_http_gzip_module module is a filter that compresses responses using the “gzip” method. This often helps to reduce the size of transmitted data by half or even more.
指令
Context: http, server, location
, Gzip一共有9个指令可以设置:
指令 | 描述 |
---|---|
gzip on | off; |
Enables or disables gzipping of responses. |
gzip_buffers number size; |
Sets the number and size of buffers used to compress a response. By default, the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform. |
gzip_comp_level level; |
Sets a gzip compression level of a response. Acceptable values are in the range from 1 to 9(推荐压缩级别为6). |
gzip_disable regex ...; |
Disables gzipping of responses for requests with “User-Agent” header fields matching any of the specified regular expressions. |
gzip_min_length length; |
Sets the minimum length of a response that will be gzipped. The length is determined only from the “Content-Length” response header field. |
gzip_http_version 1.0 | 1.1; |
Sets the minimum HTTP version of a request required to compress a response(default 1.1). |
gzip_types mime-type ...; |
Enables gzipping of responses for the specified MIME types in addition to “text/html”. The special value “*” matches any MIME type (0.8.29). Responses with the “text/html” type are always compressed. |
gzip_vary on | off; |
Enables or disables inserting the “Vary: Accept-Encoding” response header field if the directives gzip, gzip_static, or gunzip are active. |
gzip_proxied [flag]; |
Enables or disables gzipping of responses for proxied requests depending on the request and response. The fact that the request is proxied is determined by the presence of the “Via” request header field. The directive accepts multiple parameters -> details |
实例-常用Gzip配置
http {
## ...
gzip on;
gzip_min_length 1024;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_types text/plain application/x-javascript application/javascript application/xml text/css ;
gzip_vary on;
## ...
}
为了使Nginx能够在全局范围内使用gzip,故将其放在
http
全局模块中.如果需要对各个虚拟主机区别对待,可在对应的server
块中添加自己的gzip指令.
通过以上Nginx服务器访问一个网页(前提: Content-Length
> 1024), 会看到静态资源文件的Response中新增了如下三个响应头:
Content-Encoding:gzip
Transfer-Encoding:chunked
Vary:Accept-Encoding
注意:
1. 由于图片/视频/音频之类文件压缩比率很小, 且压缩过程非常耗费CPU资源, 因此这类资源推荐不对其压缩.
2. 较小的文件压缩后很有可能会比原文件还大, 因此这类资源也推荐不对其压缩.
Expires
对于网站图片,尤其是新闻网站,图片一旦发布,改动的可能非常小.因此我们希望用户在第一访问之后,图片直接缓存在浏览器,而不再向服务端发送请求(不同于HTTP-304
-Not Modified), 且能够自定义缓存配置.这就用到了Nginx的expires
功能.
Syntax: expires [modified] time;
expires epoch | max | off;
Default:
expires off;
Context: http, server, location, if in location
- Enables or disables adding or modifying the “Expires” and “Cache-Control” response header fields provided that the response code equals 200, 201, 204, 206, 301, 302, 303, 304, or 307. A parameter can be a positive or negative time.
注意: 要确保服务器时间准确,如果服务器时间落后于实际时间,可导致缓存失效.
实例-图片缓存
- 配置图片缓存时间为一天:
location ~* (jpg|png|jpeg|gif)$ {
expires 1d;
}
通过以上Nginx服务器访问一个图片(如nginx.png),会看到图片的Response中添加了如下两个响应头:
Cache-Control:max-age=86400
Expires:Fri, 20 May 2016 12:26:11 GMT
再次刷新该URL, 在浏览器(如Chrome)中会看到这张图片来自本地缓存: