nginx进行转发代理的核心在于两处,一是入口,二是出口;入口就是url路径匹配识别对应的路径,出口就是转发映射对应的后台服务地址
**【1】 location 指令详解 **
我们的入口路径匹配识别都是在location模块实现的,所以我们要首先认识location支持的匹配模式。location支持2种匹配模式:精确匹配(普通匹配)和模糊匹配(正则匹配),总共以下几种呈现形式:
location简单实例如下:
location / {
root html;
#首页文件。以下按顺序匹配
index index.html index.htm;
}
location语法格式:
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
匹配模式
1. 全路径精确匹配 = , 不含正则表达式
= :精确匹配。用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。
进行uri的全路径精确匹配,要匹配的一模一样的uri比如 location = /index ,那么只有路径为/index的才会匹配到
2. 前缀模糊匹配 ^~ , 不含正则表达式
用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。
进行uri的前缀精确匹配比如 location ^~ /user/ ,那么只要是路径以/user/开头的都会匹配到
3. 模糊匹配 ~ 包含正则表达式,区分大小写:
~用于表示 uri 包含正则表达式,,并且区分大小写。
进行uri的模糊匹配,区分大小写,匹配到后不再进行其他匹配
比如 location ~ /user/ ,当路径包含/user/时会匹配,
比如/admin/user/或者/user/admin/当然也可以用正则表达式来表示匹配路径:比如 location ~ ^/user(.*)admin$,能够匹配以/user开头,admin结尾的路径,.*表示的是任意字符
location如果没有“/”时,请求就可以模糊匹配以字符串开头的所有字符串,而有“/”时,只能精确匹配字符本身。
目标访问地址:http://192.168.88.129/edu/index.html
这里我们简单测试一下,配置后我们访问192.168.244.41/user/xxx/admin,发现是可以正常转发至后台的tomcat服务的,只是tomcat服务中没有/user地址的接口,所以返回404
我们继续访问192.168.244.41/user/xxx,发现报的就是nginx的404了,这说明请求并没有转发到后台tomcat中,说明没有命中匹配。
在比如实例如下
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
location ~ /edu {
proxy_pass http://127.0.0.1:8080;
}
/edu 可以匹配/edu*/*格式的路径URL,而/edu/ 只能匹配/edu/*格式的URL。这里注意到proxy_pass后面没有加/也没有加目录,则会把location的值直接拼接到proxy_pass后面。
4. 模糊匹配 ~* 包含正则表达式,不区分大小写:
用于表示 uri 包含正则表达式,并且不区分大小写,即看到~就表示正则表达式。
进行uri的模糊匹配,不区分大小写,匹配到后不再进行其他匹配,优先级与~相同,按照先后顺序优先****
比如 location ~ /USER/,当路径包含/USER/时会匹配,如果是/user/则不会,因为区分大小写了****
优先级:****
5.不带符号精确匹配
匹配起始于此uri的所有的url
没有符号,按照路径开头精确匹配,但是匹配到后不会立即返回,还会继续匹配其他普通匹配,如果匹配到,则会舍弃之前匹配的路径
比如 location /user/ , 当访问/user/开头时会匹配到
比如 location /user/admin,当访问/user/admin时会匹配到
注意事项:
-
如果 uri 包含正则表达式,则必须要有
~或者~*标识 -
匹配优先级:由高到低为 = > ^~ > 其他,其他匹配根据先后顺序,配置在前的越优先
匹配优先级:=, ^~, ~/~*,不带符号。
- 精确匹配=
- 前缀匹配
^~(立刻停止后续的正则搜索) - 按文件中顺序的正则匹配
~或~* - 匹配不带任何修饰的前缀匹配。
实例
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
/匹配规则A,“/index.html”匹配规则B,“/documents/document.html”匹配规则C, “/images/1.gif”匹配规则D,“/documents/1.jpg”匹配规则E。
【2】 转发代理 proxy_pass指令 配置详解
我们上述讲解了匹配模式的书写,匹配到了还要进行合理的转发,而转发模式的控制就是通过proxy_pass, 下面我们来看看proxy_pass的语法结构
proxy_pass 的四种配置写法 首先我们来回顾下proxy_pass的语法:
1.proxy_pass url;
转发地址url分为带/和不带/,带杠的为绝对根路径,会直接在路径后拼接上不带匹配路径的转发地址;如果没有杠表示相对路径,则会将匹配路径也带上进行转发,我们举例说明:
1.location /user/ {
proxy_pass url;
}
访问路径固定为:http://192.168.244.21/user/index.html
-
当proxy_pass http://192.168.244.21:8080/ 时,会跳转至http://192.168.244.21:8080/index.html,带/表示绝对路径,匹配路径/user/会被消除
-
当proxy_pass http://192.168.244.21:8080 时, ,相对路径 ,会跳转至http://192.168.244.21:8080/user/index.html,匹配路径/user/不会被消除,
3.当proxy_pass http://192.168.244.21:8080/admin/ 时 会跳转至http://192.168.244.21:8080/admin/index.html,匹配路径/user/被消除,并且保留转发路径里的/admin/
4.当proxy_pass http://192.168.244.21:8080/admin 时
会跳转至http://192.168.244.21:8080/adminindex.html,因为proxy_pass中也包含了/了,表示绝对路径,所以/user/会被消除
总言之记住一点,带/表示绝对路径,请求路径中的匹配路径(location)转发时会被消除;
server和location模块中proxy_pass的区别
- 在server模块中的proxy_pass只需要配置ip(或域名)和端口,相当于端口转发;
- 在location中的proxy_pass,也就是我们更加常用的,可以配置域名、ip、端口、uri,此外还需要提供协议:http或https,相当于地址转发。
配置语法如下:
server {
listen 80;
proxy_responses 1;
proxy_timeout 20s;
proxy_pass xxx.com:8080;
# proxy_pass 192.168.244.21:8080;
location /user/ {
roxy_pass http://192.168.244.21:8081;
}
}
【3】# 文件路径指令 root与alias
在NGINX配置中,root 和 alias 是两个用于指定文件路径的指令,它们用于将URL路径映射到服务器上的文件系统路径。尽管它们的目的相似,但它们的行为和用法有所不同。
location ${path} {
root html; # 会将${path}一起加入到代理的(/html/${path})路径中
alias html; # 不会将${path}一起加入到代理的(html/)路径中
}
root path
root 设置web资源路径映射, 指令用于定义请求的根目录。NGINX会将请求的URI附加到root指令指定的路径上,以构建文件系统的路径,用于指明用户请求的url所对应的本地文件系统上的文档所在目录路径,可指定相对路径也可使用绝对路径。
可用的位置:http, server, location, if in location。
实例如下
location /images/ {
root /data/www;
}
如果用户请求 /images/example.jpg,NGINX会在/data/www/images/example.jpg中查找文件。
如请求/i/top.gif,则按照如下配置目标文件为/data/w3/i/top.gif:
location /i/ {
root /data/w3;
}
alias path
alias 指令也用于定义请求的根目录,但它不会将请求的URI附加到指定的路径上。相反,它使用指定的路径替换URI中的位置部分。
实例一 :
为指定路径 定义一个替代值,仅能用于location上下文。
如访问/i/top.gif,按照如下location配置,则目标文件为/data/w3/images/top.gif :
location /i/ {
alias /data/w3/images/;
}
实例二
location /images/ {
alias /data/www/static/;
}
在这个例子中,如果用户请求 /images/example.jpg,NGINX会在/data/www/static/example.jpg中查找文件,而不是在/data/www/static/images/example.jpg中。
使用场景
- 当你的目录结构和URL结构一致时,使用root。
- 当你的目录结构和URL结构不一致时,使用alias。
注意事项 在使用alias时,要特别注意末尾的斜杠(/)。
- 如果alias的路径以斜杠结尾,那么请求的URI中匹配location的部分将会被替换掉;
- 如果不以斜杠结尾,那么请求的URI中匹配location的部分将会被替换并保留到最后一个斜杠。
root通常比alias更安全,因为它不会允许访问服务器上的任意目录。而alias如果不正确使用,可能会导致安全漏洞。 在使用这两个指令时,请确保你完全理解它们的行为,并根据你的具体需求进行选择。
location中使用: root指令和alias指令的意义不同:
- root,目标文件路径为root指定的value+URI;
- alias,给定的路径对应于location中的/uri/右侧的/
也就是说当使用root指令时,文件的路径构造只是把URI的值拼接在了root指令值的后面!
在使用这两个指令时,请确保你完全理解它们的行为,并根据你的具体需求进行选择。
【4】 设置处理请求的策略 try_files
示例
#对象组件前端
location /object-component/ui {
alias /home/bom/deploy/frontend/object_component_web;
index index.html index.htm;
try_files $uri $uri/ /index.html last;
}
#xbom前端组件
location /bom-web {
alias /home/xbom/deploy/frontend/bom-web;
index index.html index.htm;
try_files $uri $uri/ /index.html last;
}
几点说明:
- 按指定的file顺序查找存在的文件,并使用第一个找到的文件进行请求处理
- 查找路径是按照给定的root或alias为根路径来查找的
- 如果给出的file都没有匹配到,则重新请求最后一个参数给定的uri,就是新的location匹配
- 如果最后一个参数是 = 404 ,若给出的file都没有匹配到,则最后返回404的响应码
示例
$uri 是请求文件的路径,$uri/ 是请求目录的路径。
最后一个参数也可以指向一个命名的位置,如下面的示例所示。从版本0.7.51开始,最后一个参数也可以是code如404。
#参数: $uri 表示当前请求的URI,不带任何参数
location /mall/ {
root htmlmall;
index index.html index.htm;
try_files $uri $uri/ /mall/index.html =404;
}
假设说请求是/mall/images/1.jpg:
① nginx会先去找/htmlmall/mall/images/1.jpg这个文件,
② 如果①找不到则会找/htmlmall/mall/images/1.jpg/这个目录下的index索引页
③ 如果②也没找到,则会去请求/mall/index.html—一个新的请求
④ 如果③也没找到,返回404
注意,如果try-files 如果不写上 $uri/,当直接访问一个目录路径时,并不会去匹配目录下的索引页。 即 访问127.0.0.1/mall/images不会去访问 127.0.0.1/mall/images/index.html 。
如果想实现项目直接解压部署在htmlmall下,不再创建一个mall文件夹的话,root换成alias即可。
【5】 动静分离之静态资源映射配置
为了提高网站反应速率,一般用于中小型网站,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源,如图片、js、css等文件,可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时,代理服务器就可以直接处理,而不用将请求转发给后端服务器。对于用户请求的动态文件,如servlet、jsp,则转发给Tomcat,Jboss服务器处理,这就是动静分离。即动态文件与静态文件的分离。
动静分离可通过location对请求url进行匹配,将网站静态资源(HTML,JavaScript,CSS,img等文件)与后台应用分开部署,提高用户访问静态代码的速度,降低对后台应用访问。通常将静态资源放到nginx中,动态资源转发到tomcat服务器中。
在Nginx中进行动静分离,通常需要配置两个location块:一个用于处理静态资源的请求,另一个用于将所有其他请求转发到后端服务器。以下是一个简单的配置示例:
server {
listen 80;
server_name example.com;
# 静态资源的根目录
root /path/to/static/files;
# 静态文件的location块
location ~* \.(jpg|jpeg|png|gif|ico|css|js|html|htm)$ {
expires 30d; # 设置静态文件的缓存过期时间
add_header Cache-Control "public";
}
# 处理所有其他请求的location块
location / {
proxy_pass http://backend_server; # 假设后端服务器地址是http://backend_server
include proxy_params; # 假设proxy_params文件包含了一些代理设置参数
}
}
在这个配置中,所有.jpg, .jpeg, .png, .gif, .ico, .css, .js, .html, .htm等静态资源的请求都会被Nginx直接处理,并设置30天的缓存。其他所有请求都会被转发到名为backend_server的后端服务器。
请根据实际情况调整root指令中的静态文件目录和proxy_pass中的后端服务器地址。
通过 expires 参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体 Expires 定义:是给一个资源设定一个过期时间,也就是说无需去 服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用 Expires 来缓存)
示例二 这里以图片实例,将图片存储在/usr/local/nginx/image路径下。
nginx配置文件实例如下:
location ~* .(jpg|png|jpeg)$ {
root /usr/local/nginx/;
expires 3d;
}
如这里设置 3d ,表示在这 3 天之内访问这个 URL ,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码 304如果有修改,则直接从服务器重新下载,返回状态码 200 。
浏览器访问如下http://192.168.88.129/image/1.jpg:
这里需要注意浏览器访问uri是/image/1.jpg,这个location拦截后会拼接到root后去服务器找,也就是 /usr/local/nginx/image/1.jpg!
示例三
worker_processes 1;
events { worker_connections 1024; }
http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65;
#定义一组服务器 upstream httpds{ server 172.16.70.222:8080; server 172.16.70.223:8080; } server { listen 80; server_name www.jiang.com;
location / {
proxy_pass http://httpds;
#root /www/proxy;
#index index.html index.htm;
}
location ~*/(images|assets) {
root /www/resources;
index index.html index.htm;
}
#将图片和样式以正则表达式来表现出来 #location /assets {
#root /www/resources;
#index index.html index.htm;
#}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
【6】 autoIndex指令 展示文件路径目录下内容
如下所示,访问image路径然后展示其下(location里面映射的路径)的文件列表。
autoindex模块它所实现的一个基本功能,是当用户请求以 / 结尾式的URL,它会列出对应的目录结构
- 比如说, 在实际的生态环境中,内部系统可能经常需要为用户提供一些下载功能。
- 可能需要列出来某一个磁盘上的一个文件, 比如,磁盘上是一个视频目录文件
- 在访问某一个特定的目录的URL的时候,会给用户列出来所有视频文件
- 这个时候,通常就会使用到autoindex这样一个功能
1)指令集
1.1 autoindex
- 语法:autoindex on | off;
- 默认值:autoindex off
- 上下文:http、server、location
- 默认情况下是不打开这样一个功能的
- 因为这样一个功能对我们的用户来说,会有很多隐藏信息
- 在对一些特定的内网环境,可能是有用的
- 比如说,我们的公司内部可能经常需要下载一些文件,分享一些文档
- 使用这样一个功能,就可以很好的去搭建这样一个下载平台
1.2 autodindex_exact_size
- 语法:autodindex_exact_size on | off;
- 默认值:autodindex_exact_size off
-
-
-
- 上下文:http、server、location
-
-
-
-
- 默认情况下,它是一个on的一个指令,文件的大小,它会精确到字节,以字节为单位的
-
-
- 把这个功能给关闭掉,字节很大的话,比如说50M,它小的话, 比如显示150Byte,或者更大的话,能显示来GB
- 关闭后,使我们这个文件大小更直观,更友好
1.3 autoindex_format
- 语法:autoindex_format html | xml | json | jsonp;
- 默认值:autoindex_format html;
- 上下文:http、server、location
- 就是返回目录结构的时候,以哪种形式返回
- 经常会用的是html 还有 xml/json/jsonp等
- 这样一些格式我们都是可选的
1.4 autoindex_localtime
- 语法:autoindex_localtime on | off;
- 默认值:autoindex_localtime off;
- 上下文:http、server、location
- 这个决定文件的一个时间格式,默认情况下开off,它就显示GMT的格式
这里需要用到autoindex 指令,也就是ngx_http_autoindex_module 模块。其往往用于处理以/结尾的请求并展示一个路径下内容列表。配置实例如下:
示例一
location /image/ {
root /usr/local/nginx/;
autoindex on;
}
也可以返回json格式:
location /image/ {
root /usr/local/nginx/;
autoindex on;
autoindex_format json;
}
示例二
server {
listen 80;
server name www.baidu.com
location /download/ {
root /opt/source;
index b.html;
autoindex on;
autoindex exact size on;
autoindex format html;
autoindex localtime off;
}
注意,download/b.html 不存在, 如果存在,则下面配置会失效
注意,如果 autoindex exact size off; 关闭,就会显示的更人性化
- 注意,除了 html, 其他格式均不支持下载
【7】 add_header 指令 添加/覆盖响应头
add_header 是 Nginx 中用于设置 HTTP 响应头的指令,它通常位于 server、location 或者 http 级别的上下文中。
基本语法如下:
add_header name value;
其中 name 是响应头的名称,value 是响应头的值。
配置示例
server {
listen 80;
server_name example.com;
location / {
add_header X-My-Header "My Value";
proxy_pass http://backend;
}
}
在这个例子中,对于所有通过该 location 的请求,Nginx 将添加一个名为 X-My-Header 的响应头,其值为 My Value。
注意:
add_header不会覆盖已有的响应头,除非使用了always参数。- 如果
value包含变量,确保变量名用花括号{}包围,以避免语法混淆。
add_header X-My-Header "My $value";
在这个例子中,$value 是一个变量,它的值将被插入到响应头 X-My-Header 中。
示例二
http {
# 添加一个新的头部
add_header X-Custom-Header "CustomValue";
server {
listen 80;
# 修改现有的头部
add_header Content-Type text/html;
# 条件性地添加头部
if ($request_method = GET) {
add_header X-Method-Type "GET";
}
location / {
# 代理请求时添加头部
proxy_pass http://backend;
proxy_set_header Host $host;
add_header X-Proxy-Used "true";
}
}
}
这个例子中,我们添加了自定义的 HTTP 头部 X-Custom-Header ,修改了 Content-Type 头部,并且根据请求方法添加了条件性的头部 X-Method-Type 。在代理请求时,我们添加了 X-Proxy-Used 头部以表明请求是通过 Nginx 代理的。 请注意, add_header 指令应该放在 http 、 server 或 location 块中,具体取决于你想要在哪个级别上添加或修改头部。
【8】 proxy_set_header 指令 修改请求/添加请求头
proxy_set_header 指令在 Nginx 中用于设置或重置从代理服务器传递到目标服务器的请求头。这可以用来修改或添加请求头,以便传递给后端服务。
以下是一些常用的 proxy_set_header 配置示例:
- 默认情况下,
proxy_set_header会设置Host为被代理的主机,但你可以重写它:
location / {
proxy_set_header Host $host;
proxy_pass http://backend;
}
- 如果你想要传递原始的主机名到后端服务器,可以使用
$http_host变量:
location / {
proxy_set_header Host $http_host;
proxy_pass http://backend;
}
3.你也可以设置 X-Real-IP 头来传递客户端的原始 IP 地址
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://backend;
}
4.如果你想要传递客户端的 IP 地址给后端服务器,但不想使用 $remote_addr 变量,可以使用 X-Forwarded-For 头:
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://backend;
}
- 如果你想要修改
Cookie头,可以使用proxy_set_header
location / {
proxy_set_header Cookie "";
proxy_pass http://backend;
}
6.如果你想要添加一个新的头部信息:
location / {
proxy_set_header X-Custom-Header "some-value";
proxy_pass http://backend;
}
- add_header 与 proxy_set_header两者区别
- 方向:proxy_set_header 修改的是请求头(request header),而 add_header 修改的是响应头(response header)
- 目标:proxy_set_header 的目标是后端服务器,用于通知后端关于请求的一些信息;而 add_header 的目标是客户端,用于向客户端提供额外的信息或指令
- 使用场景:proxy_set_header 通常在反向代理配置中使用,确保后端服务器能正确处理请求;而add_header 在需要向客户端发送额外信息或增强安全性的情况下使用