【分布式金融交易模型】服务网关

1. 微服务gateway网关

参考:
https://javaweixin6.blog.csdn.net/article/details/107735759
谷粒商城17-SpringCloud Gateway网关介绍

https://javaweixin6.blog.csdn.net/article/details/107736472
谷粒商城18-注册“gulimall-gateway”服务到Nacos

https://javaweixin6.blog.csdn.net/article/details/107736535
谷粒商城19-gulimall-gateway网关使用案例

1.1. 不用网关所产生的问题1(请求同一功能的不同微服务需要重新修改请求端口)

后台管理系统(如浏览器)需要给商品服务、订单服务等各个服务发送请求,现在要想对商品做CRUD,而发请求就得知道商品服务等各个服务的地址。假设一开始请求的是1号商品服务的地址,在1号商品服务掉线后,那么要使业务正常运行,就得将该请求改为2号商品服务的地址(即动态切换到一个能用的商品服务中),这样在后台代码中修改各个服务所在的端口太麻烦。
在这里插入图片描述
改进:后台管理系统给任何服务发送请求都经过网关,网关帮我们动态地路由到各个服务。且网关也能从注册中心中实时感知每一个服务的上下线,总会能帮我们把请求正确路由到指定位置;

1.2. 不用网关所产生的问题2(每个微服务都开发权限、监控等功能,这样会导致冗余)

每一个请求到微服务后,后期都需要加权限、监控等等。而如果每个请求到每一个微服务都做这个事(在每个服务都重复开发权限、监控等功能),这样太冗余。如:
在这里插入图片描述
改进:后台管理系统先请求API网关,在网关层将权限、监控等统一的功能统一处理,再将请求代转给每一个服务。
在这里插入图片描述

1.3. Gateway

网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。而 springcloud gateway作为 SpringCloud 官方推出的第二代网关框架,取代了 Zuul 网关。

1.3.1. Gateway的三大概念

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.3.RELEASE/reference/html/#glossary
  1. Route: The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates, and a collection of filters. A route is matched if the aggregate predicate is true.
    Route为路由,客户端发一个请求个网关,网关把请求路由到指定的服务中去。路由之间的区分采用的是ID。当次请求的路径为URI,只要路由匹配了断言,那么该次请求就能到达指定的路径。
  2. Predicate: This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange. This lets you match on anything from the HTTP request, such as headers or parameters.
    请求发送给网关,是否需要到达某一个服务,是需要进行条件判断的,该条件就是Predicate断言。让开发者匹配当次请求的任何信息,比如请求头或者请求参数。网关根据请求参数,或者请求头的不同,路由到不同的服务,判断路由到不同的服务,就是进行断言。
  3. Filter: These are instances of Spring Framework GatewayFilter that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.
    Filter为Spring提供的网关过滤器,过滤器就是请求到后台服务的时候,进行一次过滤,后台给前端响应,再次进行一次过滤。在请求到后台之前,或者响应之前都能进行修改过滤。

1.3.2. SpringCloud Gateway工作流程

在这里插入图片描述
客户端将请求到达网关,先利用Predicate 断言,判定是否符合某个路由Route规则。
如果符合了,就让路由转发到指定的后台服务中,在到达后台之前,需要进行一系列的filter,进行过滤。

在Gateway的官方文档中,如下的两节,写明了有哪些路由断言的工厂,和哪些过滤器工厂。

1.3.3. 给交易模型配置网关

1.3.3.1. 配置pom

在这里插入图片描述
注意,网关也要注册到服务注册/发现(这样它才能发现其他服务所在的位置)以及配置中心,所以要加相关的依赖。

1.3.3.2. 配置application.yml(nacos注册中心、gateway网关)
1.3.3.3. 配置bootstrap.properties(nacos配置中心)

在这里插入图片描述

#服务名
spring.application.name=gateway
# 配置中心url
#spring.cloud.nacos.config.server-addr=120.26.160.234:8848
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
#配置命名空间
#spring.cloud.nacos.config.namespace=9cdb5e05-e6fb-43fb-a770-1a571ab04182

配置命名空间的步骤:

  1. 新建名字空间
    在这里插入图片描述
    在这里插入图片描述
  2. 新建配置
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  3. namespace指定名字空间的唯一ID
    在这里插入图片描述
1.3.3.4. 启动网关

在这里插入图片描述
该网关使用Netty做的:
在这里插入图片描述

1.3.3.5. 账户开立服务和转账服务的网关测试
1.3.3.5.1. 账户开立服务
        - id:  resetpassword-gateway
          uri: lb://distributed-accopen #端口地址(请求要去的地址)
          predicates:
          	#匹配规则  *代表所有的字符
            - Path=/rest/ResetPassword/* 
          filters:
            #过滤规则  过滤掉第一个字段details。如http://127.0.0.1:25008/details/test/test  转发后变成   http://127.0.0.1:25002/test/test
            - StripPrefix=1

则URL路径为/AccLogin/*,都会跳转到lb://distributed-accopen中(lb代表作了负载均衡)
在这里插入图片描述

1.3.3.5.2. 转账服务
        - id: transfer-gateway
          uri: lb://distributed-transfer
          predicates:
            - Path=/transfer/transfer/*
          filters:
            - StripPrefix=1

则URL路径为/transfer/*,都会跳转到lb://distributed-transfer中(lb代表作了负载均衡)
在这里插入图片描述

2. gateway网关统一配置跨域

参考:
谷粒商城40 - 后端-商品服务-API-三级分类-网关统一配置跨域
https://javaweixin6.blog.csdn.net/article/details/107797387

谷粒商城39 - 前后端-商品服务-API-三级分类-配置网关路由与路径重写
https://javaweixin6.blog.csdn.net/article/details/107772429

2.1. 没有统一配置跨域导致报错的案例

在这里插入图片描述
在这里插入图片描述

localhost:8001/端口的登录页面,点击登录按钮,应跳转到http://localhost:88/api/sys/login地址,但此时会报错,这是因为由于从8001跨域到88端口,不满足浏览器的同源策略,导致登录失败。(需求检查请求头中,是否有Access-Control-Allow-Origin访问控制允许来源, 来允许跨域。)

2.2. 跨域的概念

端口号以前,稍微不一样,都不满足同源策略。
在这里插入图片描述

2.3. 跨域流程

发送非简单请求(PUT、DELETE)等,需要先发送预检请求。
在这里插入图片描述

跨源资源共享(CORS)
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

2.4. 如何实现跨域请求?

跨域失败的根本原因:目标网站和想要发送远程请求的网站不在同一域(网址的端口号、协议、域名有任何一个发生了变化)。

2.4.1. 使用nginx服务器将目标网站和想要发送远程请求的网站部署为同一个域

在这里插入图片描述

  1. 把前端项目和后端网关项目,都放在nginx服务器中。
  2. 浏览器要访问前端项目,不直接访问前端项目的地址(localhost:8001/#/login),而是访问nginx服务器的地址。
  3. 登录的时候,只要是静请求都默认代理给前端项目,动态请求由nginx反向代理到网关,网关再转给其他后端微服务。
    这样,从头到尾,访问的都是nginx的地址。
    但此方法只适合于部署的时候,不适合开发环境。

2.4.2. 后端服务配置当次请求允许跨域(分布式金融交易模型的网关跨域配置)

既然浏览器跨域首先会发一个预检请求给服务器,询问该服务器能不能跨域。那么如果服务器响应浏览器能跨域,就可以了。
在这里插入图片描述
写一个fiter过滤器,所有请求(预检请求)一进来后,放行,执行完以后,在给浏览器响应数据之前,给响应添加跨域需要的响应头字段即可。
在这里插入图片描述
这个fiter不用写在每一个服务中,只需要写在gateway服务中即可。因为最终每个服务都可能被远程服务(即都需要跨域),我们是使用网关代理浏览器请求给其他服务,在网关统一配置跨域即可解决各个微服务的跨域问题。

当浏览器发送一个预检请求到后端服务,首先会经过网关,网关的fiter会对该请求进行跨域过滤,对于没被过滤的请求,后端会响应允许该请求跨域的信号给浏览器,此时浏览器会发生真实请求给后端服务,后端服务进而响应数据。

gateway中配置了跨域过滤器fiter,其他各个后端服务不需要单独配置跨域过滤器。

2.4.2.1. 使用corsConfiguration.addAllowed**来设置服务器给浏览器返回的响应(gateway服务和转账服务中的做法)

在这里插入图片描述

package com.icbc.distributed.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.server.ServerWebExchange;

import java.nio.file.Path;

@Configuration
/**
 * 网关统一配置跨域
 **/
public class DisCorsConfiguration {
    // 网关统一配置跨域
    @Bean
    public CorsWebFilter corsWebFilter(){

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        corsConfiguration.addAllowedHeader("*");//允许跨域的请求头
        corsConfiguration.addAllowedMethod("*");//允许跨域的请求方式
        corsConfiguration.addAllowedOrigin("*");//允许跨域的请求来源
        corsConfiguration.setAllowCredentials(true);//允许携带cookie跨域

        source.registerCorsConfiguration("/**",corsConfiguration);// 任意路径都进行跨域配置

        // source:跨域的配置信息
        return new CorsWebFilter(source);
    }
}

此时,在某端口跨域访问另一个不同端口,是可以获得响应数据的。

2.4.2.2. 使用httpServletResponse.setHeader来设置服务器给浏览器返回的响应(账户开立服务中的做法)
参考:
前后端交互跨域问题
https://blog.csdn.net/qq_38321137/article/details/113309117?utm_medium=distribute.pc_category.none-task-blog-hot-1.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-1.nonecase&request_id=

在这里插入图片描述

package com.icbc.distributed.accopen.config;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
/**
 * 网关统一配置跨域方法而
 * https://zhuanlan.zhihu.com/p/347924923
 **/
public class OpenCorsConfiguration implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        //这里填写你允许进行跨域的主机ip
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        //允许的访问方法
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        //Access-Control-Max-Age 用于 CORS 相关配置的缓存
        httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        String userId = servletRequest.getParameter("userId");
        String token = servletRequest.getParameter("token");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

两种方法都是使用跨域资源共享CORS来解决浏览器请求跨域的问题的。

3. gateway网关的跨域问题和Feign的远程调用是不一样的

网关针对的是客户端(浏览器)请求路径的路由,Feign是针对后端服务内部代码调用其它后端服务接口的路由。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cashapxxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值