【发布时间】:2017-02-17 19:40:58
【问题描述】:
我没有想法,如何实现。这是问题所在,我已经尝试过。
问题
有一个消息队列,其中包含来自外部系统的消息。客户端必须打开与服务器的 websocket 连接,并在插入这些消息后立即从队列中接收这些消息。除此之外,客户端可以通过相同的 websocket 连接向服务器发送命令(客户端和服务器之间的通信必须具有尽可能低的延迟)。
工具
我更喜欢使用最低级别但仍然实用的官方库,因此选择Microsoft.AspNetCore.WebSockets (1.0.0)。该应用程序作为启用了 websockets (WSS) 的 Web 应用程序在 Azure 应用程序服务上运行。该应用程序是netcoreapp1.1。不需要 SSE/长轮询/等后备 (SignalR)。
解决方案 #1 - 已测试
服务器应该运行一个循环到:
- 如果消息队列不为空,则发送任何更新。
- 等待传入消息超时。
可以这样实现:
while (_request_not_aborted_) // The condition is simplified.
{
if (_there_is_a_new_message_in_message_queue_)
{
// Send all available messages from the message queue.
await SendAsync();
}
using (var timeoutCancellationTokenSource = new CancellationTokenSource())
{
var timeoutCancellationToken = timeoutCancellationTokenSource.Token;
var receiveTask = ReceiveAsync(timeoutCancellationToken, webSocket);
// Wait for any incoming message for 1000ms and cancel the task if
// the client hasn't sent any yet.
if (await Task.WhenAny(receiveTask, Task.Delay(1000, timeoutCancellationToken)) ==
receiveTask)
{
var result = await receiveTask;
// Process the message.
}
timeoutCancellationTokenSource.Cancel();
}
}
解决方案 #1 - 出了什么问题?
一旦timeoutCancellationTokenSource被取消,websocket连接进入“Aborted”状态,客户端断开。
可能相关问题:https://github.com/aspnet/WebSockets/issues/68
解决方案 #2 - 已测试
使用 SSE 将数据从服务器流式传输到客户端,并使用常规 HTTPS 请求发回消息。
解决方案 #2 - 出了什么问题?
HTTPS 请求延迟不可接受,IE/Edge 尚不支持 SSE。
解决方案 #3
使用多个 websocket 连接,一个用于服务器->客户端,另一个用于客户端->服务器通信。
解决方案 #3 - 出了什么问题?
但这会增加断开连接出错的机会,而且总的来说,这听起来很糟糕,因为 websocket 技术应该提供双向通信。
解决方案 #4
使用解决方案 #2 并删除超时逻辑,但每 1000 毫秒从客户端向服务器发送 NOOP 消息,以允许 ReceiveAsync 正常完成。
解决方案 #4 - 出了什么问题?
听起来像一个讨厌的解决方法。
请求帮助/想法
也许知道任何其他解决方案,服务器如何相对同时侦听传入消息并向客户端发送消息?
其他发现
- “每个 WebSocket 对象并行支持一个发送和一个接收。” MSDN
【问题讨论】:
-
消息队列用什么?
-
Azure 云存储
标签: c# asp.net websocket .net-core kestrel-http-server