springcloud gateway网关浅析

网关是微服务架构中非常重要的一个组件,在微服务应用中,客户端所有的请求都是先经过网关,然后再转发到具体的微服务上,客户端无需知道具体微服务的地址,知道网关的地址即可。下面对Spring Cloud GateWay网关进行简单的聊聊。

1、单体架构
在传统的springboot单体应用中,一般只有一个后端服务,如下
在这里插入图片描述
2、微服务架构
在springcloud微服务架构中,往往有多个微服务,这些微服务可能部署在不同的机器上,而且一个微服务可能会扩容成多个相同的微服务,组成微服务集群。
在这里插入图片描述
上面的情况下,会出现如下问题

  • 添加鉴权:需要对每个微服务进行改造;
  • 流量控制:需要对每个微服务进行改造;
  • 跨域问题:需要对每个微服务进行改造;
  • 安全问题:每个微服务需要暴露自己的Endpoint (ip+端口)给客户端;

痛点其实就是各个微服务都有一个入口,没有统一的入口,这时在客户端和服务器之间增加一个节点作为唯一的入口,这个就是网关。
多个微服务之间若需要进行通信,还需要用到远程调用组件了,如OpenFeign。
在这里插入图片描述
3、网关
应用场景,有三个节点:网关、客户端、服务端,其通信对话如下
网关:客户端你好,你可以访问我了,我可以将你想发给微服务的流量进行转发,微服务处理后再将结果饭给你;
客户端:网关你好,你没有赚差价吧?
网关:客户端你好,我可能会加些请求头,做下认证、鉴权、限流;
客户端:网关你好,微服务自己可以做吧?
网关:客户端你好,每个微服务都自己加,很麻烦了,也不统一呀;
服务端:网关你好,你会为微服务保密地址吗?
网关:服务端你好,当然会保密了,客户端只知道我网关的地址,不需要知道微服务的地址,只需要知道路由就行,剩下的交给我来转发;

4、Spring Cloud Gateway网关
gateway的工作流程如下
在这里插入图片描述
客户端的请求到达网关后,先经过断言Predicate判断,符合那个路由规则,转换映射后端的某个服务;然后经过过滤器链,对请求进行拦截,如添加请求头,参数校验等,最后再将请求转发到实际的后端服务;后端服务处理完成之后,将结果返回给网关,网关再次进行过滤,然后将结果返回给客户端。
断言配置的规则示例如下

spring:
  cloud:
    gateway:
      routes:
        - id: route_order # 订单微服务路由规则
          uri: lb://order # 负载均衡,将请求转发到注册中心注册的order 服务
          predicates: # 断言
            - Path=/api/order/** # 如果前端请求路径包含 api/order,则应用这条路由规则
          filters: #过滤器
            - RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的api替换成空

        - id: route_member # 会员微服务路由规则
          uri: lb://member # 负载均衡,将请求转发到注册中心注册的 member 服务
          predicates: # 断言
            - Path=/api/member/** # 如果前端请求路径包含 api/member,则应用这条路由规则
          filters: #过滤器
            - RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的 api 替换成空

其中uri: lb://member,标识将请求转发给member微服务,且支持负载均衡,lb是loadbalance的缩写。

5、Spring Cloud Gateway动态路由
微服务架构中,不会直接通过IP+端口的方式来访问微服务,而是通过服务名的方式来访问,这时引入了注册中心,多个微服务将自己注册到注册中心,这样注册中心就保存了微服务与IP+端口的映射信息。
在这里插入图片描述
动态路由就算添加一个微服务或者IP地址变了,网关都可以感知到,但是配置是不需要更新的,微服务的集群个数、IP和端口是动态可变的。
那么此时整合各个组件之后,整体的架构中请求的转发如下
在这里插入图片描述

客户端先将请求发送给Nginx,然后转发给网关,网关经过断言匹配到一个路由后,将请求进行过滤然后转发给知道uri,这个uri可以配置成微服务的名字,gateway网关从注册中心拉取注册表,就能知道服务名对应的IP+端口,若一个微服务部署了多台机器,则通过负载均衡进行请求的转发。

6、Spring Cloud Gateway过滤
gateway中的过滤器就是统一对请求和响应进行一些过滤操作,安装请求和响应分为两种:Pre类型和Post类型。

  • Pre 类型:在请求被转发到微服务之前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。
  • Post 类型:微服务处理完请求后,返回响应给网关,网关可以再次进行处理,例如修改响应内容或响应头、日志输出、流量监控等。

按作用范围也可以分为:全局过滤器和局部过滤器。

  • GlobalFilter:全局过滤器,应用在所有路由上的过滤器;
  • GatewayFilter:局部过滤器,应用在单个路由或一组路由上的过滤器。标红色表示比较常用的过滤器;

gateway网关也自带了很多过滤器,详细查看官网。
在gateway网关中做一个自定义的登录认证过滤器,如客户端登录时,将用户名和密码发送给网关,网关转发给认证服务器,如果账号密码正确,则拿到一个JWT token,然后客户端再访问应用服务时,先将请求发送给网关,网关统一做token认证,如果token符合条件,再将请求转发给应用服务,流程如下
在这里插入图片描述
实例
过滤器代码

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        String token = request.getHeaders().getFirst("token");
        if(!antPathMatcher.match("/login", path)) {
            if(StringUtils.isEmpty(token) || !"admin".equals(token)) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            }
        }
        //内部服务接口,不允许外部访问
        if(antPathMatcher.match("/**/inner/**", path)) {
            ServerHttpResponse response = exchange.getResponse();
            return out(response);
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private Mono<Void> out(ServerHttpResponse response) {
        String message = "口令失效.";
        byte[] bits = message.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        //指定编码,否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }
}

未携带token
在这里插入图片描述
携带token
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值