SignalR 实时通知消息并行推送和批量存储实现

本文介绍了使用SignalR实现实时通知消息的并行推送和批量存储。通过MVC控制器,利用.NET的Parallel.ForEach()并行推送消息到多个接收人,并使用BulkCopy方法批量存储到数据库。客户端接收端则通过SignalR接口接收消息。虽然未深入探讨SignalR的详细用法和在线用户管理,但展示了SignalR在实时通讯应用中的实用性。

前言:SignalR是基于.NET平台Web应用的实时消息通讯框架,有人称之为.NET平台的.NodeJS;可用于Web页面聊天,消息推送等功能实现。本文摘取部分代码,利用.NET平台的Parallel功能实现通知消息的并行推送和批量存储。


1. 接收通知消息的Api接口:

MVC 控制器代码:

[HttpPost]
[AllowAnonymous]
public void Notify(Message message)
{
    var msgModel = new MessageModel();
    msgModel.Notify(message);
}

[HttpPost]
[AllowAnonymous]
public void Notify(List<Message> msgList)
{
    var msgModel = new MessageModel();
    msgModel.BatchNotify(msgList);
}	


2. 通知消息的并行推送:

2.1 批量推送接口

首先调用到Task.Factory.StartNew()方法创建新任务,用BulkCopy()方法将数据批量插入到数据库;然后并行推送消息,因为消息接收人有多个,根据消息接收人的消息实体对象列表,Parallel.ForEach()对每条消息并行推送到Web用户的前端。

/// <summary>
/// 通知单条消息
/// </summary>
/// <param name="msg"></param>
public void Notify(Message msg)
{
    List<Message> msgList = new List<Message>();
    msgList.Add(msg);
    BatchNotify(msgList);
}

/// <summary>
/// 多条消息列表推送
/// </summary>
/// <param name="msgList"></param>
public void BatchNotify(List<Message> msgList)
{
    //批量插入消息
    var msgService = new MessageService();
    Task.Factory.StartNew(() =>
    {
        msgService.BulkInsert(msgList);
    });

    IList<string> onlineConnectionIds = new List<string>();
    var hub = GlobalHost.ConnectionManager.GetHubContext<ClientPushHub>();
    var onlineUsers = ChatHub.GetOnlineUsersOnHub();

    //发送消息
    Parallel.ForEach<Message>(msgList, (msg) => 
    { 
        PushMessage(msg, onlineUsers, hub); 
    });
}



2.2 调用SignalR 接口给在线用户发送通知消息

每条消息有多个接收人,每个接收人在前端的Connection连接存储在ConnectionIds集合中,遍历进行推送。

/// <summary>
/// 单条消息推送服务
/// </summary>
/// <param name="message">消息数据</param>
private void PushMessage(Message msg, List<User> onlineUsers, IHubContext hub)
{
    User user = null;
    List<RecieverEntity> recievers = msg.Recievers;
    foreach (var reciever in recievers)
    {
        user = onlineUsers.SingleOrDefault(a => a.Name == reciever.Reciever);
        if (user != null)
        {
            foreach (var connId in user.ConnectionIds)
            {
                hub.Clients.Client(connId).onPushingMessage(new
                {
                    sender = msg.Sender,
                    msgTitle = msg.MsgTitle,
                    msgContent = msg.MsgContent,
                    billUrl = msg.BillUrl,
                    iframeTxt = msg.IframeTxt,
                    iframeCode = msg.IframeCode,
                    sendTime = DateTime.Now.ToString(),
                    sendType = "notification"
                });
            }
        }
    }
}


2.3 客户端接收通知消息

//接收系统服务通知消息
clientPushHub.client.onPushingMessage = function (message) {
    popNewMsgHintWindow(message);
}

3. 批量消息的批量存储

3.1 批量插入

/// <summary>
/// 批量插入
/// </summary>
/// <param name="msgList"></param>
public void BulkInsert(List<Message> msgList)
{
    var msgTable = MsgBatchUtility.GetTableSchema();
    foreach (var msg in msgList)
    {
        Insert(msgTable, msg);
    }
    MsgBatchUtility.BulkCopy(msgTable);
}

3.2  获取消息表结构

/// <summary>
/// 获取数据表Schema
/// </summary>
/// <returns></returns>
public static DataTable GetTableSchema()
{
    DataTable dt = new DataTable();
    dt.Columns.AddRange(new DataColumn[]{
        new DataColumn("MsgID", typeof(int)),
        new DataColumn("MsgType", typeof(byte)),
        new DataColumn("MsgTitle", typeof(string)),
        new DataColumn("MsgContent", typeof(string)),
        new DataColumn("Status", typeof(byte)),
        new DataColumn("SenderID", typeof(string)),
        new DataColumn("Sender", typeof(string)),
        new DataColumn("SendTime", typeof(DateTime)),
        new DataColumn("RecieverID", typeof(string)),
        new DataColumn("Reciever", typeof(string)),
        new DataColumn("RecievedTime", typeof(DateTime)),
        new DataColumn("AppName", typeof(string)),
        new DataColumn("AppInstanceID", typeof(string)),
    });
    return dt;
}



3.3 数据库批量拷贝方法BulkCopy()

/// <summary>
/// 批量插入方法
/// </summary>
/// <param name="dt"></param>
public static void BulkCopy(DataTable dt)
{
    SqlConnection sqlConn = new SqlConnection(connectionString);
    SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlConn);
    bulkCopy.DestinationTableName = "dbo.im_message";
    bulkCopy.BatchSize = dt.Rows.Count;
    try
    {
        sqlConn.Open();
        if (dt != null && dt.Rows.Count != 0)
            bulkCopy.WriteToServer(dt);
    }
    catch (Exception)
    {
        throw;
    }
    finally
    {
        sqlConn.Close();
        if (bulkCopy != null)
            bulkCopy.Close();
    }
}



总结:


本文暂时没有对SignalR的用法和在线用户列表维护做出代码示例,会在后期文章中单独列出,SiganlR功能在做WebQQ聊天功能,网站页面聊天,聊天室功能时非常有用,有兴趣的开发人员可以以此为框架,搭建自己的实时通讯的工具,至于性能方法,SignalR评价是非常不错的,完全可以做企业级的分布式实时应用,有兴趣的读者可以访问官方站点了解。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值