前后端分离,前端通过网关连接到后端多个微服务

项目介绍

  1. 前端项目 renren-fast-vue,baseurl 为 http://localhost:8080/renren-fast,默认连接到后端项目 renren-fast
  2. 后端项目 renren-fast,在端口 8080 启动
  3. 后端项目 mall-product,在端口 11000 启动

如果前端想请求后端项目 mall-product 提供的api,如何解决?

  1. 如想请求 http://localhost:11000/product/category/list/tree
  2. 需要修改前端 baseurl http://localhost:8080/renren-fasthttp://localhost:11000,这样的话,前端又会发生请求不到 renren-fast 项目下的 api
  3. 如果 mall-product 项目部署多份,分别在不同的端口启动,又怎么解决?

显然,前端请求的 baseurl 应该是一个公共路径。
那么,如何解决公共路径的问题呢?
此时,引入网关。让所有的请求,首先发送到网关,接着网关转发所有请求到相应的微服务即可。

网关微服务 mall-gateway

  1. 确保 renren-fast 和 mall-product 已经注册到注册中心 nacos 注册过程参考
  2. 创建 mall-gateway 微服务,并注册到注册中心,启动端口号 13000
  3. 修改 renren-fast-vue 前端项目的 baseurl 为 http://localhost:13000/api
  4. 解决路径问题
    1. 原来访问验证码的路径为:http://localhost:8080/renren-fast/captcha.jpg?uuid=98fcaea6-71d5-43e4-8ce3-e839de8912bf
    2. 通过网关,访问 renren-fast 后端项目,验证码的请求路径为http://localhost:13000/api/captcha.jpg?uuid=ee83f4f0-1bb8-4f0f-8f2e-d86d1ad305a7,显然访问不到,因为renren-fast后端项目在8080端口启动,并且路径为/renren-fast/captcha.jpg 而不是/api/captcha.jpg
    3. 在网关 mall-gateway 的 application.yml 增加如下配置,并重启网关微服务
      spring:
        application:
          name: mall-gateway
        cloud:
          nacos:
            discovery:
              server-addr: 127.0.0.1:8848
          gateway:
            routes:
              - id: admin_route
                uri: lb://renren-fast  # 路由到 renren-fast 后端项目, renren-fast为注册到nacos的名字
                predicates:
                  - Path=/api/** # 如果请求路径是以api开头的任意路径,则通过 nacos 路由到 renren-fast后端服务
                filters:
                  - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment} # 路径重写,如/api/captcha.jpg 会被重写成 /renfen-fast/captcha.jpg
      
      注意:要保证路由成功,在高版本的spring cloud中,需要额外引入以下依赖:
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-loadbalancer</artifactId>
              </dependency>
      
    4. 访问验证码成功:
      在这里插入图片描述

跨域问题

参考资料
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
http://www.ruanyifeng.com/blog/2016/04/cors.html

当输入用户名,密码的时候,发生跨域问题:

Access to XMLHttpRequest at 'http://localhost:13000/api/sys/login' from origin 'http://localhost:8001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

  1. 跨域
    浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 javascript 施加的安全限制。
    同源策略是指协议、域名、端口都要相同,其中一个不同都会产生跨域。

    url说明是否允许通信
    http://www.a.com/a.js
    http://www.a.com/b.js
    同一域名下允许
    http://www.a.com/lab/a.js
    http://www.a.com/script/b.js
    同一域名,不同文件夹允许
    http://www.a.com:8000/a.js
    http://www.a.com/b.js
    同一域名,不同端口不允许
    http://www.a.com/a.js
    https://www.a.com/b.js
    同一域名,不同协议不允许
    http://www.a.com/a.js
    http://70.32.121.74/b.js
    域名和域名对应ip不允许
    http://www.a.com/a.js
    http://www.script.a.com/b.js
    主域相同,子域不同不允许
    http://www.a.com/a.js
    http://a.com/b.js
    同一域名,不同二级域名不允许,这种情况下也不允许访问cookie
    http://www.cnblogs.con/a.js
    http://www.a.com/b.js
    不同域名不允许

    显然,从 http://localhost:8001 域名到 http://localhost:13000/api/sys/login 域名跳转时,违反了浏览器的同源策略,因此产生跨域。

  2. 解决跨域问题,两种方法
    方法一: 利用nginx反向代理,解决跨域问题
    在这里插入图片描述
    所有的请求都通过nginx,让 nginx 来区别请求是发送到前端还是网关。发送到网关的请求,让网关转发到相应的微服务。

    方法二:添加响应头
    因为所有的请求都会经过 gateway 网关,在请求响应的过程中,经 gateway 网关给请求添加响应头,解决跨域问题。

    参数名含义
    Access-Control-Allow-origin支持哪些来源的请求跨域
    Access-Control-Allow-Methods支持哪些方法跨域,如Get、Post、Put、Delete等
    Access-Control-Allow-Credentials跨域请求默认不包含cookie,设置为true可以包含cookie
    Access-Control-Expose-Headers跨域请求暴露的字段
    CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:
    Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
    如果想拿到更多其它字段,就必须在Access-Control-Expose-Headers里面指定
    Access-Control-Max-Age表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。
    请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效
  3. Spring Boot工程,mall-gateway 网关解决跨域【采用方法二】

    @Configuration
    public class MallCorsConfiguration {
    
        @Bean
        public CorsWebFilter corsWebFilter() {
    
            UrlBasedCorsConfigurationSource ubcs = new UrlBasedCorsConfigurationSource();
            // 对于任意路径(/**)都要配置跨域
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            // 配置跨域
            corsConfiguration.addAllowedHeader("*"); // Access-Control-Expose-Headers
            corsConfiguration.addAllowedMethod("*"); // Access-Control-Allow-Methods
            corsConfiguration.addAllowedOriginPattern("*"); // Access-Control-Allow-origin
            corsConfiguration.setAllowCredentials(true); // Access-Control-Allow-Credentials
    
            ubcs.registerCorsConfiguration("/**", corsConfiguration);
            return new CorsWebFilter(ubcs);
        }
    }
    

请求商品服务 mall-product

  1. 修改网关配置,因为之前配置的时候,默认所有请求 /api/** 都通过网关,发送到了后端服务 renren-fast。

    spring:
      application:
        name: mall-gateway
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
        gateway:
          routes:
            - id: product_route
              uri: lb://mall-product
              predicates:
                - Path=/api/product/** # 这里路径/api/product/** 比 /api/** 路径更精确,所有放在上面。否则会先匹配模糊路由,到了renren-fast服务
              filters:
                - RewritePath=/api/(?<segment>.*),/$\{segment}
            - id: admin_route
              uri: lb://renren-fast
              predicates:
                - Path=/api/**
              filters:
                - RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
    
  2. 测试经过网关,到达商品服务
    在这里插入图片描述

总结

至此,renren-fast-vue 前端通过 mall-gate 网关,成功连接到后端 renren-fast 服务和 mall-product 服务。

  • 11
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值