Vaadin 24 LONG_POLLING推送报错及Tomcat适配问题排查
Vaadin 23升级至24后Tomcat下Atmosphere推送警告问题解析
问题背景
从Vaadin 23升级到Vaadin 24后,使用Tomcat嵌入式服务器时,控制台频繁出现两类Atmosphere相关的WARN日志,切换到Undertow服务器后问题消失,确认该问题与Tomcat服务器相关。
第一类警告日志
2023-03-09T16:32:14.882+02:00 WARN 4348 --- [sphere-Shared-0] org.atmosphere.cpr.DefaultBroadcaster : This message Entry{message=com.vaadin.flow.server.communication.AtmospherePushConnection$PushMessage@428f5045, type=RESOURCE, future=org.atmosphere.cpr.BroadcasterFuture@ca43632} will be lost 2023-03-09T16:32:14.882+02:00 WARN 4348 --- [sphere-Shared-0] org.atmosphere.cpr.DefaultBroadcaster : Failed to submit broadcast handler runnable to for Broadcaster/* java.lang.IllegalStateException: The request object has been recycled and is no longer associated with this facade at org.apache.catalina.connector.RequestFacade.getHeader(RequestFacade.java:675) ~[tomcat-embed-core-10.1.5.jar:10.1.5] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest.getHeader(StrictHttpFirewall.java:714) ~[spring-security-web-6.0.2.jar:6.0.2] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.http.HttpServletRequestWrapper.getHeader(HttpServletRequestWrapper.java:88) ~[tomcat-embed-core-10.1.5.jar:6.0] at org.atmosphere.cpr.AtmosphereRequestImpl.getHeader(AtmosphereRequestImpl.java:353) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.AtmosphereRequestImpl.getHeader(AtmosphereRequestImpl.java:338) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at com.vaadin.flow.server.communication.LongPollingCacheFilter.filter(LongPollingCacheFilter.java:56) ~[flow-server-24.0.0.jar:24.0.0] at org.atmosphere.cpr.BroadcasterConfig.filter(BroadcasterConfig.java:452) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster.perRequestFilter(DefaultBroadcaster.java:822) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster.deliverPush(DefaultBroadcaster.java:695) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster.push(DefaultBroadcaster.java:572) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster$1.run(DefaultBroadcaster.java:423) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na] at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395) ~[na:na] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[na:na] at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[na:na] at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[na:na] at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[na:na] at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[na:na]
成因
Vaadin 24配套的Atmosphere版本(atmosphere-runtime-3.0.0.slf4jvaadin2)与Tomcat 10的请求回收机制存在兼容冲突:Tomcat在请求处理完成后会快速回收RequestFacade对象,但Atmosphere的异步广播任务仍在尝试访问该已被回收的请求对象(比如读取Header),从而触发IllegalStateException,导致推送消息丢失。
修复方案
- 升级Vaadin版本:Vaadin在24.0.1及后续小版本中修复了该兼容问题,建议直接升级到最新的24.x稳定版。
- 调整Tomcat配置:若暂时无法升级Vaadin,可修改Tomcat的请求回收策略:
对于嵌入式Tomcat,通过代码配置Connector的recycleStandardRequests属性为false:
对于独立Tomcat,修改TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.addConnectorCustomizers(connector -> { ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setRecycleStandardRequests(false); });server.xml中的Connector配置,添加recycleStandardRequests="false":<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" recycleStandardRequests="false"/> - 切换服务器:如已验证的方案,换成Undertow或Jetty服务器,规避Tomcat的请求回收机制冲突。
第二类警告日志
2023-03-09T16:32:14.881+02:00 WARN 4348 --- [phere-Shared-61] org.atmosphere.cpr.DefaultBroadcaster : This message com.vaadin.flow.server.communication.AtmospherePushConnection$PushMessage@4ad4f0be will be lost for AtmosphereResource 48727133-d436-42aa-ab43-903ea948851d, adding it to the BroadcasterCache 2023-03-09T16:32:14.881+02:00 WARN 4348 --- [phere-Shared-61] org.atmosphere.cpr.DefaultBroadcaster : Failed to execute a write operation for Broadcaster /* java.lang.IllegalStateException: The request object has been recycled and is no longer associated with this facade at org.apache.catalina.connector.RequestFacade.removeAttribute(RequestFacade.java:549) ~[tomcat-embed-core-10.1.5.jar:10.1.5] at org.apache.catalina.core.ApplicationHttpRequest.removeAttribute(ApplicationHttpRequest.java:281) ~[tomcat-embed-core-10.1.5.jar:10.1.5] at jakarta.servlet.ServletRequestWrapper.removeAttribute(ServletRequestWrapper.java:268) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.ServletRequestWrapper.removeAttribute(ServletRequestWrapper.java:268) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.ServletRequestWrapper.removeAttribute(ServletRequestWrapper.java:268) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.ServletRequestWrapper.removeAttribute(ServletRequestWrapper.java:268) ~[tomcat-embed-core-10.1.5.jar:6.0] at jakarta.servlet.ServletRequestWrapper.removeAttribute(ServletRequestWrapper.java:268) ~[tomcat-embed-core-10.1.5.jar:6.0] at org.atmosphere.cpr.AtmosphereRequestImpl.removeAttribute(AtmosphereRequestImpl.java:681) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster.executeAsyncWrite(DefaultBroadcaster.java:915) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at org.atmosphere.cpr.DefaultBroadcaster$2.run(DefaultBroadcaster.java:477) ~[atmosphere-runtime-3.0.0.slf4jvaadin2.jar:3.0.0.slf4jvaadin2] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
是否需要关注
这类警告表明推送消息写入失败,消息被临时存入BroadcasterCache等待重试。如果只是偶尔出现,通常不会影响业务;但频繁出现时,可能导致前端接收消息延迟、甚至部分消息永久丢失,进而影响实时交互功能(比如推送通知、实时数据更新),因此建议修复根源问题。
内容的提问来源于stack exchange,提问作者alexanoid
相关产品推荐
相关产品推荐

