开发者学堂课程【Nginx 企业级 Web 服务实战:Nginx location 基础使用、四层访问控制、账户认证及自定义日志路径】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/649/detail/10757
Nginx location 基础使用、四层访问控制、账户认证及自定义日志路径(一)
内容介绍
一、root 与 alias
二、location 的详细使用
三、匹配案例
四、Nginx 四层访问控制
五、nginx 账户认证功能
六、自定义错误界面
七、自定义访问日志
一、root 与 alias
本节讲的 nginx 偏向于技术性方面,是和配置相关的,nginx 服务相对是比较重要的,所以这个配置要学好。
nginx 在公司里的应用场合要远远大于287,在公司里目前应该很少用到287。
上次讲到 root 和 alias 的区别,讲了 root 是一个比较常用的方式,root 会用这样的方式来定义一些用户访问资源目录:会在用户访问的目录加 /data/nginx/html/pc 这个目录,比如访问 about,那就需要在 root 定义好的目录下面也就是这个绝对路径下面引入 about 目录
location/about {
root /data/nginx/html/pc
index index.html
}
如果没有 about 目录,找不着它就会报404,报错理由就是文件或者目录找不到。
2、alias 用处少一些,alias 只是定义一个别名,会把用户的请求重新类似于做301的跳转一样,跳 alias/data/nginx/html/pc
这个目录,并且把这个目录下的资源显示。
alias 一般很少用到,除非程序里已经写好了这样的目录,但不能动,更多的是四五级的目录变了,这个时候才有可能会用上,就是程序里写的路径不想动或者动不了,然后物理服务器或者虚拟机上所定义的资源路径发生变化了,这个时候才有可能会用到 alias,但这个时候一般会想办法把它换成 root。
因为 alias 配置难度和 root 差不多,但是 root 的利用率要高一些,所以偏向用好配置好管理的 root。
二、location 的详细使用
上次讲到基于 pc 端和移动端的演示,基于虚拟主机来实现的,这个几乎每个公司都有,本节接着这个讲,上面是一个 PC 端,一个移动端,写好之后主要用 PC 端的域名做演示,访问一下 www.magedu.net 这个域名,用这个域名做演示。
接下来讲 location 的详细使用,到目前为止还没有在里面写正则表达式,也就是在没有正则表达式的场景下,nginx 首先会把请求在多个 server 的多个 location 中选取一个匹配度最高的 uri,所以会优先访问到 nginx 的 server 端,也就是它一定会先看域名是哪个,请求域名然后再根据域名不同的路径返回不同的资源。
假如这是 nginx 的80端口,那到了这个80端口之后,再往后就是资源路径了,也就是 server name,它先判断是哪个server name,这个 server name 在一个按键上可以跑的几乎是无上限的,一个 nginx 可以配 n 个 server name,所以它会先看请求的是哪个 server name,如果是移动端那就交给移动端的 server name 处理,如果是 pc 端就交给 pc 端的 server name 处理。那么也就到了相应的配置文件中,先去取server name,然后再看请求的 uri,这个 uri 在请求的 body 头部里面也会有。
刷新一下请求,看 request 这个信息,这个域名 www.magedu.net 后面可以加内容,比如加 index.html,这是给这个域名加个文件,index.html 就是 uri,如果请求的后面有很长或者很多目录,它也会显示。
所以到了 nginx 之后,nginx 先把 server name 判断出来,然后到哪个 server name下面,再走就会请求到相应的 location,也就是所说的 uri 判断,在有的公司,location 会配得特别复杂。
假如请求的 uri 是这个,那么定一个 root,一般会配放到 data下的 nginx,然后是html 或者是 images 等等,可能放到不同的地方。
root/data/nginx/images
一个域名下面可以有多个内容,比如这个是 uri,也可以是图片资源 images 等等
location/image {
root/data/nginx/images
}
可以在 nginx 定义各种各样的资源,让它去各个地方找,这些资源就是这个宿主机上的 data下的 nginx,image,或者 uri,这些都是绝对路径,这里面放的内容有些是单独放在宿主机上的,可以理解为直接放到宿主机上,或者有一些是直接挂过去的,把一些资源挂到 data 下的 nginx 下的 image,这些可能是 NFS 或者是分布值存储或者是商业存储等等。这一个挂载可以在多个 nginx 的服务器共享,一个 nginx 要监听很多 server name 和 location,每个 nginx 服务器都要做相同的话本,以保证数据的一致性。
用户从前面访问过来,中间有个负载均衡以及防火墙,用户的访问先经过防火墙,然后再转到 LVS
然后再从别的均衡转换到它后面的各个 nginx 服务器,这个 nginx 服务器它一定能够找到不同用户访问到不同服务器的那些相同资源,并且能够同时找到。
如果想用 location,得按照官方的配置参数去做,它可以实现很多功能,也就是这个匹配 uri。
uri 是用户请求的字符串,也就是在请求头部里会加一个字符串,如果这个字符串访问到一个不存在的,比如访问 static:www.magedu.net.static.1.jpg,访问这个图片,但是这个图片不存在,看这个头部在 reques t里面,就匹配这个 uri,拿到 uri 之后,就可以对用户做一些重定向,也就是匹配用户域名后面的 web 文件路径,static.1.jpg 称为 uri,这是资源定位符,可以在服务器上定位这个资源的路径,然后再使用 location 模块当中的正则或者某些匹配方式做匹配,如果匹配成功,就接受搜索,并且给用户做返回,location 配置语法相对是比较复杂的。看官方文档,在nginx 这个文档里面,找到 location,location 后面有一些操作符,像 = | ~ | ~* |^~,在操作符后面再写 uri,然后在 uri 后面用大括号 { } 把动作括起来,这个动作里面有很多指令,可以写指令。配置的位置是在 server 里面或者 location 里面,一般在 server 里面。
示例:
location = / {
[configuration A]
}
location / {
[configuration B]
}
location /document/ {
[configuration C]
}
location = ^~/images {
[configuration D]
}
location = ~*\.(gif | jpg | jpeg)$ {
[configuration E]
’=’用在 uri 前面,是做精确匹配,不是赋值的。要求用户的 uri 和 [ | = | ~ | ~* |^~]这个地方指定的完全一样,如果匹配成功就不再往下搜索而是走下面 location 的操作符{ ~ }。
但是’=’一般用的最少,因为这个太精确了,无法保证用户请求的就是指定的那个资源,所以一般用的不多。
因为有一些是可以精确匹配的,比如 /index.html、/ index.jsp、/index.php,像这些首页文件,可以用’=’来匹配。如果访问的就是 jsp 或者 php,就不再往下处理了。
有多个 location 的时候,有可能会用到这样的加速,对网站首页的请求进行加速,就不再往其他 location 匹配了,否则它会一个一个 location 去找,没匹配就会继续找,直到匹配成功。但是有一种方式是直接匹配用户的 uri,如果用户请求的是首页,恰好等于 location,就直接选用不再往别的地方匹配了,这样可以节省 nginx 的处理性能,或者不让 nginx 再匹配其他的,不再做这些资源消耗了。
还有一个是波浪符’~’,波浪符也是用在 uri 前面的,表示[ | = | ~ | ~* |^~]会包含正常表达式,并且区分大小写,匹配结果是成功的,这个意思就以区分大小写的方式对用户的 uri 进行匹配,匹配成功之后再往后操作,这个区分大小写一般用的不多,一般会用下面不区分大小写的,因为那些电商的网站有程序生成的文件名,文件名是包含大小写的,有的时候还包含特殊字符,所以如果区分大小写就不容易处理了,以天猫为例,点检查,要重新刷新一下,之后就找电商的图片
这个图片名称包括 nginx 文件就做了多文件合并了,就是把两个文件的请求和一起了。
这个图片有大写有小写,还有数字和特殊字符,所以对于这种资源一般不区分大小写,这个图片是可以单独访问的,前提是拿到它的 uri 路径。
区分大小写就是访问这个图片,如果这个图片正好有大写有小写,那么就得精确写好绝对名称,这个绝对名称就是该大写大写,该小写小写,不能有任何的差异。不区分大小写就是在 nginx 这层匹配的时候,只要是字母相同就行,不管是大写的 a 还是小写的 a,只要是 a,就往定义的 root 里转,root 里就是定义的资源地址,转过去以后再有那些资源就会做返回。所以‘~’是区分大小写并且匹配, ~*是不区分大小写并且匹配,这两个都是匹配成功之后才往下执行,前面加‘!’的就是取反,比如‘~‘是区分大小写并且匹配,那么!~就是区分大小写并且不匹配,一般用的不多。一般都会明确声明匹配关系,然后只有在匹配成功之后才往这个动作里面转,!~这个可以理解为当前面所有的都没有匹配成功才往这里转。
还有一些其他的操作符,比如‘^~‘也是表示这个里面包含正当表达式,并且匹配以什么开头,这个开头有些是有路径的,像 static,这个就是有精彩资源,但是精彩资源有好几个,这个时候可以写多个 location,也可以 static1,static2,精彩资源一般都在 static 目录下面,要是不想写多个 static,那就写一个牟定开头,当访问location 时直接牟定这个开头,然后等于 static,到了这里就认为是符合这个判断方式的,然后往{ }里面转,可以把 root 放到根下 data 下的 images,然后在这下面放static1、static2 等等,就能匹配到了。
location ^~ /static {
root/data/images/;
}
或者写多个 location,location static1、static2,但是一般公司没有那么多 static,像一个集群里面跑数万个网站,也就五六个目录,用于区分各种各样的资源。
比如 static1 是 jsp 的,还有 static2,可能会放图片,包括 png、jpg、jpeg,然后static3 再放什么资源,有可能会这样分开。所以一般的公司可能只有两三个目录,有的公司甚至只有一个,他们是这样做的:在 static 目录下面再做一个子目录,比如放images、css,可能在一个目录里面就拆分了。
因为小文件太多,有可能是不用一个存储的,可能是多个存储,小文件太多就会占用大量的 inode,inode一旦被占完,存储上就写不了数据了。所以当小文件太多的时候,会把它拆放到多个存储上,不然太浪费 inode,因为小文件一般是上亿级别的。
这个的用处是匹配路径,动静分离居多,一部分用于和 tomcat 结合。
$用的频率比较大,主要用于动静分离,表示包含正则表达式并且匹配以什么结尾,这个结尾通常是匹配固定格式的结尾,比如做动静分离时,就是匹配用户请求的 uri,如果访问的是 CS 文件或者是 jpg 这样的图片格式文件,就做相应的处理。在处理时可以再写个 location,然后匹配一个结尾,这个结尾就放在根下*.jpg,在后面加$符,匹配是不是以$符结尾的
location/*.jpg $ {
}
这个地方可以写很多东西,可以写括号括起来,如果有多个可以用竖线隔开,可以再写 css,js 等等,请求什么名称都无所谓,只要一个结尾是这当中的其中一个,就往下走,把图片资源或者 js 资源放到什么地方,比如放在这:
location/*.(jpg | css | js) ${
root/data/static/
}
还有一个是反应线,反应线是做转义的。这个转义就是在写正则表达式的时候,它可能会包含一些特殊字符,这些特殊字符在正则表达式里面都有单独的含义。
比如在这个地方想让这个点就是一个点,那就加个反应线转义一下
location/* \.(jpg | css | js) ${
root/data/static/
}
否则它可能在正则表达上有个隐藏的含义,比如这个地方还有个问号
location/.?\.(jpg | css | js) ${
root/data/static/
}
要求文件名称是一个字符,那在\后面就是文件名称了,这样匹配出来后,一般就是从 a 到 Z 的一些字符,然后从0~9,什么名称都可以,但是它只有一个,然后后面的点用反应线转义,它就是一个点,就不是正则表达式当中的匹配关系了。所以这个反应线是一种转义的,有的时候需要转义一下。
*表示包含正则表达式并且代表任意长度的任意字符。