alibaba / Sentinel

A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)
https://sentinelguard.io/
Apache License 2.0
22.32k stars 8k forks source link

Sentinel 1.7.1 版本,SpringMVC模式后台报错 #1392

Closed coolyujiyu closed 4 years ago

coolyujiyu commented 4 years ago

版本:

SpringBoot:2.2.6.RELEASE SpringCloud:Hoxton.SR3 SpringCloud Alibaba:2.2.0.RELEASE Sentinel:1.7.1 JDK:1.8 运行环境:undertow

使用Demo里面的案例来配置了自动埋点

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
         SentinelWebMvcConfig config = new SentinelWebMvcConfig();
          config.setBlockExceptionHandler(new TimeBlockExceptionHandler());
          config.setHttpMethodSpecify(true);
          registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
    }

然后流量控制没有问题,但是后台一直在报错

2020-04-09 14:02:37.735 ERROR [system,fa92d2578e7f1288,fa92d2578e7f1288,false] 24904 --- [ XNIO-1 task-19] o.s.web.servlet.HandlerExecutionChain    : HandlerInterceptor.afterCompletion threw exception

com.alibaba.csp.sentinel.ErrorEntryFreeException: The order of entry exit can't be paired with the order of entry, current entry in context: </menus>, but expected: </menus>
    at com.alibaba.csp.sentinel.CtEntry.exitForContext(CtEntry.java:80)
    at com.alibaba.csp.sentinel.CtEntry.trueExit(CtEntry.java:108)
    at com.alibaba.csp.sentinel.CtEntry.exit(CtEntry.java:61)
    at com.alibaba.csp.sentinel.Entry.exit(Entry.java:79)
    at com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.traceExceptionAndExit(AbstractSentinelInterceptor.java:122)
    at com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.afterCompletion(AbstractSentinelInterceptor.java:87)
    at org.springframework.web.servlet.HandlerExecutionChain.triggerAfterCompletion(HandlerExecutionChain.java:179)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1136)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at brave.servlet.TracingFilter.doFilter(TracingFilter.java:67)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter.doFilter(ExceptionLoggingFilter.java:50)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at brave.servlet.TracingFilter.doFilter(TracingFilter.java:84)
    at org.springframework.cloud.sleuth.instrument.web.LazyTracingFilter.doFilter(TraceWebServletAutoConfiguration.java:138)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:109)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
sczyh30 commented 4 years ago

也帮忙提供下 ~/logs/csp/sentinel-record.log.xxx 看看有没有一些错误信息。

coolyujiyu commented 4 years ago

csp.zip 我清理了日志,然后最小化的重现了一次,整个csp的日志都在里面了

cjdxhjj commented 4 years ago

我也复现了同样的问题,经常报错。我的使用代码如下 image image image image 异常出现的次数非常频繁

cjdxhjj commented 4 years ago

我测试了下异步操作 image image

我服务方法delay 1秒,调用超出50毫秒定义为超时,时间窗口是2秒,但是100个请求里没有一个是block的,也没有报出其它异常

sczyh30 commented 4 years ago

我也复现了同样的问题,经常报错。我的使用代码如下 image image image image 异常出现的次数非常频繁

You may use SphU.asyncEntry(xxx). See https://github.com/alibaba/Sentinel/wiki/How-to-Use#resource-for-asynchronous-entries for details.

cjdxhjj commented 4 years ago

我那个test4就是异步完成时close entry,但是有一个问题,100个请求没有block的,我的超时时间是50ms,时间窗口2s,服务delay 了一秒,我日志显示是都调用到后端了

cjdxhjj commented 4 years ago

image image

cjdxhjj commented 4 years ago

image

cjdxhjj commented 4 years ago

image

sczyh30 commented 4 years ago

我那个test4就是异步完成时close entry,但是有一个问题,100个请求没有block的,我的超时时间是50ms,时间窗口2s,服务delay 了一秒,我日志显示是都调用到后端了

It's not related to this issue. Please open a new issue to discuss this.

cjdxhjj commented 4 years ago

能留个qq么?或微信,QQ上找不到群。

cjdxhjj commented 4 years ago

已经把异步的另提了一个issure

sczyh30 commented 4 years ago

csp.zip 我清理了日志,然后最小化的重现了一次,整个csp的日志都在里面了

从日志来看,像是开启了 HTTP method 前缀支持,这样的话资源名里面理论上不应该有不包含 HTTP method 前缀的 URL(比如 /orgs)。有没有引其它的 Web 适配,或者有没有什么特殊配置?

coolyujiyu commented 4 years ago

csp.zip 我清理了日志,然后最小化的重现了一次,整个csp的日志都在里面了

从日志来看,像是开启了 HTTP method 前缀支持,这样的话资源名里面理论上不应该有不包含 HTTP method 前缀的 URL(比如 /orgs)。有没有引其它的 Web 适配,或者有没有什么特殊配置?

没有了,所有的配置都在这里了

@Override

public void addInterceptors(InterceptorRegistry registry) { SentinelWebMvcConfig config = new SentinelWebMvcConfig(); config.setBlockExceptionHandler(new TimeBlockExceptionHandler()); config.setHttpMethodSpecify(true); registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**"); }

我也尝试过设置HttpMethodSpecify为false,但是还是报错

sczyh30 commented 4 years ago

csp.zip 我清理了日志,然后最小化的重现了一次,整个csp的日志都在里面了

从日志来看,像是开启了 HTTP method 前缀支持,这样的话资源名里面理论上不应该有不包含 HTTP method 前缀的 URL(比如 /orgs)。有没有引其它的 Web 适配,或者有没有什么特殊配置?

没有了,所有的配置都在这里了

@Override
public void addInterceptors(InterceptorRegistry registry) {
     SentinelWebMvcConfig config = new SentinelWebMvcConfig();
      config.setBlockExceptionHandler(new TimeBlockExceptionHandler());
      config.setHttpMethodSpecify(true);
      registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
}

我也尝试过设置HttpMethodSpecify为false,但是还是报错

可否帮忙提供一个能够复现问题的最小化的项目?社区来看一下

coolyujiyu commented 4 years ago

demo.zip

附件里面我新初始化的一个项目,随便请求几次接口就复现了 http://localhost:8080/test/test

`com.alibaba.csp.sentinel.ErrorEntryFreeException: The order of entry exit can't be paired with the order of entry, current entry in context: <GET:/error>, but expected: at com.alibaba.csp.sentinel.CtEntry.exitForContext(CtEntry.java:80) ~[sentinel-core-1.7.1.jar:1.7.1] at com.alibaba.csp.sentinel.CtEntry.trueExit(CtEntry.java:108) ~[sentinel-core-1.7.1.jar:1.7.1] at com.alibaba.csp.sentinel.CtEntry.exit(CtEntry.java:61) ~[sentinel-core-1.7.1.jar:1.7.1] at com.alibaba.csp.sentinel.Entry.exit(Entry.java:79) ~[sentinel-core-1.7.1.jar:1.7.1] at com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.traceExceptionAndExit(AbstractSentinelInterceptor.java:122) ~[sentinel-spring-webmvc-adapter-1.7.1.jar:na] at com.alibaba.csp.sentinel.adapter.spring.webmvc.AbstractSentinelInterceptor.afterCompletion(AbstractSentinelInterceptor.java:87) ~[sentinel-spring-webmvc-adapter-1.7.1.jar:na] at org.springframework.web.servlet.HandlerExecutionChain.triggerAfterCompletion(HandlerExecutionChain.java:179) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1136) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:384) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:394) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:175) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) [tomcat-embed-core-9.0.33.jar:9.0.33] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.33.jar:9.0.33] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_231] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_231] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.33.jar:9.0.33] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_231]

`

sczyh30 commented 4 years ago

看了下,应该是重复引入了 SentinelWebInterceptor。Spring Cloud Alibaba 2.2.0.RELEASE 及以上版本默认已经自动配置了 SentinelWebInterceptor,代码里不要重复配置,配置方式可参考 SCA 的文档。

sczyh30 commented 4 years ago

可以试一下 2.2.1.RELEASE 版本

coolyujiyu commented 4 years ago

看了下,应该是重复引入了 SentinelWebInterceptor。Spring Cloud Alibaba 2.2.0.RELEASE 及以上版本默认已经自动配置了 SentinelWebInterceptor,代码里不要重复配置,配置方式可参考 SCA 的文档。

我以前是没有配置的,但是不配置的话,SCA的自动注册链路,很多URL都捕获不到,不过我刚刚升级到了2.2.1.RELEASE版本,好像解决了链路注册不到的问题

如果不用这个MVC配置的话,SCA中的BlockExceptionHandler这个怎么指定呢?不然只能返回默认的错误信息:Blocked by Sentinel (flow limiting) 我看了下SCA的文档里面没有体现

coolyujiyu commented 4 years ago

QQ截图20200423213704

SCA那边的文档还是之前的配置BlockExceptionHandler方法,但是在最新版本的Sentinel里面已经没有了WebCallbackManager这个,所以我只能用上面的配置方法来指定了

SentinelWebMvcConfig config = new SentinelWebMvcConfig(); config.setBlockExceptionHandler(new TimeBlockExceptionHandler());

Icecream0211 commented 4 years ago

csp.zip 我清理了日志,然后最小化的重现了一次,整个csp的日志都在里面了

从日志来看,像是开启了 HTTP method 前缀支持,这样的话资源名里面理论上不应该有不包含 HTTP method 前缀的 URL(比如 /orgs)。有没有引其它的 Web 适配,或者有没有什么特殊配置?

没有了,所有的配置都在这里了

@Override
public void addInterceptors(InterceptorRegistry registry) {
     SentinelWebMvcConfig config = new SentinelWebMvcConfig();
      config.setBlockExceptionHandler(new TimeBlockExceptionHandler());
      config.setHttpMethodSpecify(true);
      registry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");
}

我也尝试过设置HttpMethodSpecify为false,但是还是报错

不要尝试注册SentinelWebMvcConfig了,因为starter默认配置一个SentinelWebAutoConfiguration,会注册一个SentinelWebMvcConfig。如果自己再注册一个,位置在第二个,出现异常,第一个就已经处理了,不会过滤到第二个mvcConfig中配置的interceptor中。正确的自定义BlockExceptionHandler姿势: 直接在@Configuration文件中, @Bean public BlockExceptionHandler blockExceptionHandler(){ return new XXXBlockExceptionHandler(); } 这样,自定义的BlockExceptionHandler就可以生效了

coolyujiyu commented 4 years ago

谢谢,已经解决了