我有2个WebSockets端点:
registry.addEndpoint("/ws-handshake").withSockJS();
registry.addEndpoint("/api/admin/ws-handshake").withSockJS();
第一个未经身份验证,第二个受Spring Boot Security保护,使用与HTTP安全相同的配置,并使用OAuth2。授权标头用于连接到安全端点。
我使用一个简单的for循环,因为这是一个POC,但是生产中将使用相同数量的数据来返回很多记录,这是通过使用Spring Boot提供的SimpMessageSendingOperations类完成的:
private SimpMessageSendingOperations messagingTemplate;
@MessageMapping("/tail-topic")
public void tailLogSendToTopic(@Payload WebSocketPoCPayload payload) throws InterruptedException {
String topicName = "/topic/logentries";
for (int i = 0; i < 3000; i++) {
WebSocketPoCMessage message = new WebSocketPoCMessage(String.format("%d : returning payload %s", i, payload.getName()));
messageTemplate.convertAndSend(topicName, message);
// TimeUnit.MILLISECONDS.sleep(50);
}
log.info("done returning all messages");
}
当我通过不安全的端点发送请求时,一切运行正常,我在客户端收到了一切。
当我通过安全端点发送请求时,一切正常,直到某个有效负载编号(例如1499,始终是相同的有效负载编号)为止。 除非我取消注释超时,否则需要超过10毫秒,否则我将失去连接,但以后的连接数会丢失。
如果我的安全设置看到的流量过多,似乎断开了连接,我的安全配置中是否缺少某些内容?
答案 0 :(得分:1)
我想我已经找到了解决这个问题的真正方法, 尽管该框架是非阻塞的,但在发送每条消息后,它仍会等待rabbitMQ stomp broker 的响应。 在高吞吐量中发生的事情是有时响应丢失并且它永远挂起等待,在 StompBrokerRelayMessageHandler 中,在 future.get() 行中:
try {
ListenableFuture<Void> future = super.forward(message, accessor);
if (message.getHeaders().get(SimpMessageHeaderAccessor.IGNORE_ERROR) == null) {
future.get();
}
return future;
}
catch (Throwable ex) {
throw new MessageDeliveryException(message, ex);
}
对我有用的解决方案是在不等待响应的情况下发送消息,通过添加消息标头,如下所示:
SimpMessageHeaderAccessor accessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
accessor.setHeader(SimpMessageHeaderAccessor.IGNORE_ERROR, true);
accessor.setLeaveMutable(true);
messagingTemplate.convertAndSend(destination, message, accessor.getMessageHeaders());
当然在这种情况下,一些消息可能会丢失,但对于我的用例来说已经足够了。
另一种有效的解决方案是使用超时和单线程执行程序包装 convertAndSend 行,然后重试
干杯
答案 1 :(得分:0)
由于对此似乎没有任何回应,我将接受临时解决方法作为解决方案:
private SimpMessageSendingOperations messagingTemplate;
@MessageMapping("/tail-topic")
public void tailLogSendToTopic(@Payload WebSocketPoCPayload payload) throws InterruptedException {
String topicName = "/topic/logentries";
for (int i = 0; i < 3000; i++) {
WebSocketPoCMessage message = new WebSocketPoCMessage(String.format("%d : returning payload %s", i, payload.getName()));
messageTemplate.convertAndSend(topicName, message);
TimeUnit.MILLISECONDS.sleep(50);
}
log.info("done returning all messages");
}