如何在Vaadin Flow 14中获取Atmosphere通道上下行性能数据
实现方案整体思路
Vaadin Push底层默认基于Atmosphere框架实现,本身暴露了完整的连接生命周期、消息收发钩子接口,直接对接这些钩子再加自定义的心跳探测逻辑,即可拿到双向延迟、丢包、带宽等核心指标,不需要修改Jetty embedded的底层部署配置,适配性很高。
第一步:注册Atmosphere自定义拦截器捕获通道事件
直接在Vaadin初始化配置中注入自定义Atmosphere拦截器,不需要修改Jetty的Servlet注册逻辑:
- 实现Atmosphere的
Interceptor接口,拦截所有MESSAGE_SEND、MESSAGE_RECEIVE事件,记录每个消息的时间戳、大小、对应客户端唯一标识(可绑定Vaadin SessionId) - 拦截
CONNECT、DISCONNECT、CLOSE事件,记录连接建立时长、断开原因、重连次数等基础状态指标 - 拦截器写完后,在配置文件中添加
vaadin.push.atmosphere.interceptors=你的包名.AtmospherePerformanceInterceptor即可自动加载
参考代码片段:
public class AtmospherePerformanceInterceptor implements Interceptor { @Override public Action intercept(AtmosphereResource resource, AtmosphereRequest request, AtmosphereResponse response, Object o) throws IOException { String clientId = resource.uuid(); // 绑定Vaadin Session Id与Atmosphere资源标识 VaadinSession session = VaadinSession.getCurrent(); if (session != null) { clientId = session.getSession().getId(); } // 记录上行消息(客户端发往服务端)指标 if (request.getAttribute(FrameworkConfig.PUSH_MESSAGE) != null) { metricsStore.recordUpstream(clientId, System.currentTimeMillis(), request.getContentLength()); } // 记录下行消息(服务端发往客户端)指标 if (response.getContentType() != null && response.getContentType().contains("application/vaadin-push")) { metricsStore.recordDownstream(clientId, System.currentTimeMillis(), response.getContentCount()); } return Action.CONTINUE; } }
第二步:实现双向心跳探测计算核心指标
默认Atmosphere保活心跳间隔过大,无法满足实时性能统计需求,需要额外实现业务层双向心跳逻辑:
- 服务端每隔2秒往每个活跃Push通道发送携带唯一心跳ID、发送时间戳的固定64字节空payload,避免占用正常业务带宽
- 客户端收到心跳包后立刻返回同ID的响应,同时记录本地接收时间戳
- 服务端收到响应后,用当前时间减去初始发送时间得到双向往返延迟(RTT),连续3次心跳未收到响应则标记为连接异常
- 连续统计1分钟内的RTT值,计算抖动(相邻两次RTT差值的平均值)、丢包率(丢失心跳数/总发送心跳数)
- 如需统计带宽,可每隔10秒发送一次固定大小(例如1MB)的测试包,用传输完成耗时计算上下行实时带宽,该测试可设置为用户手动触发,避免影响正常业务
第三步:前端指标可视化
所有指标可直接绑定Vaadin原生组件展示,无需额外引入前端框架:
- 用Vaadin自带
Chart组件做实时折线图,展示最近5分钟的RTT、抖动、带宽变化趋势 - 用
ProgressBar或Badge组件展示当前连接质量等级:RTT<100ms标绿色优秀、100-300ms标黄色一般、>300ms标红色较差,丢包率>5%直接标红色警告 - 所有指标与当前用户Vaadin Session绑定,仅用户本人可查看自己的连接质量数据
第四步:Jetty embedded适配注意事项
需要提前打开两处配置,避免Atmosphere的WebSocket通道降级为长轮询,导致指标统计失真:
- 开启Jetty WebSocket支持:在Jetty的ServletContextHandler中添加
WebSocketServerContainerInitializer配置,设置最大二进制消息大小、空闲超时为300秒,避免长连接被中途断开 - 明确指定Vaadin Push传输协议为
websocket,不使用默认的websocket-with-fallback,减少降级场景的适配成本,参考配置:
@Configuration public class VaadinConfig implements AppShellConfigurator { @Override public void configurePage(AppShellSettings settings) { settings.setPushMode(PushMode.AUTOMATIC); settings.setPushTransport(Transport.WEBSOCKET); } }
内容的提问来源于stack exchange,提问作者lanmaster
相关产品推荐
相关产品推荐

