SignalR客户端持续发送空对象消息的追踪与日志记录方案
针对ASP.NET MVC(.NET Framework 4.7.2)追踪客户端心跳消息的解决方案
1. 定义接收心跳的接口
首先需要创建一个MVC Action来接收客户端每10秒发送的空对象请求,ASP.NET MVC的模型绑定可以直接兼容空JSON对象:
[HttpPost] public JsonResult KeepAlive([FromBody] object emptyObject) { // 后续的日志记录、活跃用户更新逻辑写在这里 return Json(new { success = true }); }
2. 记录活跃用户与心跳日志
在Action中获取用户标识(认证用户用User.Identity.Name,匿名用户用Session ID或客户端自定义UUID),同时记录心跳日志并更新活跃状态:
using System.Runtime.Caching; using System.Diagnostics; [HttpPost] public JsonResult KeepAlive([FromBody] object emptyObject) { // 获取用户唯一标识 string userId = User.Identity.IsAuthenticated ? User.Identity.Name : Session.SessionID; // 匿名用户用SessionID,若需跨会话追踪可让客户端存UUID到Cookie // 1. 写入心跳日志(可替换为log4net、NLog等日志框架) string logContent = $"用户[{userId}]心跳时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"; Trace.WriteLine(logContent); // 2. 更新活跃用户缓存,设置过期时间(例如30秒,超过则判定为非活跃) var cache = MemoryCache.Default; cache.Set($"ActiveUser_{userId}", userId, DateTime.Now.AddSeconds(30)); return Json(new { success = true }); }
3. 实现服务器向活跃用户推送消息
方案一:基于轮询的简单推送
客户端在发送心跳的同时,额外定期请求服务器获取未读消息,Action示例:
[HttpGet] public JsonResult GetUnreadMessages() { string userId = User.Identity.IsAuthenticated ? User.Identity.Name : Session.SessionID; // 从数据库/缓存中获取该用户的未读消息 var messages = GetMessagesFromStorage(userId); return Json(messages, JsonRequestBehavior.AllowGet); }
方案二:基于SignalR的实时推送(更高效)
ASP.NET MVC 4.7.2可集成SignalR 2.x实现长连接推送:
- 安装SignalR NuGet包:
Install-Package Microsoft.AspNet.SignalR
- 配置SignalR路由(新建或修改Startup类):
using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(YourAppNamespace.Startup))] namespace YourAppNamespace { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } } }
- 定义Hub类,整合心跳与推送逻辑:
using Microsoft.AspNet.SignalR; using System.Runtime.Caching; public class NotificationHub : Hub { // 客户端调用此方法发送心跳 public void ReportAlive() { string userId = Context.User.Identity.Name ?? Context.ConnectionId; var cache = MemoryCache.Default; // 缓存用户的连接ID,用于精准推送 cache.Set($"ActiveUser_{userId}", Context.ConnectionId, DateTime.Now.AddSeconds(30)); } // 服务器主动推送消息的静态方法 public static void PushMessageToUser(string userId, string messageContent) { var cache = MemoryCache.Default; string connectionId = cache.Get($"ActiveUser_{userId}") as string; if (!string.IsNullOrEmpty(connectionId)) { GlobalHost.ConnectionManager .GetHubContext<NotificationHub>() .Clients.Client(connectionId) .receiveMessage(messageContent); } } }
客户端可直接调用SignalR的ReportAlive方法替代单独的空对象请求,同时监听receiveMessage事件接收推送。
4. 日志持久化(可选)
若需将心跳日志持久化到文件或数据库,以NLog为例,配置NLog.config:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="heartbeatLog" xsi:type="File" fileName="${basedir}/Logs/Heartbeat/${shortdate}.log" layout="${longdate} | ${message}" /> </targets> <rules> <logger name="HeartbeatLogger" minlevel="Info" writeTo="heartbeatLog" /> </rules> </nlog>
在Action中使用NLog记录:
private static readonly NLog.Logger heartbeatLogger = NLog.LogManager.GetLogger("HeartbeatLogger"); [HttpPost] public JsonResult KeepAlive([FromBody] object emptyObject) { string userId = User.Identity.IsAuthenticated ? User.Identity.Name : Session.SessionID; heartbeatLogger.Info($"用户[{userId}]发送心跳"); // 更新活跃用户缓存... return Json(new { success = true }); }
内容的提问来源于stack exchange,提问作者AmirHosseinMp02
相关产品推荐
相关产品推荐

