一、场景
现有如下的的应用需求:
1.利用域名代理多个端口的应用
2.利用二级目录代理多个端口的应用
3.利用二级目录代理多个IP服务器的应用
4.利用域名代理多个服务器的应用
5.利用端口代理多个服务器应用
二、场景实现
1.利用域名代理多个端口的应用
这个实现比较简单,基本上是一些基础的配置,在我应用中,我利用docker搭建了两个应用,一个nextcloud,一个是jupyter,其中一个运行在8088端口,一个运行在8888端口。现在的利用场景一的技术进行实现,nginx的配置文件如下:
map $http_upgrade $connection_upgrade {default upgrade;'' close;}server {listen 80;server_name jupyter.test.com ;access_log /var/log/nginx/host.access.log main;location / {proxy_pass http://127.0.0.1:8888/;proxy_redirect / /;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_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection $connection_upgrade;}error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}}server {listen 80;server_name nextcloud.test.com;access_log /var/log/nginx/nextcloud.log main;location / {proxy_pass http://127.0.0.1:8088/;proxy_redirect / /;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}
简单的解释如下:
首先建立两个server,
- 其监听的端口都是80
- 其服务器名称分别是不同的域名,这是区分两个server的关键
- 然后是服务器日志,这里可以定义其他日志,如错误日志等
location /
一个关键,就是到根目录时如何进行操作,简单的解释如下 :
proxy_pass http://127.0.0.1:8088/;
表示所有到根目录的请求由代理到8088端口
proxy_redirect / /;
表示所有重定向定向到根据目录下,这里有一个问题,就是此处是给同一个站的重定向设置的,如果是不同站点的重定向,该如何处理,以后再研究。
此处的域名都是一个本地的域名,无法进行网络的访问,但在本地还是运行的挺好的。其在进行应用区分的时候,是以请求的主机名字段来区分的,如果是请求到80端口的主机名为nextcloud.test.com,则由server_name为nextcloud.test.com的主机进行处理。另一个同理。
利用二级目录代理多个端口的应用
这个基本的思路是有,但在实现上还是有些问题的。简单的配置文件如下:
server {listen 80;server_name localhost;#access_log /var/log/nginx/host.access.log main;location / {root /usr/share/nginx/html;index index.html index.htm;#if ( $cookie_jupyter = 'test' ){# rewrite ^/(.*)$ /jupyter/$1 last;#}#if ( $http_referer ~* "jupyter" ){# rewrite ^/(.*)$ /jupyter/$1 last;#}#if ( $cookie_nextcloud = 1 ){# rewrite ^/(.*)$ /nextcloud/$1 last;#}#if ( $http_referer ~* ^.*/nextcloud/.*$ ){# rewrite ^/(.*)$ /nextcoud/$1 last;#}rewrite ^/(.*)$ /jupyter/$1;}location /jupyter/ {proxy_pass http://127.0.0.1:8888/;proxy_redirect / /jupyter/;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_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection $connection_upgrade;if ($http_cookie !~* "jupyter=test") {add_header Set-Cookie jupyter=test;}}location /nextcloud/ {proxy_pass http://127.0.0.1:8088/;proxy_redirect / /nextcloud/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;if ($http_cookie !~* "nextcloud=1") {add_header Set-Cookie nextcloud=1;}}
面临的一个困难:
在请求过程中,由于所有的请求都是向服务器IP的80端口发出的,这时,浏览器会认为这是同一个站点。同时,页面中的相对路径,请求到根目录下时,必然会发生404错误。
解决方法思路如下:
1.利用referer进行区分
- 基本思路:
根据请求头中的referer字段,来区分是请求那个目录下文件的,将请求到根目录下的url进行重写(rewrite),然后进行请求。
2.存在问题:
根据 referer 字段进行区分,有时有些请求不一定带referer字段,带了也不一定含有指定的目录
2.利用cookie进行解决
- 基本思路:
在nginx响应的时候,写入cookie,利用cookie进行区分。
- 存在问题:
同一个请求的IP,浏览器会认为是同一个站点,将所有的cookie全部保存,有时会解析错误。比如:我先访问 jupyter,然后访问nextcloud,jupyter的cookie还保存着,
而我在访问nextcloud的时候,如果是jupyter的cookie的规则在前面,会先将所有的url重写为/jupyter/
,此时,也会出现错误。目前尚不知该如何解决。
3.利用二级目录代理多个IP服务器的应用
未进行具体的实现,但在实现的服务器建立,利用upstream的ip_hash来进行流的引导,从而实现多个目录代理的实现。
upstream server1{ip_hash;server 192.168.1.1:80;
}
upstream server2{ip_hash;server 192.168.1.2:80;
}
upstream server3{ip_hash;server 192.168.1.3:80;
}server {listen 80;server_name localhost;location /app1/ {proxy_pass http://server1/;}
server {listen 80;server_name localhost;location /app2/ {proxy_pass http://server2/;}
server {listen 80;server_name localhost;location /app3/ {proxy_pass http://server3/;}
4.利用域名代理多个服务器的应用
在端口的基础上,将不同端口改为不同的服务应用即可
server {listen 80;server_name www.exp1.com;location / {proxy_pass http://192.168.1.1/}
server {listen 80;server_name www.exp2.com;location / {proxy_pass http://192.168.1.2/}
server {listen 80;server_name www.exp3.com;location / {proxy_pass http://192.168.1.3/}
5.利用端口代理多个服务器应用
在nginx 端开启多个端口,直接将端口代理到相应的服务器即可
server {listen 8081;server_name localhost;location / {proxy_pass http://192.168.1.1/}
server {listen 8082;server_name localhost;location / {proxy_pass http://192.168.1.2/}
server {listen 8083;server_name localhost;location / {proxy_pass http://192.168.1.3/}