摘要:如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个,该将成为头部值。没有状态码的将被视为一个状态码,这种情况下需要以或者开头。因为和不能简单的只返回状态码,还必须有重定向的,这就是指令无法返回的原因了。
HTTP模块(核心模块,也是主要用到的模块) server模块
server模块是http的子模块,它用来定义一个虚拟主机
例子:
server { listen 80; server_name localhost www.example.com; root /Users/yangyi/www;# 全局定义,表示在该server下web的根目录 index index.php index.html index.htm; charset utf-8; access_log logs/host.access.log main; #用来指定此虚拟主机的访问日志存放路径,输出格式为main。 error_log logs/host.error.log error; #错误日志存放路径,输出格式为error。 error_page 404 /404.html; #状态码为404时的时候的网页地址,还可定义500,502之类的 .... }
以上一些配置为在该server下具有全局性,例如 root,可在location中重新定义root
关于server_name用来指定IP地址或者域名,多个域名之间用空格分开
当我们想定义多个server监听同一个端口但访问的host不一样时,server_name就派上用场了。nginx会根据HTTP请求的header Host选择nginx配置文件里符合条件的server_name的server配置
匹配顺序如下
完全匹配的server_name;
后缀匹配: *.example.com;
前缀匹配: www.example.*;
正则匹配: ~w+.com;
listen指令里配置了default或default_server的server;如`listen 80 default`
第一个匹配上listen的server。
所以当我们监听的的端口只有一个server配置的时候,server_name 可以不填
关于root和alias的区别两者作用差不多,区别在于最终映射的地址不同,例:
location /request_path/image/ { # 如果现在访问 /request_path/image/a/b.jpg,root映 # 射的地址为/local_path/image/request_path/image/a/b.jpg, # 而alias为/local_path/image/a/b.jpg root /local_path/image/; alias /local_path/image/; }关于error_page
语法:error_page code ... [=[response]] uri
使用字段: http, server, location, if in location
产生的效果为内部跳转(internal redirect),即用户页面地址不变,但内容实际上为设置的uri对应的内容
我们也可以自定义设置返回的状态码,如:
error_page 502 503 =200 /50x.html;
这样用户访问产生502 、503的时候给用户的返回状态是200,内容是50x.html。
还有一种写法是 = 后面不带状态码,是针对相应的内容不是一个静态的页面,最终返回的状态码取决于对应url服务返回的状态码。
最主要和最复杂的配置,通过定位和解析url,判断该选择什么配置,支持正则和条件判断;
简单例子,匹配所有请求
location / { root /home/www/html; index index.php index.html index.htm; }
一个正则匹配的例子:
# 匹配.php结尾的请求 location ~ .php$ { .... }
一个反向代理的例子:
# 匹配到/api开头的路由时候,将请求转发到http://192.168.0.1,但是通常不是直接填写地址,而是设置一个`upstream`配置,后面会提到 location /api { proxy_pass http://192.168.0.1; #请求转向地址192.168.0.1 #不修改被代理服务器返回的响应头中的location头 proxy_redirect off; #使用nginx反向代理后,如果要使服务获取真实的用户信息,用以下的设置 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
vue-router、react-router等路由框架要开启history模式可以选择的nginx配置的例子
location / { alias static/; try_files $uri $uri/ /index.html; }
location的匹配规则和顺序
第一种是 = 类型,表示精确匹配,优先级最高,一旦匹配到忽略之后的正则匹配
^~ 类型,表示前缀匹配,是字符串开头匹配而非正则匹配,当匹配到该规则时,停止往下面的搜索,所以如果存在两个^~ 匹配的时候要注意有顺序之分。优先级比正则高。
~ 和 ~*,正则匹配,两者区别是后者不区分大小写。有顺序之分,匹配到第一个正则停止搜索。
/uri,普通字符串匹配,无顺序之分,会选择匹配长度最长的配置。
/ 通用匹配,匹配所有请求
还有一种特殊匹配类型 @url,只用于nginx内部跳转,例:
location / { root /var/www/html; error_page 404 @40x; } location @40x { root /var/www/errors/40x.html; }upstream模块
upstream后端服务器提供简单的负载均衡(轮循调度和客户端 IP)。
例子:
upstream backend { server backend1.example.com weight=5; server backend2.example.com:8080; server unix:/tmp/backend3; } server { location / { proxy_pass http://backend; } }
有常用两种负载均衡支持调度算法,分别是 weight 和 ip_hash 。weight 模式下可以为每个 server 设置weight值,weight值越大,分配到的访问机率越高,ip_hash 为同一个ip的
分配同一个后端服务器,这样我们不用解决session共享问题。
include指令 使nginx配置更加灵活,将部分配置直接拆分出来,分成不同的配置文件
例子:
http { include mime.types; include vhost/*.conf; # 虚拟主机配置 }关于 mime.types:
mime type 和 文件扩展名的对应关系一般放在 mime.types 里,然后 用 include mime.types;
mime.types作用:通过文件的扩展名设置了Content-Type,Nginx如果没找到对应文件的扩展名的话,就使用默认的Type,默认Type通用 default_type 定义,比如 default_type application/octet-stream ;
完整的 mime.types 配置:https://github.com/h5bp/server-configs-nginx/blob/master/mime.types
一个虚拟主机对一个文件配置,放到vhost文件夹下面,然后通过include指令包含进来,这样更便于维护和管理
gzipgzip 压缩,用来对静态资源进行压缩,需要客户端同时支持才有效。
配置:
http { #开启gzip压缩 gzip on; #IE6的某些版本对gzip的压缩支持很不好,故关闭 gzip_disable "MSIE [1-6].(?!.*SV1)"; #HTTP1.0以上的版本都启动gzip gzip_http_version 1.0; #指定哪些类型的相应才启用gzip压缩,多个用空格分隔 gzip_types application/javascript application/json text/css text/plain; # 压缩等级,可选1-9,值越大压缩时间越长压缩率越高, # 通常选5,能压缩到原来的1/4 gzip_comp_level 5; }rewrite模块(ngx_http_rewrite_mode)
rewrite模块配合很多模块一起使用,包含几个指令:
break
if
return
rewrite
rewrite_log
set
uninitialized_variable_warn
这里简单介绍下break、if、return,重点介绍 rewrite
break语法: break;
使用字段: server, location, if
此指令的意思是停止执行当前虚拟主机的后续rewrite指令集
例子
# 如果访问的文件名不存在,反向代理到localhost 。这里的break也是停止rewrite检查 if (!-f $request_filename) { break; proxy_pass http://127.0.0.1; }if
语法: if (condition) { ... }
使用字段: server, location
if 判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。
条件(conditon)可以是如下任何操作:
当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false;
使用“=”和“!=”比较一个变量和字符串;
使用“~”做正则表达式匹配,“~*”做不区分大小写的正则匹配,“!~”做区分大小写的正则不匹配;
使用“-f”和“!-f” 检查一个文件是否存在;
使用“-d”和“!-d”检查一个目录是否存在;
使用“-e”和“!-e”检查一个文件、目录、符号链接是否存在;
使用“-x”和“ !-x”检查一个文件是否可执行;
# 如果提交方法为POST,则返回状态405(Method not allowed) if ($request_method = POST) { return 405; }return
语法: return code [text];
return code URL;
return URL;
使用字段: server, location, if
停止处理并为客户端返回状态码,非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头部值。没有状态码的URL将被视为一个302状态码,这种情况下URL需要以“http://”, “https://”, 或者 “$scheme”开头。
语法: rewrite regex replacement [flag];
使用字段: server, location, if
使用nginx提供的全局变量或自己设置的变量,然后结合正则表达式和标志位实现url重写以及重定向。多条 rewrite 顺序靠前且匹配的优先执行。可以通过设置 flag 停止继续处理。如果replacement 以“http://”, “https://”, 或者 “$scheme”开头,那么将立即停止处理并临时重定向给客户端。
flag可以是如下参数:
last,完成该rewrite规则的执行后,停止处理后续rewrite指令集;然后查找匹配改变后URI的新location;
break,完成该rewrite规则的执行后,停止处理后续rewrite指令集,并不再重新查找;但是当前location内剩余非rewrite语句和location外的的非rewrite语句可以执行;
redirect,返回302临时重定向,地址栏会显示跳转后的地址;
permanent,返回301永久重定向,地址栏会显示跳转后的地址;即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。
因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。两种重定向的方式对客户端来说是一样的,就是重新加载另外一个url。我们在实际设置中推荐只使用永久重定向,因为临时重定向可能造成在url为A页面,但显示的是B页面的内容,造成网址劫持。
比较难以理解的是 last 和 break,让我们先了解 nginx 运行的11个阶段,注意到第四阶段:
typedef enum { NGX_HTTP_POST_READ_PHASE = 0, //读取请求头 NGX_HTTP_SERVER_REWRITE_PHASE, //执行rewrite NGX_HTTP_FIND_CONFIG_PHASE, //根据uri替换location NGX_HTTP_REWRITE_PHASE, //根据替换结果继续执行rewrite NGX_HTTP_POST_REWRITE_PHASE, //执行rewrite后处理 NGX_HTTP_PREACCESS_PHASE, //认证预处理 请求限制,连接限制 NGX_HTTP_ACCESS_PHASE, //认证处理 NGX_HTTP_POST_ACCESS_PHASE, //认证后处理, 认证不通过, 丢包 NGX_HTTP_TRY_FILES_PHASE, //尝试try标签 NGX_HTTP_CONTENT_PHASE, //内容处理 NGX_HTTP_LOG_PHASE //日志处理 } ngx_http_phases;
所以我们再来理解last与break的区别:
last: 停止当前这个请求,并根据rewrite匹配的规则重新发起一个请求。新请求又从第一阶段开始执行…
break:相对last,break并不会重新发起一个请求,只是跳过当前的rewrite阶段,并执行本请求后续的执行阶段…
通过实例会更加清晰的理解
server { listen 80 default_server; server_name dcshi.com; root www; location /break/ { rewrite ^/break/(.*) /test/$1 break; echo "break page"; } location /last/ { rewrite ^/last/(.*) /test/$1 last; echo "last page"; } location /test/ { echo "test page"; } }
请求:http://dcshi.com/break/*
输出: break page
分析:正如上面讨论所说,break是跳过当前请求的rewrite阶段,并继续执行本请求的其他阶段,很明显,对于/foo 对应的content阶段的输出为 echo “break page”; (content阶段,可以简单理解为产生数据输出的阶段,如返回静态页面内容也是在content阶段;echo指令也是运行在content阶段,一般情况下content阶段只能对应一个输出指令,如同一个location配置两个echo,最终只会有一个echo指令被执行);当然如果你把/break/里的echo 指令注释,然后再次访问/break/xx会报404,这也跟我们预期一样:虽然/break/xx被重定向到/test/xx,但是break指令不会重新开启一个新的请求继续匹配,所以nginx是不会匹配到下面的/test/这个location;在echo指令被注释的情况下,/break/ 这location里只能执行nginx默认的content指令,即尝试找/test/xx这个html页面并输出起内容,事实上,这个页面不存在,所以会报404的错误。
请求: http://dcshi.com/last/*
输出: test page
分析: last与break最大的不同是,last会重新发起一个新请求,并重新匹配location,所以对于/last,重新匹配请求以后会匹配到/test/,所以最终对应的content阶段的输出是test page;
解释完了 last 和 break ,我们再写一个实例用来说明 rewrite 可以做什么事情。通过rewrite将不带www的请求统一转向为www:
server { # ........ server_name www.abc.com ;//只留一个 # ...... } server { server_name abc.com; rewrite ^(.*)$ http://www.abc.com$1 permanent; }
或者是:
server { listen 80; server_name abc.com www.abc.com; if ( $host != "www.abc.com" ) { rewrite ^/(.*) http://www.abc.com/$1 permanent; } location / { root /data/www/www; index index.html index.htm; } }
参考:
http://tool.oschina.net/apidocs/apidoc?api=nginx-zh
https://www.jianshu.com/p/bed000e1830b
http://blog.sina.com.cn/s/blog_4f9fc6e10102ux0w.html
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/39895.html
摘要:既然是从零开始,那么就把作为统一的安装工具。下面附上安装方法安装好之后,就可以开始搭建环境了。环境安装比较简单安装好之后,首先要启动服务。和一起安装,我们先去安装,再做相关配置。成功解析还差一步,就是修改配置文件。 既然是从零开始,那么就把 homebrew 作为统一的安装工具。如果你不知道 homebrew 是什么东东,移步这里。下面附上 homebrew 安装方法: /usr/bi...
摘要:既然是从零开始,那么就把作为统一的安装工具。下面附上安装方法安装好之后,就可以开始搭建环境了。环境安装比较简单安装好之后,首先要启动服务。和一起安装,我们先去安装,再做相关配置。成功解析还差一步,就是修改配置文件。 既然是从零开始,那么就把 homebrew 作为统一的安装工具。如果你不知道 homebrew 是什么东东,移步这里。下面附上 homebrew 安装方法: /usr/bi...
摘要:在时间段内,日志文件最少使用几次,该日志文件描述符记入缓存,默认是次。例子中,设置缓存最多缓存个日志文件描述符,内如果缓存中的日志文件描述符至少被被访问次,才不会被缓存关闭。每隔分钟检查缓存中的文件描述符的文件名是否还存在。 前言 Nginx日志对于统计、系统服务排错很有用。Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志)。通过访问日志我们可...
摘要:买了一个服务器,系统是做了一番基础设置,在此记录一下。安装成功后重启服务。我采用源码编译的方式安装默认安装到,可以通过指定安装目录。几个常用的命令启动停止 买了一个服务器,系统是CentOS7.2 .做了一番基础设置,在此记录一下。 更新 yum 源仓库 yum update 安装 Git yum 源仓库里最新版本的 Git 是 1.8.3.1,但是官方最新版本已经到了 2.9.2。想...
阅读 2465·2021-09-09 09:33
阅读 2865·2019-08-30 15:56
阅读 3118·2019-08-30 14:21
阅读 890·2019-08-30 13:01
阅读 854·2019-08-26 18:27
阅读 3583·2019-08-26 13:47
阅读 3449·2019-08-26 10:26
阅读 1583·2019-08-23 18:38