- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到了 Spring WebSocket 版本 4.1.1.RELEASE 未发送 WebSocket 消息的问题。并不是每条消息都会发生这种情况,只是有些消息由于我不明白的原因而没有发送。消息内容需要一些时间才能加载,但我不确定这是否是问题的原因,因为有时它可以工作,但大多数时候却不能。
我的 Web 应用程序成功订阅 channel /user/queue/overview/reqinfo/events
,然后发送四条消息来请求信息。我的 Controller 类通过 spring-data-jpa 和 Hibernate 在数据库上触发 COUNT() 语句,并将结果作为消息返回给请求来源的用户。所有四个消息都由相同的 Controller 方法处理,但只有两个响应传递给发送者。我从Spring日志中提取了相关信息并附在此处。正如您所看到的,最后两条消息没有被 SimpleBrokerMessageHandler 处理,因此不会发送给用户。创建这些消息的内容需要一分多钟的时间。
12:50:54,953 DEBUG clientInboundChannel-12 user.UserDestinationMessageHandler:187 - Translated /user/queue/overview/reqinfo/events -> [/queue/overview/reqinfo/events-user8178efnd]
12:50:54,953 DEBUG clientInboundChannel-12 broker.SimpleBrokerMessageHandler:175 - Processing SUBSCRIBE /queue/overview/reqinfo/events-user8178efnd id=sub-7 session=8178efnd
[...]
12:50:54,957 DEBUG clientInboundChannel-2 support.SimpAnnotationMethodMessageHandler:348 - Searching methods to handle SEND /app/overview/reqinfo/events session=8178efnd
12:50:54,957 DEBUG clientInboundChannel-1 support.SimpAnnotationMethodMessageHandler:348 - Searching methods to handle SEND /app/overview/reqinfo/events session=8178efnd
12:50:54,957 DEBUG clientInboundChannel-16 support.SimpAnnotationMethodMessageHandler:348 - Searching methods to handle SEND /app/overview/reqinfo/events session=8178efnd
12:50:54,959 DEBUG clientInboundChannel-10 support.SimpAnnotationMethodMessageHandler:348 - Searching methods to handle SEND /app/overview/reqinfo/events session=8178efnd
[...]
12:50:54,959 DEBUG clientInboundChannel-16 support.SimpAnnotationMethodMessageHandler:446 - Invoking de.d.i.g.websocket.OverviewController#requestOverviewEvents[2 args]
12:50:54,959 DEBUG clientInboundChannel-10 support.SimpAnnotationMethodMessageHandler:446 - Invoking de.d.i.g.websocket.OverviewController#requestOverviewEvents[2 args]
12:50:54,959 DEBUG clientInboundChannel-2 support.SimpAnnotationMethodMessageHandler:446 - Invoking de.d.i.g.websocket.OverviewController#requestOverviewEvents[2 args]
12:50:54,959 DEBUG clientInboundChannel-1 support.SimpAnnotationMethodMessageHandler:446 - Invoking de.d.i.g.websocket.OverviewController#requestOverviewEvents[2 args]
[...]
12:50:55,006 DEBUG clientInboundChannel-1 websocket.OverviewController:196 - requestOverviewEvents, incoming message: MsgOverviewEventsRequest(timeframe=THIS_WEEK)
12:50:55,006 DEBUG clientInboundChannel-10 websocket.OverviewController:196 - requestOverviewEvents, incoming message: MsgOverviewEventsRequest(timeframe=LAST_WEEK)
12:50:55,006 DEBUG clientInboundChannel-2 websocket.OverviewController:196 - requestOverviewEvents, incoming message: MsgOverviewEventsRequest(timeframe=YESTERDAY)
12:50:55,006 DEBUG clientInboundChannel-16 websocket.OverviewController:196 - requestOverviewEvents, incoming message: MsgOverviewEventsRequest(timeframe=TODAY)
[...]
12:50:55,032 DEBUG clientInboundChannel-16 websocket.OverviewController:225 - requestOverviewEvents, outgoing message: MsgOverviewEvents(timeframe=TODAY, count=31, error=false)
12:50:55,035 DEBUG clientInboundChannel-16 broker.SimpleBrokerMessageHandler:152 - Processing MESSAGE destination=/queue/overview/reqinfo/events-user8178efnd session=null payload={"timeframe":"TODAY","count":31,"error":false}
12:50:55,035 DEBUG clientInboundChannel-16 broker.SimpleBrokerMessageHandler:196 - Broadcasting to 1 sessions.
[...]
12:51:01,018 DEBUG clientInboundChannel-2 websocket.OverviewController:225 - requestOverviewEvents, outgoing message: MsgOverviewEvents(timeframe=YESTERDAY, count=190292, error=false)
12:51:01,020 DEBUG clientInboundChannel-2 broker.SimpleBrokerMessageHandler:152 - Processing MESSAGE destination=/queue/overview/reqinfo/events-user8178efnd session=null payload={"timeframe":"YESTERDAY","count":190292,"error":false}
12:51:01,020 DEBUG clientInboundChannel-2 broker.SimpleBrokerMessageHandler:196 - Broadcasting to 1 sessions.
[...]
12:51:19,081 DEBUG clientInboundChannel-1 websocket.OverviewController:225 - requestOverviewEvents, outgoing message: MsgOverviewEvents(timeframe=THIS_WEEK, count=845956, error=false)
12:51:19,088 DEBUG clientInboundChannel-10 websocket.OverviewController:225 - requestOverviewEvents, outgoing message: MsgOverviewEvents(timeframe=LAST_WEEK, count=1421118, error=false)
这是一个经常出现问题的示例案例。我对遭受相同问题的其他消息和 Controller 有其他看法,并且它们的消息不需要一分钟即可构建,只需要几秒钟甚至更短的时间。我正在使用带有 SockJS 支持的 SimpleMessageBroker
(使用 SockJS 0.3.4)。在尝试解决此问题时,我将此 bean 添加到我的 WebSocket 配置类中以手动设置连接超时,但它没有解决问题:
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
long tenMinutesInMillis = 10 * 60 * 1000;
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setAsyncSendTimeout(tenMinutesInMillis);
container.setMaxSessionIdleTimeout(tenMinutesInMillis);
return container;
}
为什么有些消息会被丢弃,而另一些消息会正确发送?如果您需要日志或源代码中的更多信息,请询问。
[更新]有关该行为的一些附加信息:
始终返回计算最少项目数的第一条消息。第二条消息大部分时间都会返回,最后两条消息大约 90% 的时间都会发送失败。在它们加载失败后,其他 View 也不会加载,即使接收并处理了订阅,响应消息也不会发送到 Web 界面。在浏览器中点击刷新以重新加载页面后,一切正常,直到消息再次卡住。
但是,在后台运行并使用 WebSocket 向用户发送消息的心跳系统始终有效。它似乎完全不受该问题的影响。
[更新2]
当问题发生时,sockJsScheduler
似乎没有处理所有请求。 WebSocketMessageBrokerStats
记录的 INFO 消息提供以下输出:
INFO MessageBrokerSockJS-2 config.WebSocketMessageBrokerStats:113 - WebSocketSession[1 current WS(1)-HttpStream(0)-HttpPoll(0), 1 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(1)-CONNECTED(1)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 16, active threads = 0, queued tasks = 0, completed tasks = 120], outboundChannelpool size = 16, active threads = 0, queued tasks = 0, completed tasks = 16], sockJsScheduler[pool size = 8, active threads = 1, queued tasks = 4, completed tasks = 18]
它说 sockJsScheduler
有四个排队任务没有被处理,也许这些是没有正确发送的消息?不幸的是,没有进一步的信息说明为什么它们没有在日志中得到处理。
最佳答案
对我的应用程序(尤其是处理的 Spring 代码)进行深入调试后,我找到了该行为的原因。
问题既不是 Controller 也不是 Spring 内部进程,而是我在 Spring Security 身份验证期间用于主体对象的类。它存储用户成功应答的最后一个心跳 ID,以检查向系统发送消息的用户是否还活着,或者 session 是否已被视为已死亡。此 ID 包含在 equals()
中, hashCode()
和toString()
该对象的方法。
Spring 使用其中一种方法(经过一些测试,我猜它是 toString()
,在我看来这不是一个好的选择)来转换 @SendToUser
的目标路径。操作。如果字符串发生变化(当应答新的心跳 ID 时,我的应用程序就是这种情况),Spring 无法转换目标路径并且不会发送消息。指出这一点的日志条目被隐藏为 TRACE 级别消息,这就是为什么我一开始没有找到它。该消息如下所示:
14:29:00,260 TRACE clientInboundChannel-16 user.UserDestinationMessageHandler:175 - No user destinations found for /user/RtAuthorizedUser(super=AuthorizedUser(username=SIEM-User 1, authenticated=true, lastAnsweredHeartbeat=9971f9ea-8e64-4c24-823b-f7e6e277c775, alive=true), rtSessionId=RT_SID_iMonitor.443=782acc747aac01b9e0a7ece3ab2d27bd)/queue/overview/reqinfo/events
我建议开发人员将此消息至少设置为“调试”级别(甚至“警告”或“错误”),因为在发送过程中搜索问题时很难发现此信息。事实上这是一个错误。
从上述三种方法中删除心跳 ID 后,系统运行良好,不再丢失消息。所以这首先是我这边的一个错误,但我认为使用toString()
这里不是最佳的。现在 Spring 可以正确翻译消息,生成这些消息(这些消息是 DEBUG 级别而不是上面的 TRACE 级别):
14:37:35,661 DEBUG clientInboundChannel-3 user.UserDestinationMessageHandler:187 - Translated /user/RtAuthorizedUser(super=AuthorizedUser(username=SIEM-User 1, authenticated=true, alive=true), rtSessionId=RT_SID_iMonitor.443=bf3adbaa858932b64a03724b6137e95d)/queue/overview/reqinfo/events -> [/queue/overview/reqinfo/events-user_qtca5il]
关于java - Spring WebSocket - Controller 发送消息后丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27061358/
假设浏览器被强制终止,并且没有关闭消息发送到 Tornado 服务器。 Tornado 怎么知道(或者它甚至知道?)这个连接已经在客户端终止了?翻看Tornado websocket code这对我来
我目前正在开发一款使用 WebSockets 的基于浏览器的多人游戏。我的首要任务是低延迟以及与各种平台和网络设置的兼容性。 但是我正在做密码验证。我还有聊天功能,我认为玩家的隐私很重要。因此,我认为
我必须设计一个解决方案,允许通过远程托管的网络应用程序读取本地传感器生成的实时数据。 设计仍在进行中:传感器的数据可以由安装在客户端计算机上的 Windows 应用程序/服务处理,或者由位于客户端计算
WebSocket的端口是什么? WebSocket 使用什么协议(protocol)? 当防火墙阻止除 80 和 443 端口之外的所有端口时,WebSocket 是否工作? 最佳答案 What i
有一个 fantastic answer其中详细介绍了 REST apis 的工作原理。 websockets 如何以类似的细节工作? 最佳答案 Websocket 创建并代表了服务器和客户端之间双向
请原谅我的无知,因为我在负载均衡器和 websockets 方面的经验有限。我试图了解客户端如何通过 websockets 连接到位于负载均衡器后面的服务器集群。 我对负载均衡器的理解是它们就像反向代
我正在尝试使用 websocket 发送音频消息,我应该将音频流更改为什么类型的消息,以便我可以使用套接字发送? 如果我直接使用 websocket.send(audio),我会得到一个错误“DOME
我对 WebSockets 的前景感到非常兴奋。由于我在过去构建了一些基于桌面套接字的游戏和 Web 游戏,因此我热衷于将这两种方法结合起来构建基于 Web 的多人游戏,而无需长时间轮询。 自从 Fi
我读过很多关于实时推送通知的文章。并且简历是 websocket 通常是首选技术,只要您不关心 100% 的浏览器兼容性。然而,one article指出 Long polling - potenti
我很难找到文档或教程,以便通过网络套接字发送文件。 这是我的JS: ['dragleave', 'drop'].forEach(event_name => document.addEventListe
我正在使用 Dart 的 WebSocket 类(dart:io 和 dart:html 版本)连接到 Dart WebSocket 服务器。当我让客户端使用自定义关闭代码和原因关闭 Web 套接字连
谷歌浏览器框架是否支持 websocket? 最佳答案 答案是肯定的,Chrome Frame supports websockets .我不确定,但这也可能取决于您安装的 Chrome 版本。我有
是否可以在同一应用程序(同一端口)中托管一个普通 Bottle 应用程序和一个 WebSocket 应用程序(例如: https://github.com/defnull/bottle/blob/ma
我有一个支持网络套接字的服务器。浏览器连接到我的网站,每个浏览器都会打开一个到 www.mydomain.example 的 Web 套接字。这样,我的社交网络应用程序就可以向客户端推送消息。 传统上
我是 Websockets 新手。在阅读有关 websockets 的内容时,我无法找到一些疑问的答案。我希望有人能澄清一下。 websocket 是否仅将数据广播到所有连接的客户端而不是发送到特定客
客户端可以通过 websockets 连接到服务器多长时间?是否有时间限制,它们是否有可能连在一起多年? 最佳答案 理论上,WebSocket 连接可以永远持续下去。假设端点保持正常运行,长期存在的
我正在尝试使用 websockets 制作自己的聊天客户端,并认为我会从 Tomcat 7 websocket chat example code. 开始。 .我已经成功编译并部署了ChatAnnot
我有一个使用 AdSense 的应用程序,据我所知,由于 AdSense 政策,不允许进行轮询。我想知道如果我使用 WebSockets 并且服务器在创建新数据时向客户端发送新数据并且在客户端上显示新
在 servlet 世界中,我会使用 cookie 和 HttpSession 之类的东西来识别谁在访问我的 Restful 服务以将请求路由到正确的数据。将 Sec-WebSocket-Key 用作
我必须使用 websocket 实现一个聊天应用程序,用户将通过群组聊天,可以有数千个群组,并且一个用户可以在多个群组中。我正在考虑两种解决方案: [1] 对于每个群聊,我创建一个 websocket
我是一名优秀的程序员,十分优秀!