Nginx 安装和配置大全
CentOS 版本
nginx 安装
nginx 安装:
yum -y install openssl
yum -y install zlib
yum -y install pcre
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install nginx
service nginx start
NginX - 响应时间计算与日志输出格式修改
参考: https://www.cnblogs.com/JustBeZero/p/9441413.html
日志输出配置
默认调用 combined 格式:
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" ';
Nginx 也允许自定义日志格式,例如:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$request_time"';
输出日志时,还需明确指定调用自定义格式名(示例中为 main):
access_log logs/access.log main;
时间计算属性
主要涉及以下两个属性值,可根据需要应用计算:
request_time
官网描述
request processing time in seconds with a milliseconds resolution; time elapsed between the first bytes were read from the client and the log write after the last bytes were sent to the client.
应用释义
该属性计算的是从接收到用户发送请求中的第一个字节到发送完完整响应数据的时间;
可粗略理解为:request_time = 接收请求数据时间 + 后端服务响应时间 + 输出响应数据时间
upstream_response_time
官网描述
keeps times of responses obtained from upstream servers; times are kept in seconds with a milliseconds resolution. Several response times are separated by commas and colons like addresses in the $upstream_addr variable.
应用释义
该属性计算的是从 Nginx 与后端服务建立连接到接收完数据关闭连接的时间;
可粗略理解为: 后端服务响应时间(略去 Nginx 与后端服务之间的数据传输时间)
time_local
日志输出时间
重定向 URI
location 指令语法
location [=||*|^~|@] /uri/ { … }
或 location @name { … }
Nginx 路径匹配符号
= 表示精确匹配
^~ 表示 uri 以某个常规字符串开头,大多情况下用来匹配 url 路径,nginx 不对 url 做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa 匹配到(注意是空格)。
~ 正则匹配(区分大小写)
~* 正则匹配(不区分大小写)
!和!*分别为区分大小写不匹配及不区分大小写不匹配的正则
/ 任何请求都会匹配
符号的优先级
首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
URI 匹配模式
location 指令分为两种匹配模式:
- 普通字符串匹配:以=开头或开头无引导字符(~)的规则
- 正则匹配:以~或~*开头表示正则匹配,~*表示正则不区分大小写
location URI 匹配规则
当 nginx 收到一个请求后,会截取请求的 URI 部份,去搜索所有 location 指令中定义的 URI 匹配模式。在 server 模块中可以定义多个 location 指令来匹配不同的 url 请求,多个不同 location 配置的 URI 匹配模式,总体的匹配原则是:先匹配普通字符串模式,再匹配正则模式。只识别 URI 部份。
一个请求过来后,Nginx 匹配这个请求的流程如下:
- 先查找是否有=开头的精确匹配,如:location = /test/abc/user.do { … }
- 再查找普通匹配,以 最大前缀 为原则,如有以下两个 location,则会匹配后一项
location /test/ { … }
location /test/abc { … } - 匹配到一个普通格式后,搜索并未结束,而是暂存当前匹配的结果,并继续搜索正则匹配模式
- 所有正则匹配模式 location 中找到第一个匹配项后,就以此项为最终匹配结果。所以正则匹配项匹配规则,受定义的前后顺序影响,但普通匹配模式不会。
- 如果未找到正则匹配项,则以 3 中缓存的结果为最终匹配结果。
- 如果一个匹配都没搜索到,则返回 404。
精确匹配与模糊匹配差别
location =/ { … }
与 location / { … }
的差别:
前一个是精确匹配,只响应/请求,所有 /xxx
或 /xxx/xxxx
类的请求都不会以前缀的形式匹配到它。
后一个是只要以 / 为前缀的请求都会被匹配到。如:/abc , /test/abc, /test/abc/aaaa
正则与非正则匹配
location ~ /test/.+.jsp$ { … }
:正则匹配,支持标准的正则表达式语法。location ^~ / { … }
: ^~意思是关闭正则匹配,当搜索到这个普通匹配模式后,将不再继续搜索正则匹配模式。
Rewrite 用法
rewrite regex replacement [flag];
如果相对域名或参数字符串起作用,可以使用全局变量匹配,也可以使用 proxy_pass 反向代理。
从上表明看 rewrite 和 location 功能有点像,都能实现跳转。主要区别在于 rewrite 是在同一域名内更改获取资源的路径,而 location 是对一类路径做控制访问或反向代理,可以 proxy_pass 到其他机器。
很多情况下 rewrite 也会写在 location 里,它们的执行顺序是:
- 执行 server 块的 rewrite 指令
- 执行 location 匹配
- 执行选定的 location 中的 rewrite 指令
如果其中某步 URI 被重写,则重新循环执行 1-3,直到找到真实存在的文件;循环超过 10 次,则返回 500 Internal Server Error 错误。
rewrite 语法格式
rewrite <regex> <replacement> <flag>;
关键字 正则表达式 代替的内容 重写类型
Rewrite:一般都是 rewrite
Regex:可以是字符串或者正则来表示想要匹配的目标 URL
Replacement:将正则匹配的内容替换成 replacement
Flag:flag 标示,重写类型:
- last:本条规则匹配完成后,继续向下匹配新的 location URI 规则;相当于 Apache 里德(L) 标记,表示完成 rewrite,浏览器地址栏 URL 地址不变;一般写在 server 和 if 中;
- break:停止执行当前虚拟主机的后续 rewrite 指令集。本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏 URL 地址不变;一般使用在 location 中;
- redirect:返回 302 临时重定向,浏览器地址会显示跳转后的 URL 地址;
- permanent:返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址;
因为 301 和 302 不能简单的只返回状态码,还必须有重定向的 URL,这就是 return 指令无法返回 301,302 的原因了。
这里 last 和 break 区别有点难以理解:
- last 一般写在 server 和 if 中,而 break 一般使用在 location 中
- last 不终止重写后的 url 匹配,即新的 url 会再从 server 走一遍匹配流程,而 break 终止重写后的匹配
- break 和 last 都能组织继续执行后面的 rewrite 指令
server {
# 访问 /last.html 的时候,页面内容重写到 /index.html 中,并继续后面的匹配,浏览器地址栏 URL 地址不变
rewrite /last.html /index.html last;
# 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配,浏览器地址栏 URL 地址不变;
rewrite /break.html /index.html break;
# 访问 /redirect.html 的时候,页面直接 302 定向到 /index.html 中,浏览器地址 URL 跳为 index.html
rewrite /redirect.html /index.html redirect;
# 访问 /permanent.html 的时候,页面直接 301 定向到 /index.html 中,浏览器地址 URL 跳为 index.html
rewrite /permanent.html /index.html permanent;
# 把 /html/*.html => /post/*.html ,301 定向
rewrite ^/html/(.+?).html$ /post/$1.html permanent;
# 把 /search/key => /search.html?keyword=key
rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
# 把当前域名的请求,跳转到新域名上,域名变化但路径不变
rewrite ^/(.*) http://www.jd.com/ $1 permanent;
}
IF 判断
if (表达式) {
}
对给定的条件 condition 进行判断。如果为真,大括号内的 rewrite 指令将被执行,if 条件(conditon) 可以是如下任何内容:
当表达式只是一个变量时,如果值为空或任何以 0 开头的字符串都会当做 false
直接比较变量和内容时,使用=或!=
~ 正则表达式匹配
~* 不区分大小写的匹配
!~ 区分大小写的不匹配
-f 和!-f 用来判断是否存在文件
-d 和!-d 用来判断是否存在目录
-e 和!-e 用来判断是否存在文件或目录
-x 和!-x 用来判断文件是否可执行
#当表达式只是一个变量时,如果值为空或任何以 0 开头的字符串都会当做 false 直接比较变量和内容时,使用=或!=~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配
#判断访问地址
if ($remote_addr = 192.168.1.100) {
return 403;
}
#判断访问的是否 ie;
if ($http_user_agent ~ MSIE) {
rewrite ^.*$ /ie.htm;
break; #不 break 会循环重定向(是 ie 重写到 ie.htm,然后又发现是 ie,又重写到 ie.htm...)
}
如果用户设备为 IE 浏览器的时候,重定向
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果 UA 包含"MSIE",rewrite 请求到/msid/目录下
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} //如果 cookie 匹配正则,设置变量$id 等于正则引用部分
if ($request_method = POST) {
return 405;
} //如果提交方法为 POST,则返回状态 405(Method not allowed)。return 不能返回 301,302
if ($slow) {
limit_rate 10k;
} //限速,$slow 可以通过 set 指令设置
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1 ;
} //如果请求的文件名不存在,则反向代理到 localhost 。这里的 break 也是停止 rewrite 检查
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果 query string 中包含"post=140",永久重定向到 example.com
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.comwww.leizhenfang.com ;
if ($invalid_referer) {
return 404;
} //防盗链
}
# 示例 1:不存在的文件跳到 404.html
#跳转到 404
if (!-e $document_root$fastcgi_script_name) {
rewrite ^.*$ /404.html;
break;
}
/*
要加 break,以 xx.com/dsafsd.html 这个不存在页面为例,我们观察访问日志, 日志中显示的访问路径,依然是 GET /dsafsd.html HTTP/1.1
提示: 服务器内部的 rewrite 和 302 跳转不一样.302 跳转 url 会改变,变成重新 http 请求 404.html, 而内部 rewrite, 上下文没变,
就是说 fastcgi_script_name 仍然是 dsafsd.html,因此会循环重定向.
*/
# 示例 2:在不使用 break 的情况下,对 ie 访问进行重写
if ($http_user_agent ~* msie) { //如果是 ie 访问的话设变量为 1;
set $isie 1;
}
if ($fastcgi_script_name = ie.html) { //如果访问的脚本为 ie.html,变量为 0;
set $isie 0;
}
if ($isie 1) { //综合起来,如果 ie 访问的是 ie.html 这个脚本就不重写;
rewrite ^.*$ ie.html;
}
# 示例 3:目录自动加/
if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
用(1) 匹配最后一个非'/'的字符,然后自己强行再添加一个'/'($2 变量后的那个)
# 示例 4:Nginx 防盗链
location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
valid_referers none blocked *.nixi8.com nixi8.com localhost 192.168.42.188; #定义 none(空,直接访问),blocked(被防火墙标记过的来路),nixi8.com 的二级域名和一级域名,localhost,192.168.42.188
if ($invalid_referer) { # 如果不是上面定义的其中一个
rewrite ^/ http://www.nixi8.com/none.gif ; # 就重写到一张 gif 图片上;
return 412;
break;
}
access_log off; # 关闭日志,降低服务器的损耗
root /opt/lampp/htdocs/web;
expires 3d;
break;
}
# 示例 5:隐藏 index.php
apache 下只要在全局配置文件中设置了缺省首页 index.php 就能实现直接到达 index.php,但是 nginx 目前默认情况下只能到达 index.html 而不能访问到 index.php,所以只好 rewrite 重写使其支持
if (-f $request_filename) { //使其不隐藏 index.php 的时候也能访问到
expires max;
break;
}
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 last;
}
内置全局环境变量
$args :这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的 Content-length 字段。
$content_type : 请求头中的 Content-Type 字段。
$document_root : 当前请求在 root 指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端 agent 信息
$http_cookie : 客户端 cookie 信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为 GET 或 POST。
$remote_addr : 客户端的 IP 地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过 Auth Basic Module 验证的用户名。
$request_filename : 当前请求的文件路径,由 root 或 alias 指令与 URI 请求生成。
$scheme : HTTP 方法(如 http,https)。
$server_protocol : 请求使用的协议,通常是 HTTP/1.0 或 HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始 URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前 URI,$uri 不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri 相同。
例子:
URL: http://localhost:81/download/stat.php?id=1585378&web_id=1585378
Server_Dir:/var/www/html
$host:localhost
$server_port:81
$request_uri:/download/stat.php?id=1585378&web_id=1585378
$document_uri:/download/stat.php
$document_root:/var/www/html
$request_filename:/var/www/html/download/stat.php
# 如果文件不存在则返回 400
if (!-f $request_filename) {
return 400;
}
# 如果 host 是 www.360buy.com ,则 301 到 www.jd.com 中
if ( $host != "www.jd.com" ){
rewrite ^/(.*)$ https://www.jd.com/ $1 permanent;
}
# 如果请求类型是 POST 则返回 405,return 不能返回 301,302
if ($request_method = POST) {
return 405;
}
# 如果参数中有 a=1 则 301 到指定域名
if ($args ~ a=1) {
rewrite ^ http://example.com/ permanent;
}
- 文件名及参数重写
location = /index.html {
# 修改默认值为
set $name test;
# 如果参数中有 name=xx 则使用该值
if ($args ~* name=(\w+?)(&|$)) {
set $name $1;
}
# permanent 301 重定向
rewrite ^ /$name.html permanent;
}
- 隐藏真实目录
server {
root /var/www/html;
# 用 /html_test 来掩饰 html
location / {
# 使用 break 拿一旦匹配成功则忽略后续 location
rewrite /html_test /html break;
}
# 访问真实地址直接报没权限
location /html {
return 403;
}
}
- 禁止指定 IP 访问
location / {
if ($remote_addr = 192.168.1.253) {
return 403;
}
}
- 如果请求的文件不存在,则反向代理到 localhost 。这里的 break 也是停止继续 rewrite
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1 ;
}
- 对/images/bla_500x400.jpg 文件请求,重写到/resizer/bla.jpg?width=500&height=400 地址,并会继续尝试匹配 location。
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;
反向代理 Proxy_Pass
Proxy_pass 反向代理,用的是 nginx 的 Proxy 模块。
第一种:
location /proxy/ {
proxy_pass http://127.0.0.1/ ;
}
代理到 URL: http://127.0.0.1/test.html
第二种:
location /proxy/ {
proxy_pass http://127.0.0.1 ; #少/
}
代理到 URL: http://127.0.0.1/proxy/test.html
第三种:
location /proxy/ {
proxy_pass http://127.0.0.1/aaa/ ;
}
代理到 URL: http://127.0.0.1/aaa/test.html
第四种(相对于第三种,最后少一个 / )
location /proxy/ {
proxy_pass http://127.0.0.1/aaa ;
}
代理到 URL: http://127.0.0.1/aaatest.html
- proxy_set_header Host $host; 作用 web 服务器上有多个站点时,用该参数 header 来区分反向代理哪个域名。比如下边的代码举例。
- proxy_set_header X-Forwarded-For $remote_addr; 作用是后端服务器上的程序获取访客真实 IP,从该 header 头获取。部分程序需要该功能。
Proxy_pass 配合 upstream 实现负载均衡
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
upstream core_tomcat {
server 192.168.1.253:80 weight=5 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 weight=1 max_fails=3 fail_timeout=30;
server 192.168.1.251:80 backup;
}
server {
listen 80;
server_name www.jd.com ;
location /web {
proxy_pass http://core _tomcat;
proxy_set_header Host $host;
}
}
}
Nginx 负载均衡的几种模式
轮询:每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,就不在分配;
upstream core_tomcat {
server 192.168.1.253:80 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 max_fails=3 fail_timeout=30;
}
权重轮询:根据后端服务器性能不通配置轮询的权重比,权重越高访问的比重越高;
upstream core_tomcat {
server 192.168.1.253:80 weight=2 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 weight=8 max_fails=3 fail_timeout=30;
}
# 假如有十个请求,八个会指向第二台服务器,两个指向第一台;
IP_Hash:根据请求的 ip 地址 hash 结果进行分配,第一次分配到 A 服务器,后面再请求默认还是分配到 A 服务器;可以解决 Session 失效重新登录问题;
upstream core_tomcat {
ip_hash;
server 192.168.1.253:80 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 max_fails=3 fail_timeout=30;
}
Fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配;
upstream core_tomcat {
fair;
server 192.168.1.253:80 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 max_fails=3 fail_timeout=30;
}
Url_hash:按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效;
upstream core_tomcat {
hash $request_uri;
server 192.168.1.253:80 max_fails=3 fail_timeout=30;
server 192.168.1.252:80 max_fails=3 fail_timeout=30;
}
配置访问静态资源
[root@localhost conf.d]# cat /etc/nginx/nginx.conf
#user nginx;
user root; ## 修改用户为 root,访问没有访问权限
[root@localhost conf.d]# cat /etc/nginx/conf.d/yyxz.conf
server {
listen 82;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
# 静态资源访问统一重定向到本机路径(所有 http://**/api/**.jpg 都会访问到/home/yyxz/yyxz/static/test/**.jpg)
location ~ /api/.*\.(jpg|png|xlsx)$ {
rewrite "^/api/(.*\.(jpg|png|xlsx))$" /$1 break;
root /home/yyxz/yyxz/static/test/;
}
# 指定静态资源访问
location /bianxh/ {
alias /home/yyxz/yyxz/static/test/;
#autoindex on; ## 是否开启路径访问
}
}
报错:
nginx -s reload
nginx: [error] invalid PID number "" in "/var/run/nginx.pid"
发生这个错误的原因是,nginx 读取配置文件时出错,需要指定一个特定的 nginx 配置文件,所以解决这个问题需要先执行
sudo nginx -c etc/nginx/nginx.conf
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: MySQL 编程规范
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论