微服务应用开发入门④服务网关

简述

相信通过微服务应用开发入门①web端架构演进的阅读,大家已经知道服务网关是干嘛的;

一般来说服务网关会做以下几件事情:

  • 路由:路由是API网关很核心的模块功能,此模块实现根据请求,锁定目标微服务并将请求进行转发
  • 鉴权:权限身份认证
  • 控:记录请求响应数据,api耗时分析,性能监控。
  • 日志:日志记录。
  • 限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则。

Spring Cloud Gateway

在SpringBoot1.x的版本中,一般来说用Netflix公司的zuul;(对又是netflix、Netflix是SpringCloud的开源组件大户)

但是在SpirngBoot2.x的发布后,zuul2.x的版本闭源,于是Spring团队有开发了gateway这个网关;

关于相关的资讯,以及注册中心、服务网关选型参考之前的博客SpingCloud资讯-断路器、注册中心、网关

 

一般来说: 内部请求通过feignribbon进行访问 (这个在之前的文章微服务应用开发入门③微服务组件eureka、ribbon、feign和hystrix初识有介绍)

 外部请求通过gateway做统一的路由

      1.当请求到达gateway首先Gateway Handler Mapping会判断请求是否匹配

2.如果不匹配404

3.如果匹配将其发送Gateway web handler处理。

4.Gateway web handler处理请求时会经过一系列的过滤器链;

类似zuul,在执行所有“pre”过滤器逻辑时,往往进行了鉴权、限流、日志输出等功能,以及请求头的更改、协议的转换;转发之后收到响应之后,会执行所有“post”过滤器的逻辑,在这里可以响应数据进行了修改,比如响应头、协议的转换等。

简单应用

下载项目 https://github.com/zhouxiaohei/cloud-start-demo/tree/master/cloud-gateway-demo

Predicates

Gateway Handler Mapping中用到一个概念叫Predicates,用断言来判断请求是否匹配;

Gateway为我们提供的断言有:时间断言、cookie断言、header断言、host断言、方法类型断言、路径断言等

一般我们会用到路径断言或者header断言;当然可以自定义断言

项目配置文件

大家也可以加上header断言 试试,请求头不包含X-Request-Id并且值是123的,会404;值也可以是一个正则表达式

- Header=X-Request-Id, 123

Gateway Filter 

          和zuul一样分为pre、post、也从范围上分为普通过滤器和global filter 全局过滤器。

  普通过滤器

          刚才用到了切割前缀过滤器,可以打开StripPrefixGatewayFilterFactory查看它的源码

          它不是一个全局过滤器所以需要在每个路由(route)下面去配置;下图打错了,基础==继承

  那我们现在可以仿照上面的过滤器,写一个自定义RequestTimeGatewayFilterFactory,来获取请求时间和请求参数

@Slf4j
public class RequestTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestTimeGatewayFilterFactory.Config> {

    private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    private static final String KEY = "withParams";

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(KEY);
    }

    public RequestTimeGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                        if (startTime != null) {
                            StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
                                    .append(": ")
                                    .append(System.currentTimeMillis() - startTime)
                                    .append("ms");
                            if (config.isWithParams()) {
                                sb.append(" params:").append(exchange.getRequest().getQueryParams());
                            }
                            log.info(sb.toString());
                        }
                    })
            );
        };
    }


    public static class Config {

        private boolean withParams;

        public boolean isWithParams() {
            return withParams;
        }

        public void setWithParams(boolean withParams) {
            this.withParams = withParams;
        }

    }
}

       如果要是用它,按照名称的规则来使用 ;这样转发到service-a的请求,就会打印请求时间和请求参数;

         注意点

        获取请求时间我们需要在gateway的Pre类型的过滤器(在请求真正触发之前),添加开始时间;

        而ServerWebExchange 是一个pre的过滤器,将请求时间加上去

       在post类型过滤器(请求结束以后)中去统计到底执行了多久,而chain.filter的内部类中的run()方法中相当于"post"过滤器

全局过滤器

       项目代码里面有全局过滤器AuthSignatureFilter,全局过滤器需要实现GlobalFilter;

       一般在做登录校验的时候会用到全局过滤器,以JWT为例,如果是登录的地址/api/v1/common/login就放行;

       如果是其他地址就校验header中是否有token(也有可能是别的名字);

      然后去校验合法性和有效性(JWT不支持校验有效性,需要改造)------这部分代码上没去实现哈;

      最后决定是否放行,不通过就返回HTTP状态码401(未认证)

OK,简单的服务网关之旅到这里就结束了,有问题没问题都欢迎关注我和我交流~  

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值