当前位置: 首页 > 知识库问答 >
问题:

无法在Spring云网关中启用RequestRateLimiter筛选器

陆俊智
2023-03-14

我正在尝试在Spring Cloud Gateway中启用RequestRateLimiter。我havr配置了其他过滤器,甚至是自定义过滤器,但当我将其添加到我的路由中时:

 filters:
    - StripPrefix=1
    - name: RequestRateLimiter
      args:
        redis-rate-limiter.replenishRate: 2
        redis-rate-limiter.burstCapacity: 3
@Configuration
@SpringBootApplication
@ComponentScan({ "com.skios.ms.gateway" })
@EnableDiscoveryClient
public class GatewayApplication implements ApplicationListener<ApplicationReadyEvent> {
    private Logger logger = LoggerFactory.getLogger(GatewayApplication.class);

    @Autowired
    private Environment environment;

    public static Map<String, String> versions;

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(GatewayApplication.class);
        SimpleCommandLinePropertySource source = new SimpleCommandLinePropertySource(args);
        if (!source.containsProperty("spring.profiles.active") && !System.getenv().containsKey("SPRING_PROFILES_ACTIVE"))
            app.setAdditionalProfiles("local");
        app.setWebApplicationType(WebApplicationType.REACTIVE);
        app.run(args);
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        logger.info("Loaded profile: {}", Arrays.toString(environment.getActiveProfiles()));
    }

    @Bean
    @Primary
    public CorsConfiguration corsConfiguration(RoutePredicateHandlerMapping routePredicateHandlerMapping) {
        CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
        Arrays.asList(HttpMethod.OPTIONS, HttpMethod.PUT, HttpMethod.GET, HttpMethod.DELETE, HttpMethod.POST, HttpMethod.PATCH).forEach(m -> corsConfiguration.addAllowedMethod(m));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.addAllowedHeader("*");
        routePredicateHandlerMapping.setCorsConfigurations(new HashMap<String, CorsConfiguration>() {
            {
                put("/**", corsConfiguration);
            }
        });

        return corsConfiguration;
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        return http.csrf().disable().build();
    }
}

我得到了这个异常(当然,如果我移除RequestRateLimiter筛选器并只保留StripPrefix条目,一切正常。我已经删除了异常的代码):

    2019-07-07 20:46:14.514 ERROR 1 --- [or-http-epoll-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [af6d0b2b] Error [java.lang.UnsupportedOperationException] for HTTP GET "/orion/v2/entities", but ServerHttpResponse already committed (403 FORBIDDEN)
    2019-07-07 20:46:14.525 ERROR 1 --- [or-http-epoll-2] r.n.http.server.HttpServerOperations     : [id: 0xaf6d0b2b, L:/172.30.41.45:8080 - R:/10.135.138.40:54598] Error starting response. Replying error status

    java.lang.UnsupportedOperationException: null
        at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:99) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory.lambda$null$0(SetResponseHeaderGatewayFilterFactory.java:32) ~[spring-cloud-gateway-core-2.1.2.RELEASE.jar:2.1.2.RELEASE]
        at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:73) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:32) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoCallableOnAssembly.call(MonoCallableOnAssembly.java:90) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:135) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.Mono.subscribe(Mono.java:3848) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:74) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDoFinallyFuseable.subscribe(MonoDoFinallyFuseable.java:48) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.Mono.subscribe(Mono.java:3848) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
[..]
reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.Mono.subscribe(Mono.java:3848) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:172) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekFuseable.subscribe(MonoPeekFuseable.java:70) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:56) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoPeekTerminal.subscribe(MonoPeekTerminal.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.core.publisher.MonoOnAssembly.subscribe(MonoOnAssembly.java:61) ~[reactor-core-3.2.10.RELEASE.jar:3.2.10.RELEASE]
        at reactor.netty.http.server.HttpServerHandle.onStateChange(HttpServerHandle.java:64) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
        at reactor.netty.tcp.TcpServerBind$ChildObserver.onStateChange(TcpServerBind.java:226) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
        at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:442) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:91) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:161) ~[reactor-netty-0.8.9.RELEASE.jar:0.8.9.RELEASE]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297) ~[netty-codec-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:796) ~[netty-transport-native-epoll-4.1.36.Final-linux-x86_64.jar:4.1.36.Final]
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:432) ~[netty-transport-native-epoll-4.1.36.Final-linux-x86_64.jar:4.1.36.Final]
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:333) ~[netty-transport-native-epoll-4.1.36.Final-linux-x86_64.jar:4.1.36.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
        at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Assembly trace from producer [reactor.core.publisher.MonoIgnoreThen] :
        reactor.core.publisher.Mono.then(Mono.java:4078)
        org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory.lambda$apply$1(SetResponseHeaderGatewayFilterFactory.java:31)
    Error has been observed by the following operator(s):
        |_  Mono.then ⇢ org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory.lambda$apply$1(SetResponseHeaderGatewayFilterFactory.java:31)
        |_  Mono.defer ⇢ org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
        |_  Mono.doOnSuccessOrError ⇢ org.springframework.cloud.gateway.filter.GatewayMetricsFilter.filter(GatewayMetricsFilter.java:60)

[...]

org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:66)
        |_  Mono.doOnSuccess ⇢ org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:67)

共有1个答案

闽康安
2023-03-14

我想我知道你的问题是什么。是否配置了密钥解析器?如果没有,默认情况下过滤器将返回403。将denyemptykey:false添加到筛选器arg,以允许通信量。您还可以在Java配置中配置密钥解析器。如果有多个bean,可以在application.yml文件中引用这些bean。有关更多信息,请参见https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.release/single/spring-cloud-gateway.html#_redis_rateLimiter

由于我无法访问示例应用程序,这是我的猜测工作。我创建了一个小应用程序,在本地运行只有这两个过滤器没有问题。

我使用了文档中的密钥解析器。

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
spring.cloud.gateway:
  routes:
    - id: test
      uri: https://google.com
      predicates:
        - Path=/test/**
      filters:
        - StripPrefix=1
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 2
            redis-rate-limiter.burstCapacity: 3

因此,如果我连续访问http://localhost:8080/test?user=tysewyn 5次(例如使用邮递员),最后2次将返回429-太多请求

顺便说一句:不过,这并不能解释为什么您会得到这个stacktrace。

 类似资料:
  • 我正在Spring Boot项目(版本2.2.6)中使用Spring Cloud Gateway和Spring Security。我有一个自定义的预过滤器,它需要在将请求转发给下游服务之前向请求添加头部。Pre过滤器需要读取Spring Security的Authentication对象以获取权限,然后才能添加头部(它需要根据权限进行一些查找)。由于Spring Cloud Gateway是反应式

  • 我试图通过spring启用hibernate过滤器,方法是tyring指向一个用自定义注释注释的服务实现方法并向该方法添加建议。我希望启用自定义筛选器,它在扩展的所有实体上添加一个差异器。因此,我创建了自定义注释,并在需要的方法上使用它。它成功地拦截了该方法,但当我记录变量值时,变量值显示为空,过滤器也没有设置。 该项目是一个Spring-Boot2应用程序,我使用spring aop创建方面。我

  • 我正在研究一个示例poc,我正在尝试集成Spring云api网关 在我的pom.xml中,我有 在我的应用程序中。yml我有 在我的主课上 我能够直接从它们各自的端口访问服务,但是当我试图从端口网关端口ie 9191访问api时,我得到 ***2022-09-08 16:23:34.644错误4128-[ctor-http-nio-3]a . w . r . e . abstracterrorwe

  • 我正在使用spring cloud网关过滤器,希望通过过滤请求,但order不使用注释 我试着交换过滤器的顺序,但不起作用。 我期望输出: 但实际输出:

  • 我有一个Spring Boot应用程序正在尝试使用Spring Cloud Gateway访问一些微服务。我使用的代码基于以下位置的说明: 基本上,我的应用程序复制了该站点上提供的代码,包括作者创建的两个测试微服务: 和 我的实际网关代码与作者的类似: package com . betterjavacode . API gateway demo . config; 不幸的是,当我运行此应用程序时