前言
最近工作用到了nginx,但是路由配置特殊,业务场景复杂,举几个例子:一个机器上多个服务,使用同一个端口,不同的域名如何配置?同一个服务分子域名呢?location那么多,怎么判断它匹配哪个呢?重定向和proxy都能跳到指定地址,那用哪个呢?带着这些问题我集中整理了nginx跳转的配置方式,方便后进行技术选型和决策。本文按分类整理了四种方式,相信总有一种满足你的需求。
一、配置server对应的域名
server name 为虚拟服务器的识别路径。因此不同的域名会通过请求头中的HOST字段,匹配到特定的server块,转发到对应的应用服务器中去。server_name匹配规则:后面可以跟多个域名,第1个是主域名
1.1、精确匹配
如下nginx配置
1 | server复制代码 listen 8080; |
请求结果
1 | arduino复制代码curl http://my.test.com:8080 返回:I am mytest! |
1.2、正则表达式
- 以*通配符开始的最长字符串,如下示例
1 | arduino复制代码server { |
- 以*通配符结束的最长字符串
1 | server复制代码 listen 8080; |
- 通配符名字只可以在名字的起始处或结尾处包含一个星号,并且星号与其他字符之间用点分隔。所以,“my..com“都是非法的。
例如 :server_name my..com;
报以下错误:
1 | vbnet复制代码nginx: [emerg] invalid server name or wildcard "my.*.com" on 0.0.0.0:8080 |
- 匹配正则表达式
1 | perl复制代码server { |
解释说明
- ~: 表示大小写敏感的正则;
- ^:匹配字符串的开始;
- {.+}:换行符以外的任意自读重复一次活更多次;
- (): 分组与取值;
- :表示转义;
- serno:设置提取的变量;
- $:匹配字符串的结束;
请求结果
1 | arduino复制代码curl http://my02.mydomain.com:8080 返回:02% |
- server_name的配置顺序是怎样的呢?
按照如下顺序匹配:
匹配顺序->
->精确匹配
->*在前的域名
->*在后的域名
->按文件中的顺序匹配
->default server:第一个,listen指定default
二、配置location
2.1、Location 匹配规则:仅匹配URI,忽略参数
1 | bash复制代码location [=|~|~*|^~] /uri/ { … } |
匹配的正则符号如下:
- = 严格匹配。如果请求匹配这个location,那么将停止搜索并立即处理此请求
- ~ 区分大小写匹配(可用正则表达式)
- ~* 不区分大小写匹配(可用正则表达式)
- !~ 区分大小写不匹配
- !~* 不区分大小写不匹配
- ^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式
2.2、举例
1 | ruby复制代码1、匹配任意请求 |
2.3、匹配顺序如下图
按照上面的规则配置了如下location
1 | bash复制代码location = /documents { |
- curl test1.com:8080/documents,精… configuration A
- curl test1.com:8080/documents/ ^~匹配上后不在匹配,返回 configuration D
- curl test1.com:8080/documents/t… 走到了正则匹配,不会走到/documents/txt1(正则没走完) 返回configuration E
- curl test1.com:8080/documents/t… C,因为正则都不匹配
2.4、如何debug正则呢?
编译的时候加上 –with-debug选项,例如 ./configure –with-debug
conf文件加上要debug的host,debug_connection对应要debug的连接。
1 | ini复制代码events { |
error.log查看debug日志,图中test location就是正则匹配的过程
三、配置rewrite
语法如下:
1 | scss复制代码 指令语法:rewrite regex replacement[flag]; |
flag标记 | 说明 |
---|---|
last | 本条规则匹配完成后继续向下匹配新的location URI规则 |
break | 本条规则匹配完成后终止,不在匹配任务规则 |
redirect | 返回302临时重定向 |
permanent | 返回301永久重定向 |
3.1、重定向
return三种code,code url和url。
返回状态码:444表示关闭连接 301表示http1。0中永久重定向,302表示临时重定向,进制缓存。http1.1后,303表示临时重定向,允许改变方法,进制缓存,307表示临时重定向,不允许改变方法,禁止被缓存,308表示永久重定向,不允许改变方法。
- 返回code
1 | bash复制代码location / { |
- 通过$request_uri变量匹配所有的URI。
1 | bash复制代码rewrite ^ https://www.xxxx.com$request_uri? permanent; |
- 通过正则匹配所有的URI后再去掉开头第一个/(反斜线)。
1 | javascript复制代码rewrite ^/(.*)$ https://www.xxxx.com/$1; |
- 与if指令结合
1 | perl复制代码server { |
3.2、如何查看rewrite日志
打开日志开关rewrite_log on;
可以配置到http,server,location和if上下文中
示例:curl test1.com:8080/first/2.txt
1 | bash复制代码location /first { |
效果图如下
四、配置 proxy
对上游服务使用http/https协议进行反向代理。proxy_pass后面跟url,可以仿造location,if in location和limit_except上下文中。 这个功能是默认编译到nginx中的。本文重点讨论http proxy。
url参数规则
- url必须以http或者https开头,接下来是域名、ip、unix socket或者upstream名字,都可以就端口。后面是可选的uri
http示例proxy_pass http://localhost:8000/uri/;
UNIX域套接字路径来定义示例proxy_pass http://unix:/tmp/backend.socket:/uri/;
- url中是否携带uri,结果也不一样,如果在proxy_pass后面的url加/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;如果没有/,则会把匹配的路径部分给代理走。
目录结构如下
1 | sql复制代码├── first |
nginx配置如下
1 | ini复制代码server { |
不带/,然后 curl http://127.0.0.1:8082/first/index.html 返回index html
带/,然后 curl http://127.0.0.1:8082/first/index.html 返回first index
- Url参数中可以携带变量
proxy_pass http://$host$uri;
- 可以配合rewrite break语句
1 | ini复制代码location /nameb/ { |
五、小结
配置nginx的路由,有多种方式,域名可以用server_name配置,uri可以用location配置,复杂的可以加rewrite配置修改请求。还有就是配置proxy代理,在代理中转发id等。本文开头的几个问题,同端口不同域名使用server_name配置就可以,可以放到不同的server中;location的匹配顺序可以参考文中的那张流程图;重定向的情况下客户端拿到302和url就会去请求这个url指定的资源,proxy不会,因此在nginx+tomcat的场景下,proxy更适合。
本文转载自: 掘金