我正在通过.net中的rest和web套接字编写高度可用的api。我正在寻找以下策略:
此时,我的关键词搜索并未向我提供有关如何实现此问题的大量见解,但如果有任何想法,我会非常感谢您的建议!
TL; DR:是否有人在webapi项目中创建了一个队列服务,以便将消息推送到websocket?
答案 0 :(得分:1)
是否有人在webapi项目中创建了一个队列服务,以便将消息推送到websocket?
根据您的要求,您可以创建后台任务,以便从服务总线队列接收消息,如下所示:
<强>的Global.asax.cs 强>
public class WebApiApplication : System.Web.HttpApplication
{
private static ManualResetEvent _maunalResetEvent = new ManualResetEvent(false);
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ThreadPool.QueueUserWorkItem(_ =>
{
var connectionString = "";
var queueName = "samplequeue";
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
client.OnMessage(message =>
{
var messageBody = message.GetBody<String>();
System.Diagnostics.Trace.TraceInformation(String.Format("Message body: {0}", messageBody));
//TODO: send message to the specific client (user)
});
_maunalResetEvent.WaitOne();
});
}
protected void Application_End()
{
_maunalResetEvent.Set();
}
}
注意:有关从队列接收邮件的详细信息,请参阅此官方tutorial。
为了将消息推送到您的客户端,如果您基于webapi-and-websockets,我认为您需要选择WebSocketCollection
实例,然后选择具有{WebSocketHandler
实例的特定_username
实例{1}}匹配收到的队列消息中的属性,或者将消息广播到所有客户端,如下所示:
收到队列消息后,使用以下代码向所有客户端广播:
ChatWebSocketHandler.ChatClients.Broadcast("{queue-message}");
此外,您可以利用SignalR并将您的客户端(用户)映射到signalR连接,然后当您收到队列消息时,您可以将其发送给您的客户端(用户)。有关详细信息,请参阅Mapping SignalR Users to Connections。此外,您可以关注SignalR Hubs API Guide和此git sample。
答案 1 :(得分:0)
我的要求有点费解。我能够通过主题和订阅模型解决问题。
我从队列中发布主题,并通过在websocket请求上生成的过滤订阅广播到所有websocket连接。非常光滑!
private async Task ProcessWebsocketSession(AspNetWebSocketContext context)
{
var details = ((APIIdentity)User.Identity).Details;
//SubscriptionHandler creates the subscription for the given system, and disposes of it safely when leaving scope
using (var ws = context.WebSocket)
using (var subHander = new SubscriptionHandler(details))
{
var client = subHander.Client;
client.OnMessage((brokerMsg) =>
{
var payload = brokerMsg.GetBody<string>();
var dataToSend = JsonConvert.DeserializeObject<Data>(brokerMsg.GetBody<string>());
//refreshing from db, to check if data has been updated in process
dataToSend = Repo.GetData(BusinessID, dataToSend .ID).FirstOrDefault();
if (dataToSend != null && !dataToSend Send.IsConfirmed.Value)
{
byte[] binaryData = Encoding.ASCII.GetBytes(payload);
var segment = new ArraySegment<byte>(binaryData);
var task = ws.SendAsync(segment, WebSocketMessageType.Text,
true, CancellationToken.None);
task.Wait();
}
brokerMsg.Complete();
});
var receivedBytes = new ArraySegment<byte>(new byte[1024]);
while (ws.State == WebSocketState.Open)
{
// ping/pong response to verify socket is connected without changing data
var msg = await ws.ReceiveAsync(receivedBytes, CancellationToken.None);
if (msg.MessageType == WebSocketMessageType.Text)
{
var text = Encoding.ASCII.GetString(receivedBytes.ToArray());
if (text.ToLower() == "ping")
{
await ws.SendAsync(new ArraySegment<byte>(Encoding.ASCII.GetBytes(text.ToCharArray())), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
}