Spring cloud gateway自定义filter以及负载均衡

Posted woniu4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring cloud gateway自定义filter以及负载均衡相关的知识,希望对你有一定的参考价值。

自定义全局filter

package com.example.demo;

import java.nio.charset.StandardCharsets;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * @author woniu
 * @date 2019/10/11 16:07
 */
@Component
public class CustomerTokenFilter implements GlobalFilter, Ordered{

    private static final Log log = LogFactory.getLog(GatewayFilter.class);

    private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
        log.info("contain token " + exchange.getRequest().getHeaders().containsKey("token"));
        log.info("token is " + exchange.getRequest().getHeaders().get("token"));
        if (exchange.getRequest().getPath().value().contains("success") || exchange.getRequest().getPath().value()
                .contains("rest")) {
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {
                        Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
                        if (startTime != null) {
                            log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
                        }
                    })
            );
        } else {
            byte[] bytes =
                    "{"status":429,"msg":"Too Many Requests","data":{}}".getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
            ServerHttpResponse serverHttpResponse = exchange.getResponse();
            serverHttpResponse.setStatusCode(HttpStatus.OK);
            return exchange.getResponse().writeWith(Flux.just(buffer));
        }

    }

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

自定义LoadBalanceRule

package com.example.demo;

import java.util.List;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;
/**
 * @author woniu
 * @date 2019/10/12 16:20
 */
public class CustomerLoadBalanceRule extends AbstractLoadBalancerRule {

    private static final Log log = LogFactory.getLog(CustomerLoadBalanceRule.class);

    @Override
    public Server choose(Object key) {
        log.info("key is " + key);
        List<Server> servers = this.getLoadBalancer().getReachableServers();
        log.info("servers " + servers);
        if (servers.isEmpty()) {
            return null;
        }
        if (servers.size() == 1) {
            return servers.get(0);
        }
        return randomChoose(servers);
    }
    /**
     *
     * <p>随机返回一个服务实例 </p>
     * @param servers 服务列表
     */
    private Server randomChoose(List<Server> servers) {
        int randomIndex = RandomUtils.nextInt(servers.size());
        return servers.get(randomIndex);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
}

application.properties 配置

logging.level.org.springframework.cloud.gateway: TRACE
logging.level.org.springframework.http.server.reactive: TRACE
logging.level.org.springframework.web.reactive: TRACE
logging.level.org.springframework.boot.autoconfigure.web: TRACE

spring.cloud.gateway.routes[0].id: 1bcd
spring.cloud.gateway.routes[0].uri:  lb://my-load-balanced-service
spring.cloud.gateway.routes[0].predicates[0].name: Path
spring.cloud.gateway.routes[0].predicates[0].args[0]: /rest/**


my-load-balanced-service.ribbon.listOfServers: http://woniu.com
my-load-balanced-service.ribbon.NFLoadBalancerRuleClassName: com.example.demo.CustomerLoadBalanceRule

pom.xml引入的dependency

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>

 

githup地址:https://github.com/baishi6582/wns/tree/master/springgatewaydemo

以上是关于Spring cloud gateway自定义filter以及负载均衡的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Cloud Gateway 中添加特定于路由的自定义过滤器

spring cloud gateway自定义过滤器

如何使用 Spring Cloud Gateway 自定义过滤器过滤每个请求?

spring cloud 2.x版本 Gateway自定义过滤器教程

Spring Cloud —— Gateway 服务网关

Spring Cloud Alibaba - 26 Gateway-自定义谓词工厂