请教一下,关于 nginx 多个子目录反代的问题。

2022-10-20 01:04:33 +08:00
 binghe

现在多个服务运行在服务器上,想要达成如下效果,但是这个 nginx 不懂怎么配置了。。。 三个服务有两个是 python 的,一个是 go 的。

http://demo.abc.com/drive  --->  http://127.0.0.1:8855
http://demo.abc.com/avg   --->  http://127.0.0.1:8866
http://demo.abc.com/doc   --->  http://127.0.0.1:8877



server {
	listen 80;
	server_name demo.abc.com;
    
	root /var/www/html; #注释这个后也提示错误

	location /drive/ {
         rewrite ^/drive/(.*)$ /$1 break;  #也试着这样过,不知道是不是写错了,没有效果
         proxy_pass  http://127.0.0.1:8855;
   }
   
   location /avg/ {
         proxy_pass  http://127.0.0.1:8866;
   }
	
   location /doc/ {
         proxy_pass  http://127.0.0.1:8877;
   }    
    
}


log 日志,看日志,好像最大的问题就是这个 root 路径,如果把 root /var/www/html;这个注释掉,log 就是 /usr/share/nginx/html/assets/index.786270b3.js 这样的。


#349313: *1 open() "/var/www/html/assets/index.786270b3.js" failed (2: No such file or directory), client: 172.17.0.1, server: demo.abc.com, request: "GET /assets/index.786270b3.js HTTP/1.1", host: "demo.abc.com", referrer: "http://demo.abc.com/drive/"
```
2295 次点击
所在节点    NGINX
23 条回复
rrfeng
2022-10-20 07:09:09 +08:00
GET /assets/index.786270b3.js

你配置的三个 path 都没包含这个请求的路径。搞清楚这点就解决了。
putyy
2022-10-20 08:24:34 +08:00
location /drive/ {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8855;
}
}
location /avg/ {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if (!-f $request_filename) {
proxy_pass http://127.0.0.1: 8866;
}
}
location /doc/ {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if (!-f $request_filename) {
proxy_pass http://127.0.0.1: 8877;
}
}
jifengg
2022-10-20 09:15:50 +08:00
先说下原因:
你在浏览器输入地址”http://demo.abc.com/drive/“访问,
请求到达你的服务器,被 nginx 转发给 http://127.0.0.1:8855 ,
你的 8855 服务返回了 html 内容,里面包含了类似一个<script src="/assets/index.786270b3.js"></script> 的标签,
浏览器解析到 html 的这块 script ,于是去加载这个 js ,由于这里 src 是以"/"开头,所以浏览器拼上 host 变成 http://demo.abc.com/assets/index.786270b3.js ,注意,/drive 这一层没了,
请求再次到达服务器,由于 /assets 你没有配置对应的 location ,就默认去 root 下查找对应文件,找不到,nginx 记录错误日志


解决思路:
1. [推荐] 给 8855 配置一个独立的域名,然后 ngxin 配置
location / {
proxy_pass http://127.0.0.1:8855;
}

2.修改 8855 的代码
2.1 script 引入 js 改为相对路径的方式,类似 src="assets/index.786270b3.js",但是要注意 html 和 js 的相对路径关系;
2.2 从 header 里获取”Host“,拼接到 src 里。这个 Host 需要 nginx 透传过来,因为不传的话,8855 的程序其实是不知道你浏览器是通过”demo.abc.com/drive“这个 host 访问到它的,方法 @putyy 给出了,就是“proxy_set_header Host $http_host;” 这一句
xiang0818
2022-10-20 09:34:36 +08:00
补上斜杆

server {
listen 80;
server_name demo.abc.com;

root /var/www/html; #注释这个后也提示错误

location /drive/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8855/;
}

location /avg/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8866/;
}

location /doc/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8877/;
}

}
xiang0818
2022-10-20 09:52:24 +08:00
```
```
binghe
2022-10-20 11:34:52 +08:00
@rrfeng #1 感谢,由于这个不是主业,所以搞清楚有点困难,昨天其实还去了 nginx 官网看了一会关于 proxy_pass 的,好像也没收获。


@putyy #2 按照您的方法,我配置了一个,但还是提示一样的错误:
binghe
2022-10-20 11:42:59 +08:00
哎,不小心发出去了。
------------------------------------------------------
location /drive/ {
proxy_http_version 1.1;
proxy_set_header Connection "keep-alive";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if (!-f $request_filename) {
proxy_pass http://127.0.0.1:8855;
}
}

-------------------------------------------------------

错误日志:
#408155: *1 open() "/var/www/html/assets/index.786270b3.js" failed (2: No such file or directory), client: 172.17.0.1, server: demo.abc.com, request: "GET /assets/index.786270b3.js HTTP/1.1", host: "demo.abc.com", referrer: "http://demo.abc.com/drive/"

----------------------------------------------------------

浏览器控制台的错误是这样的:
GET http://demo.abc.com/assets/index.659f4289.css net::ERR_ABORTED 404 (Not Found) (索引):53
(匿名) @ (索引):53
(匿名) @ (索引):55
binghe
2022-10-20 11:47:58 +08:00
@jifengg #3 感谢。如果是要放在现在的服务器上,好像是无法每个服务单独解析一个域名的,只能通过 nginx 反代想想办法。
binghe
2022-10-20 11:50:27 +08:00
@xiang0818 #4 好像用这个代码,错误的内容和#2 是一样的。

我其实前面自己已经各种瞎搞瞎测试两天了都没搞定😅
jifengg
2022-10-20 12:09:37 +08:00
@binghe 没法配置独立域名,那就按照第 2 个方法改吧。
再补充一个

2.3 修改 8855 的编译配置,不清楚 8855 是啥语言的,但是一般都会有一个配置,表示这个项目即将运行在哪个目录下,比如默认可能是“/",那么这时候可以改成 “/drive/”,就能解决后面路径不对的问题了。

再提一嘴,我上面列的 1 ,2.1 ,2.2 ,2.3 ,都是一个独立的解决方案,不是解决步骤。选一个你能做的就行。
adoal
2022-10-20 12:31:57 +08:00
如 #10 所说你要配置后面的三个服务,让他们“认识到”自己应该按照运行在子路径下的情况来生成页面里的站内链接 URL 。
大部分 web 框架都可以配置一个固定的 prefix 来做这事的。甚至,如果框架支持老式 CGI 惯例的话,可以从前端传一个 header 过去让后端动态知道自己应该运行在哪个子路径下。
binghe
2022-10-20 13:35:05 +08:00
@jifengg #10 该配置的话,可能也比较麻烦。目前 8855 这个项目是 go 语言写的。三个项目都不是我写的。而且项目还在更新中....

通过公网 IP 直接访问的话,路径是这样的 http://ip:port/assets/index.786270b3.js
jifengg
2022-10-20 13:51:53 +08:00
@binghe 如果你的三个项目是开源项目,那不如说下是啥项目,大家直接可以看怎么配。
如果不是开源,是其他团队在开发的,那就联系他们问怎么把“/drive”传给他们。
sher17
2022-10-20 14:17:27 +08:00
二级目录这种东西,不是 nginx 的问题。个人建议 8855 这个服务单开一个端口。如果不怕影响其他服务。不妨试试:
location ~ /.*\.(js|css)?$ {
proxy_pass http://127.0.0.1:8855;

}#设置静态文件目录
binghe
2022-10-20 14:28:20 +08:00
对不起,各位,我犯了个大错,有个环境没说清楚。目前是网络环境大致是这样的。


binghe
2022-10-20 14:32:32 +08:00
@jifengg #13 如果像#14 说的不是 nginx 的问题,那可能就没办法了。或者我这里在问问开发团队那边能不能帮忙解决。
@sher17 #14 我昨天有测试了差不多一样的写法。就是反代一个项目。
ylls
2022-10-20 14:59:50 +08:00
如果是 3 楼说的那种情况的话 你可以使用 nginx 的 subs_filter 模块进行静态文件路径替换
ylls
2022-10-20 15:02:53 +08:00
@ylls 具体你可以在终端里面使用 curl 命令直接访问网页 看看返回的网页静态文件路径 如果是 /开头 那就需要进行替换一下

看日志 你是访问 http://demo.abc.com/drive/后 nginx 报这个错误 那么和 3 楼说的情况是一致的,如果你无法修改对应的服务器上的内容 那么就可以使用 nginx 的 subs_filter 模块进行修改返回的内容
sch1111878
2022-10-20 15:52:38 +08:00
我是用不同域名实现的, 比较简单
Soutxx
2022-10-23 22:58:23 +08:00
@xiang0818 老哥,是你吗? 499

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/888264

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX