如何优雅的实现跨域方式呢?

如今很多项目中都会需要解决一个问题就是跨域问题,其实这个问题很多小公司觉得没什么,直接使用后台代码进行解决了,如此粗糙,或者稍微高级点就是让前端是实现,那么你问过了前端的想法了吗?现在都是微服务架构了,在架构设计初期,这块就需要设计好,其实无论是后端还是前端还是运维都需要去了解,因为谁都可以去实现就看谁设计的方式带来的性能更加明显了,不说了,进入正题吧~

使用nginx实现用在同域名下部署多个前后端分离项目

背景

现在我们有几个前后端分离的项目,前后台使用的分别是Vue和Springboot框架开发,部署方式的话前端使用webpack进行打包用nginx作为静态服务器访问,部署在前端服务器上,后台由springboot打成jar包直接启动运行,部署在另一台后台服务器上。

不同的项目分别使用不同的端口进行代理,大概配置如下:

在这里插入图片描述
这种方式我们代理了8084端口来映射前端目录,访问 http://前端服务器ip:8084的话会自动去找nginx服务器根目录下的leanpm文件夹。同时还代理了后端的上下文路径 leanpm,这样的话我们前端只要调用前端服务器的ip + leanpm 即可自动代理到后台服务器,这种做法不但隐藏了后端服务器的真实ip,还可以处理跨域问题,可谓一举两得。

例:访问 http://前端服务器ip:8084/leanpm/xxx 会自动代理到后台服务器 http://后端服务器ip:后台端口/leanpm/xxxx

不知道你有没有这样想过,如果这是几个独立互不干扰的项目,我们通过不同的端口来代理不同的项目,这是可以理解的。但是,如果这几个项目互为子系统的话,我们这样的做法就显得不太妥当,虽然当然这种做法本质上也不会产生什么问题。

不过要是我们不用端口而是用不同的名称来区分不同的子系统是不是就会更加合理一些呢,比如:父系统 http://cnblogs.com 子系统一: http://cnblogs.com/admin 子系统二:http://cnblogs.com/article 。使用这种方式进行代理的话,我们可以更加直观的看出不同系统的关系,而且名称相较于端口号也会更利于理解记住。

实践

上传资源文件,目录如下

.
├─conf
│ ├─... # 其他文件
│ └─nginx.conf
│
├─html # 资源存放目录 
│ ├─home # 父系统
│ │ └─static
│ │   ├─css
│ │   ├─fonts
│ │   └─js
│ │     ├─g
│ │     └─V
│ ├─article # 子系统一
│ │  └─static
│ │    ├─css
│ │    ├─fonts
│ │    └─js
│ │      ├─g
│ │      └─V
│ ├─index.html
│ └─50x.html
└─... # 其他文件

修改nginx的配置

server {
        listen       80;
        server_name  localhost;
        
        // 父系统 使用 http://ip:80/home 访问
        location /home {
            root   home;     //父系统资源目录   
            index  index.html index.htm;
        }

        location /home-back/ { //父系统后台context-Path
            proxy_pass http:   http://父系统后台服务器ip:端口号/home-back/;
            proxy_read_timeout 150;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        // 子系统一地址 使用 http://前端服务器ip:80/article 访问         
        location /article{    
            alias article;       //子系统一资源目录     
            index index.html;

        }

        location /article-back/ {  //子系统的后端 contex-Path
            proxy_pass http://子系统一后台服务器ip:端口号/article-back/;
            proxy_pass_header Server;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_read_timeout 150;
           }

    }

注意:当指定目录的时候,要注意虚拟目录alias和root目录的区别。

上面的配置中如果配置子系统资源目录的时候 使用的是root而不是alias,那么访问 http://前端服务器ip:80/article/a.html 实际指的是 /html/article/article/a.html,这样会报404错误。

修改前端配置文件

前端项目打包时修改 publicPath,配置资源的访问路径,这里我们就要将父系统设为 home,子系统一设置为 article,如果不进行配置的话访问css等静态资源时,使用的会是如下路径 http://前端服务器ip:80/css/aaa.css,因为配置了代理,所以这里会找不到资源文件,报404错误

测试

父系统访问 http://前端服务器ip:80/home

子系统一访问 http:///前端服务器ip:80/article

总结

这篇文章主要讲解如何使用nginx在同一个端口下,使用不同的名称来代理部署不同的项目。主要需要注意nginx.conf中关于location的配置,以及虚拟目录alias和root目录的区别。

Nginx虚拟目录alias和root目录

nginx是通过alias设置虚拟目录,在nginx的配置中,alias目录和root目录是有区别的:
1)alias指定的目录是准确的,即location匹配访问的path目录下的文件直接是在alias目录下查找的;
2)root指定的目录是location匹配访问的path目录的上一级目录,这个path目录一定要是真实存在root指定目录下的;
3)使用alias标签的目录块中不能使用rewrite的break(具体原因不明);另外,alias指定的目录后面必须要加上"/“符号!!
4)alias虚拟目录配置中,location匹配的path目录如果后面不带”/",那么访问的url地址中这个path目录后面加不加"/“不影响访问,访问时它会自动加上”/";
但是如果location匹配的path目录后面加上"/",那么访问的url地址中这个path目录必须要加上"/",访问时它不会自动加上"/"。如果不加上"/",访问就会失败!
5)root目录配置中,location匹配的path目录后面带不带"/",都不会影响访问

举例说明(比如nginx配置的域名是www.wangshibo.com):
示例一
location /huan/ {
alias /home/www/huan/;
}
在上面alias虚拟目录配置下,访问http://www.wangshibo.com/huan/a.html实际指定的是/home/www/huan/a.html。

注意:alias指定的目录后面必须要加上"/",即/home/www/huan/不能改成/home/www/huan

上面的配置也可以改成root目录配置,如下,这样nginx就会去/home/www/huan下寻找http://www.wangshibo.com/huan的访问资源,两者配置后的访问效果是一样的!
location /huan/ {
root /home/www/;
}

示例二
上面的例子中alias设置的目录名和location匹配访问的path目录名一致,这样可以直接改成root目录配置;那要是不一致呢?
再看一例:
location /web/ {
alias /home/www/html/;
}

访问http://www.wangshibo.com/web的时候就会去/home/www/html/下寻找访问资源。
这样的话,还不能直接改成root目录配置。
如果非要改成root目录配置,就只能在/home/www下将html->web(做软连接,即快捷方式),如下

location /web/ {
root /home/www/;
}

#ln -s /home/www/web /home/www/html //即保持/home/www/web和/home/www/html内容一直

所以,一般情况下,在nginx配置中的良好习惯是:
1)在location /中配置root目录;
2)在location /path中配置alias虚拟目录。

如下一例:
server {
listen 80;
server_name www.wangshibo.com;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;

location / {
    root /var/www/html;
    }

location /haha { //匹配的path目录haha不需要真实存在alias指定的目录中
alias /var/www/html/ops/; //后面的"/"符号一定要带上
rewrite ^/opp/hen.php(.*)$ /opp/hen.php?s=KaTeX parse error: Expected 'EOF', got '#' at position 13: 1 last; #̲ rewrite ^/opp/… /opp/hen.php?s=$1 last;
}

location /wang { //匹配的path目录wang一定要真实存在root指定的目录中(就/var/www/html下一定要有wang目录存在)
root /var/www/html;
}
}

=再看下面一例=

[root@web01 vhosts]# cat www.kevin.com.conf
server {
      listen      80;
      server_name www.kevin.com;
     
      access_log  /data/nginx/logs/www.kevin.com-access.log main;
      error_log  /data/nginx/logs/www.kevin.com-error.log;
     
 location / {
      root /data/web/kevin;
      index index.php index.html index.htm;
      }
 
  location /document/ {
      alias /data/web/document/;
}
 
  }
 
[root@web01 vhosts]# ll /data/web/
total 4
drwxrwxr-x 2 app app   33 Nov 22 10:22 document
drwxrwxr-x 4 app app  173 Sep 23 15:00 kevin
 
如上配置后,则:
访问http://www.kevin.com/admin   就会找到/data/web/kevin/admin目录
访问http://www.kevin.com/document  就会找到/data/web/document 目录 (里面是一些静态资源)

如果有什么见解或指正,欢迎在下方评论

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值