当前位置: 首页 > news >正文

拌合楼软件开发(23)监测客户端在线情况并联动企业微信提醒客户端离线和恢复

需求分析:

        项目过程中,客户端通过将车牌重量等数据post到服务端进行处理后生成相应的单据,如果没有网络那么就会出现异常情况,往往只有到客户过车发现系统不能用找过来,分析原因才发现是客户端处断网了。这不仅增加了很多不必要的沟通成本,同时也让客户对系统的稳定性产生一些质疑。因此决定开发一个检测客户端是否离线的功能,如果离线,那么服务端主动推送企业微信群消息给服务人员群中,这样服务跟进人员可以主动与客户沟通。

实现的路径:

        客户端每5分钟发送一个心跳包给到服务端,服务端记录下来心跳包到达的时间,服务端定时扫描客户端心跳包发送的时间,如果服务端记录的心跳包时间与当前时间差在30分中以上,那么表明客户端已经掉线,把客户端标记为离线,并发送消息,消息发送提醒10次。等到接收到客户端的心跳包时候,先判断客户端是否被标记为离线了,那么取消离线标识,并发送消息提醒恢复了。

        一、需要搭建一个服务端接收客户端心跳包

        实现心跳包接收的机制很多,一般的思路是服务端监听端口,客户端定时连接改端口,并发送约定的心跳包数据来证明自己存活。作者偷个懒,就用.net 写了个心跳处理的api接口来做这个事情。

        二、服务端心跳包处理

        1. 心跳包的数据内容:

        客户端请求API接口,就一个clientId来标识自己的身份就可以了,服务器端就以接口接收到数据的时间来作为心跳包的时间,clientId 为免重复,用了guid,用什么格式这个读者按照自己的业务需求来定了。

        2. 心跳包接收处理:

        作者用到了redis来做数据的缓存了,mysql的数据库中表记录clientId信息,每次客户端心跳请求,那么先查询该clientId是否在表中有记录,如果没有记录表明是非法数据集,直接丢弃了,如果有记录再做后续的处理。        

   [HttpGet]public async Task<IActionResult> Get(string clientId){if (string.IsNullOrEmpty(clientId)){_logger.LogWarning("没有收到心跳包");return BadRequest("没有收到心跳包");}//var cacheData = await _redis.GetStringAsync(clientId);var client = GetClientList.ClientList.Where(u => u.clientId == clientId).FirstOrDefault();if (client == null){_logger.LogWarning($"心跳包数据不正确:{clientId}");return BadRequest("心跳包数据不正确");}var times = await _redis.GetStringAsync(clientId + "-offline");if (!string.IsNullOrEmpty(times)){await _redis.RemoveAsync(clientId + "-offline");SendOnlineNotificationAsync(client);}await _redis.SetStringAsync(clientId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));return Ok(clientId);}

        需要传递的数据很少,所以直接用GET就行了。

        (1)先判断是否有传递clientId的参数,如果没有丢弃。

        (2)判断clientId的参数是否在mysql库中,如果没有,丢弃

        (3)查询redis中是否有key为 clientId +“-offline” 的数据,如果有那么表明客户端是已经离线的,那么移除该键值,并推送该客户端已经恢复上线的通知。

        (4)记录下来一组值,key为clientId, 值为当前时间

        3. 服务端定时轮询的处理

        如何实现定时任务,不是本文的重点,主要讲实现的需求的逻辑。        

 public async Task Execute(IJobExecutionContext context){_logger.LogInformation("开始检测客户端的连接状态");foreach (var client in GetClientList.ClientList){var cacheData = await _redis.GetStringAsync(client.clientId);if (!string.IsNullOrEmpty(cacheData)){//如果缓存不是空DateTime lastAccessTime = DateTime.Parse(cacheData);if ((DateTime.Now - lastAccessTime).TotalMinutes > int.Parse(_config.GetSection("lostConnectTime").Value)){//如果缓存时间超过5分钟_logger.LogWarning($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 客户端{client.clientId}, {client.clientName}已经断开连接,最后一次链接时间{cacheData}");string times = await _redis.GetStringAsync(client.clientId + "-offline");if (!string.IsNullOrEmpty(times)){await _redis.SetStringAsync(client.clientId + "-offline", (int.Parse(times) + 1).ToString());//只推送10次离线提醒if (int.Parse(times) <= int.Parse(_config.GetSection("notifyTimes").Value)){SendOfflineNotificationAsync(client, cacheData);}}else{await _redis.SetStringAsync(client.clientId + "-offline", "1");SendOfflineNotificationAsync(client, cacheData);}}}}

           (1)  Mysql表中记录有所有的客户端clientId信息,那么for循环查询所有redis中所有客户端的记录信息。

        (2)查询redis中是否包含clientId为key的值,如果没有表明系统可以能刚启动,如果有

        (3)该key中记录的是上一次心跳包达到服务端时间,如果与当前时间比较超过阈值,那么就标记客户端是离线。

        (4)查询redis中是否存在 clientId+ “-offline” 为key的值, 如果不存在表明为第一次掉线,那么设置该键的值为1,并推送消息。

        (5)如果存在,先查询存储的值,如果值大于设定提醒此次,那么就不发消息,如果没有那么推送消息,并将该值+1,存储回去。

三、客户端发送数据

        客户端发送数据很简单,使用HttpClient发送数据。       

    string baseUrl = "https://xxxxx/api/heartData";        string clientI    clientId  = "your_client_id_here";// 创建HttpClient实例using (HttpClient client = new HttpClient()){try{// 构造带参数的URLstring requestUrl = $"{baseUrl}?clientId={Uri.EscapeDataString(clientId)}";// 发送GET请求HttpResponseMessage response = await client.GetAsync(requestUrl);// 检查响应状态if (response.IsSuccessStatusCode){// 读取响应内容string responseBody = await response.Content.ReadAsStringAsync();Console.WriteLine("Response: " + responseBody);}else{Console.WriteLine($"Error: {response.StatusCode}");}}catch (Exception ex){Console.WriteLine($"Exception: {ex.Message}");}

        到此整个功能基本上就实现了。

http://www.dtcms.com/a/469722.html

相关文章:

  • 雄安网建 网站建设莞城微信网站建设
  • 基于Python的交通数据分析应用-hadoop+django
  • [特殊字符] 教程|打造一个 Telegram 币圈波场交易记录检测机器人
  • 高弹性不锈钢材质在技工钳应用中的优势分析
  • 东土科技连投三家核心企业 发力具身机器人领域
  • 建设行政主管部门官方网站张槎建网站服务
  • 【AI4S】利用大语言模型 LLM 进行分子设计
  • 零用贷网站如何做p2p网站建设公司排名
  • 从 Home Assistant 到 JetLinks:构建双层智能家居与社区管理平台实训全景
  • 什么是BUG,你对BUG的了解有多少?
  • 有哪些网站做任务有佣金手机活动网站模板
  • 阿里下场造“机器人”:从通义千问到具身智能,中国AI正走向“实体化”阶段
  • 盐城网站建设jsxmt公司网站域名管理
  • Cherry Studio 核心功能简介
  • 阿里巴巴国际站开店流程及费用网站建设与网络编辑综合实训课程指导手册pdf
  • 网站备案收费幕布用wordPress搭建图片库
  • Java版座位预约系统★共享自习室系统源码★学校/培训机构座位预约系统
  • 全网首发/Qt结合ffmpeg实现rist推拉流/可信赖的互联网流媒体协议/跨平台支持各个系统
  • leetcode二分查找(C++)
  • 生成对抗网络(Generative Adversarial Network,GAN)
  • 18-基于STM32的智能医嘱手环设计与实现
  • encodeURIComponent() 函数详解
  • 在JavaScript中,map方法使用指南
  • 手机网站好还是h5好找大学生做家教的网站
  • vue项目安装使用,npm、webpack版本问题注意
  • Arbess从入门到实战(12) - 使用Arbess+Gitee+SonarQube实现Node.js项目自动化构建部署
  • 旅游网站模板 手机网站构建
  • 单遍聚类:实时数据流聚类解决方案
  • 使用TimeSformer进行模型训练(mvp验证)
  • MES系统业务流程全面解析