当我们以 http://172.17.0.2:8080/a/b/c.html 访问nginx时
首先nginx会根据172.17.0.2:8080定位虚拟主机,剩余部分/a/b/c.html,我们将其称为path
然后nginx再去匹配location,如果匹配中/a,则称/a,为path1
剩余部分/b/c.html,则称/b/c.html,为path2
了解了什么是path,什么是path1,什么是path2后,此时如果我们使用root声明
location /a {
root html/;
}
表示在root指定的html/目录下找path1+path2,即path=/a/b/c.html
而如果我们使用alias 声明
location /a {
alias html/;
}
表示在alias指定的html/目录下找path2,即找/b/c.html
这就是这两个声明的区别
当我们使用root声明和alias声明时,常常也会使用到index命令
location /a {
alias html/;
index aa.html;
}
什么时候会触发index命令呢?
url 以 “/” 结尾时,如:http://172.17.0.2:8080/a/,指的是一个目录,nginx认为用户没有指定文件,会访问index指定的文件aa.html
url 不是以 “/” 结尾,http:/172.17.0.2:8080/a,认为它是个文件,尝试打开这个文件,此时index命令不启用
将请求路径转给第三方
location /a {
proxy_pass http://172.17.0.3:8080/;
}
注意:尾部的“/”很重要,,注意和index命令时的“/”进行区分
当我们以http://172.17.0.2:8080/a/b/c.html访问nginx时
如果没有“/”,我们传给第三方的是path1+path2,即访问http://172.17.0.3:8080/a/b/c.html
如果有“/”,我们传给第三方的是path2,即访问http://172.17.0.3:8080/b/c.html
作用:替换请求路径
语法:rewrite regex replacement [flag];
其中,flag=【break/last/redirect/permanent/不写】有五种选择
regex 是正则表达式
replacement 是替换值,新值
flag -- 是处理标志
举例:
当我们以http://rewrite.enjoy.com/aa.html 去请求nginx
命中了/aa.html的location , 所以path=aa.html
如果没有rewirte命令或者没有被rewirte的正则匹配中,应该根据root声明在html/static文件夹下查找aa.html
但是这里被rewrite正则匹配命中,则修改为path = /a.html,变成了在html/static文件夹下查找a.html
(若不命中则不执行rewrite语句。正则 ^/ 表示:总是匹配)
这里和servlet里面的内部重定向非常类似,浏览器的请求路径不会发生变化
注意,此时flag=break,之前提过flag有五种选择
接下来介绍每一个的作用:
如果rewrite命中,发起页面重定向,浏览器的请求路径会发生变化
redirect和permanent之间的区别在于,redirect是301重定向,permanent是302重定向
并且注意:一旦执行了页面重定向,rewrite后面的代码不会执行
如果rewrite命中,发起内部重定向,替换path值
break标记:rewrite命中后,停止执行后续命令。和for(){break}非常类似
last标记:rewrite命中后,停止执行后续命令,并引发location重新匹配。和for(){continue;}非常类似
注意:不要轻易使用last标签,很容易死循环
当没有flag值的时候,rewrite还会往下走,如果rewrite命令有多个,最后一个rewrite覆盖前面的,再引发location重匹配
负载均衡配置,通过该命令,nginx可以把请求发给不同的tomcat,发送方式有三种:轮询,权重,ip
1、轮询(默认)
upstream myProtectUpstream {
server 172.17.0.4:8081;
server 172.17.0.5:8081;
}
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。down 暂时不参与负载
例如:
upstream myProtectUpstream {
server 172.17.0.4:8081 weight=2;
server 172.17.0.5:8081 weight=1;
}
2、ip_hash
每个请求按访问ip的hash结果分配,这样同一客户端的请求总是发往同一个后端服务器,可以解决session的问题。
upstream myProtectUpstream {
ip_hash;
server 172.17.0.4:8081;
server 172.17.0.5:8081;
}
举例:
upstream myProtectUpstream {
server 172.17.0.4:8081 weight=2;
server 172.17.0.5:8081 weight=1;
}
server {
listen 80;
server_name www.enjoy.com;
location /myProtect {
proxy_pass http://myProtectUpstream;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
通过upstream配置,nginx就可以按照发送方式,将对应的请求发给不同的tomcat
nginx为我们提供很多内置的变量,方便我们使用,这里列举几个常用的
$host | 请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称 |
$remote_addr | 客户端的IP地址 |
$remote_port | 客户端的端口 |
$request_method | 这个变量是客户端请求的动作,通常为GET或POST。 |
$request_uri | 这个变量等于包含一些客户端请求参数的原始URI $scheme 所用的协议,比如http或者是https |
nginx提供了if语句,但是没有提供else
= ,!= |
比较的一个变量和字符串。 |
~, ~* |
与正则表达式匹配的变量,如果这个正则表达式中包含 |
-f,!-f |
检查一个文件是否存在。 |
-d, !-d |
检查一个目录是否存在。 |
-e,!-e |
检查一个文件、目录、符号链接是否存在。 |
-x, !-x |
检查一个文件是否可执行 |
常用正则去判断一些条件,比如:判断客户端的请求是否以php结尾
这些if判断是写在location之前,所以如果客户端的请求是以php结尾,会直接返回502错误
再比如:判断某个文件是否存在
如果不存在,返回414错误
问题来源:浏览器拒绝执行其它域名下的ajax操作
问题举例:
1、首先我们访问域名为 www.test.com 的服务器,该服务器返回了html
2、 www.test.com 服务器返回的html内容中,存在一个ajax,该ajax操作访问另一个域名 www.test2.com
此时,浏览器拒绝执行www.test2.com服务器返回的内容
问题解决方案:cors跨域,是w3c组织制定的解决方案。为目前主流方案
问题解决原理:
1、当浏览器发现ajax请求的网址,与当前主域名不一致(跨域)时,会在请求header中追加主域名值,即:origin = http://www.test.com
2、nginx在接收到ajax请求时,会查看origin值,即请求我的网址是谁?
此处使用正则来校验,满足nginx正则要求的网站才允许访问我
返回信息时,nginx追加header值:access-control-allow-origin = http://www.test.com(回答浏览器,该域名网址可以访问我)
3、浏览器收到ajax返回值后,查看返回的header中access-control-allow-origin的值,发现其中的值是正是当前的页面主域名。表明允许访问,于是执行ajax返回值内容。(ps:若此处access-control-allow-origin不存在,或者值不是页面主域名,chrome就拒绝执行返回值)
目的:
1、让资源只能在我的页面内显示
2、不能单独下载
解决方式:
1、chrome以url1首次请求web服务器,得到html页面。
2、chrome再次发起url2资源请求,携带referers = url1。(注意,是url1,不是本次的url2)
3、nginx校验referers值,决定是否允许访问。
4、下面是nginx校验referers值的过程:
valid_referers:匹配域名白名单,如果不匹配,把内置变量$invalid_referers置为1,进入if块,返回404
浏览器请求的图片可以缓存一定时间,减少资源的浪费,我们只需要使用expires命令即可
expires命令:过期时间