spring cloud gateway实践

2019-11-18  本文已影响0人  pilisiyang

Spring Cloud Gateway简介

Spring Cloud Gateway是spring官方替代zuul作为网关的解决方案.

Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux.

基于Spring Boot 2.X 和 Spring Webflux,不能在Servlet容器中运行,采用非阻塞API,相比zuul,优化了很多配置。

相关词汇

  • Route: 路由网关构建过滤规则,由id,目标url,Predicate规则,Filter定义,如果Predicate的结果为true,则匹配到路由。
  • Predicate: Java 8 Function Predicate,它可以接受输入参数,返回一个布尔值结果,靠它匹配请求的path,headers ,参数。
  • Filter: 路由过程中的filter,分为 GlobalFilter(全局过滤器) ,GatewayFilter。

工作流程

这是官方文档中的流程,client 向 gateway 发送请求,首先在 Gateway Handler Mapping 中匹配路由,如果匹配到就将请求传递到对应的 Handler ,Handler再执行设置的过滤器链,最后将请求发送到代理的服务。

内置Predicate

过滤器

以上都是可以在application.yml中配置的内置过滤器,如果无法满足开发要求,可以自己在java DSL中配置。

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("cos3", predicateSpec -> predicateSpec.path("/cos3/**")
                        .filters(gatewayFilterSpec -> {
                            gatewayFilterSpec.rewritePath("/cos3/(?<segment>.*)", "/$\\{segment}");
                            gatewayFilterSpec.filters(jwtFilter);
                            gatewayFilterSpec.preserveHostHeader();
                            gatewayFilterSpec.removeRequestHeader(HttpHeaders.AUTHORIZATION);
                            return gatewayFilterSpec;
                        })
                        .uri(cos3URI)
                )
                .build();
    }

自定义过滤器

GlobalFilters

这种过滤器针对的是全局路由,还区分了 pre 和 post 两种阶段,确定代码是指在路由前执行还是路由后执行。
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter a() {
    return (exchange, chain) -> {
        log.info("pre");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            log.info("post");
        }));
    };
}

GatewayFilter

这种过滤器针对的单独的路由,需要自己配置。
    @Bean
    public GatewayFilter sessionAuthenticationFilter() {
        return (exchange, chain) -> {
            String userMobile = exchange.getAttribute("User");

            if (userMobile == null) {
                log.info("session中不存在用户信息!");
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.FORBIDDEN);
                return Mono.empty();
            }

            return chain.filter(exchange);
        };
    }

转发日志

在VM Options设置启动参数 -Dreactor.netty.http.server.accessLogEnabled=true

在logback.xml文件配置

 <appender name="accessLog" class="ch.qos.logback.core.FileAppender">
        <file>access_log.log</file>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="accessLog" />
    </appender>

    <logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
        <appender-ref ref="async"/>
    </logger>
上一篇下一篇

猜你喜欢

热点阅读