一、安装
1、nginx安装:
wget http://nginx.org/download/nginx-1.15.8.tar.gz
tar -zxvf nginx-1.15.8.tar.gz
cd nginx-1.15.8
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
#配置
#--prefix指定安装目录
#--with-http_ssl_module安装https模块
#creating objs/Makefile 代表编译成功
make && make install
#make编译
#make install安装
2、echo安装
先进入到nginx源码目录,如/usr/local/nginx-1.15.8
下载:wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz
解压:tar -zxvf v0.61.tar.gz
配置:
./configure --add-module=/usr/local/nginx-1.15.8/echo-nginx-module-0.61 --with-http_ssl_module --with-debug
编译&安装:
make && make install
需要注意的是:如果在使用location中使用echo命令的话,需要将default_type的值指定为text/plain;
二、Location
在图中,整个请求地址中包含“ip端口或域名”和“path路径”两个部分。其中nginx在路径匹配的时候,会把整个path去做匹配。
1、空类型的匹配
是指location就是一个“/”,如下图
2、一般匹配
是指除了精准匹配之外的其它的匹配。
在一般匹配中,会按照最长的匹配原则进行匹配,什么意思呢?
就是除了精准匹配的location,只要location们被path所包含,那么这些location们是参与匹配的,但是最后只是取了长度上最长的那个location了。但是有一个要求,被匹配中的所有的location的长度必须是小于请求路径中域名端口后面的一段path。如图:
但是需要注意的是,如果输入的path和location都没有匹配中,并且存在一个空值的location,那么还是会去匹配这个空的,如下图:
3、= 精准匹配
当uri部分完全匹配上了,才路由到该location中,并且直接返回,哪怕后面存在其它的一些正则的location,也不会再去匹配了。如图:
但是需要注意的是:精准匹配是不参与一般匹配的,如下图:
4、 ~ 不忽略大小的正则匹配
匹配规则如下图:
5、~* 忽略大小写的正则匹配
它的匹配规则同“~”
6、 ^~ 非正则匹配
匹配规则如下图:
7、优先级:
优先级流程图:
8、root(它不是命令,只是起到一个声明的作用,相当于java中的int、float.....等)
但是,如果上面图中不写 “root /xxx/xxx”的话,那么nginx就是去找默认目录,即“/usr/local/nginx/html”,如果是用自义的目录,那么就必须使用root 指定。在实际使用中最好使用绝对目录,而少用相对目录。
【注意】:root 后面跟的目录要不要“/”都一样
9、alias(它不是命令,只是起到一个声明的作用,相当于java中的int、float.....等)
10、反向代理: proxy_pass
需要注意的是:“/”是表示关闭的意思,可以从下面两个图理解。写法如下:
如这个图所示,图中说明在这种情况下proxy_pass中后面有无“/”的区别
如这个图如所示,图中说明在这种情况下proxy_pass中后面有无“/”的区别
【注意】:此处“/”关闭与否,只针对于ip+port而言的,如果ip+port后面跟了其它的东西(如127.0.0.1:8080/xxx),则有无“/”的效果是一样的,而ip+port后面没有跟其它的东西,则有无“/”的效果是不一样的。
这里总结一下:
如图,一个请求地址是由图中的几个部分组成。
1、如果location的如下图中:
那么真正代理后的请求地址为http://ip:端口/path1/path2。为什么是这样呢?
因为在此处的proxy_pass的最后没有写“/”,也就是没有关闭,所以就会把path1+path2拼接后一起代理到真实的服务器了,即
http://127.0.0.1:8080/locationpath/otherpath?param=xxoo
2、如果location如下图:
那么真正代理后的请求地址为http://ip:端口/path2。为什么是这样呢?
因为在此处的proxy_pass的最后有写“/”,也就是关闭,所以只会把path2代理到真实的服务器,即
http://127.0.0.1:8080/otherpath?param=xxoo
3、如图location如下图:
那么真正代理后的请求地址为http://ip:端口/projectname/path2。为什么是这样呢?
因为在此处的proxy_pass的端口后有写“/”,也就是关闭,所以只会把path2代理到真实的服务器。即
http://127.0.0.1:8080/projectname/otherpath?param=xxoo
11、upstream 负载均衡
如上面图中所示,“ttt”相当于是对被负载的服务器作统一管理而取的名称,server指的是向nginx说明它是一个服务器,weight是表示权重,也就是说在被反向代理的时候,nginx会去轮询”ttt”里面的服务器,有2/3的命中“192.168.1.10:8080”这个服务器,有1/3的命中“192.168.1.102:8080”这个服务器。如果访问url为“www.enjoy_4/upstream_test/xxxx”,那么最终发送后是http://192.168.1.10:8080/xxxx和http://192.168.1.102:8080/xxxx,如果不权重weight不指定的话,那么就相当于是weight = 1,也就是说均匀的各一次。一个.conf文件中可以有多个upstream配置
拓展一下,如下图:
结合这两张图,可以理解为:将upstream(ttt)里面指定的ip:port替换掉proxy_pass中指向的upstream(即上图中的“ttt”)
12、rewrite
语法 :
rewrite regex replacement [flag]; 其中regex-正则,replacement-替换后面的结果, flag-处理的标志
flag=【break/last/redirect/permanent】
^/ 表示进入location后无论是什么都是匹配的。
如/xx.js,那么这样总是报错的。
一个location中可以有多个rewrite
(1)redirect
permanent-也会和redirect一样的效果,只是一个是301重定向,一个是302重定向
(2)break;
如果rewrite后面没有被break打断的话,那么就有机会触发下一轮从上往下进行location的匹配,也就是需要将当前的location走完,然后再去匹配新的location了;但是使用last就会提前触发下一轮从上往下进行location匹配,也就是说不需要将当前的location走完,就去匹配新的location了。
对break的有无总结:
有则直接被打断,无论其后有没有其它的rewrite,也不再去匹配新的location了,若有root声明,就会去root声明的目录下找资源;
无则不会被打断,在当前的location中还是会依然自上往下走的,比如有在当前的location中写了多行rewrite,并且这些reswrite后均没 有break的话,则最后一行rewrite生效,若有root声明,也不会去root声明的目录下找资源,而是离开当前的location,去新的location 中做匹配。
流程图如下:
还需要注意一点的是rewrite不仅可以写在location里面,还可以写在location外面,也可以实现对域名作重定向。如下图:
什么意思呢? 也就是说如果请求地址为:http://sales.enjoy.com,最后会跳转到https://sales.enjoy.com
13、index命令的执行时机
url 以 /结尾时,如:http://location.enjoy.com/static/,指的是一个目录,nginx认为用户没有指定文件, 所以会触发index指令,找到页面。
url 不是以 / 结尾,http://location.enjoy.com/static,认为它是个文件,尝试打开这个文件,此时index命令不启用,所以就会出现“301 Moved permanently”
14、执行阶段
三、日志![](https://img-blog.csdnimg.cn/2020051323122452.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zMjgyMjc1OQ==,size_16,color_FFFFFF,t_70)
四、其它知识要点
1、nginx内置变量
以下是常用的
$host:请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称
$http_HEADER : HTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,
-变为_(破折号变为下划线),例如:$http_user_agent(Uaer-Agent的值)
$remote_addr 客户端的IP地址。
$remote_port 客户端的端口。
$request_method 这个变量是客户端请求的动作,通常为GET或POST。
$request_uri 这个变量等于包含一些客户端请求参数的原始URI
$scheme 所用的协议,比如http或者是https
$server_name 服务器名称。
$request_filename 文件名称,对应的是url中的uri部分,如请求路径为“http://www.enjoy.com/static/a.html”,那么它对应的值就是“/static/a.html”。
$server_port 请求到达服务器的端口号。
$server_protocol 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$uri 请求中的当前URI(不带请求参数,参数位于$args)
常量输出,如下图:
2、If命令
nginx中只有if,没有else和else if。
If可以写在location之间,也可以写在location之后,还可以在location内部。
静态资源: location ~ /rex/.*\.(htm|js|css)$
域名校验:if ( $http_origin ~ http://(.*).enjoy.com)
浏览器校验:if ($http_user_agent ~ Firefox)
具体用法如下图:
3、跨域
解决跨域的办法为在.conf文件中加入以下内容,一个固定的写法:
if ( $host ~ (.*).enjoy.com){
set $domain $1;##记录二级域名值
}
#是否允许请求带有验证信息
add_header Access-Control-Allow-Credentials true;
#允许跨域访问的域名,可以是一个域的列表,也可以是通配符*,也可以具体的几个域名,使用空格连接
add_header Access-Control-Allow-Origin http://static.enjoy.com; #表示,只要是从这个指定的域名过来的请求,都能跨域请求
#允许脚本访问的返回头
add_header Access-Control-Allow-Headers 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp';
#允许使用的请求方法,以逗号隔开
add_header Access-Control-Allow-Methods 'POST,GET,OPTIONS,PUT,DELETE';
#允许自定义的头部,以逗号隔开,大小写不敏感
add_header Access-Control-Expose-Headers 'WWW-Authenticate,Server-Authorization';
#P3P支持跨域cookie操作
add_header P3P 'policyref="/w3c/p3p.xml", CP="NOI DSP PSAa OUR BUS IND ONL UNI COM NAV INT LOC"';
add_header test 1;
if ($request_method = 'OPTIONS') { ##OPTIONS类的请求,是跨域先验请求
return 204; #204代表ok
}