定时补偿方案

 1:需求描述

支持NVR升级后通道数变更,完成升级后,设备SDK上报通道数量给A平台,A平台将NVR通道数量同步给B平台,B平台自动调用C平台接口,同步通道数量给C平台,C平台重新生成通道序列号,并完成序列号入库,再由C平台将通道序列号同步给A平台,A平台完成序列号入库。

2:需求分析

我所在的小组维护的是B平台;拿到需求后,开始分析:

逻辑很简单:设备SDK在启动后,会将信息上报到A平台,A会同步到B平台,B再上报给C;所以只需要在kafka里加入更新后的通道数就可以

现有接口:A平台在设备重启后会通过Kafka上报设备信息给C、获取NVR的通道信息接口

存在问题:获取NVR通道信息的接口是http请求,可能出现网络异常掉用失败的情况,所以需要设计一个补偿机制

3:补偿逻辑

当走网络掉接口失败后,将失败后的kafka信息存入数据库,用定时任务去扫描失败信息进行kafka再次发送;考虑到以后还会有同类型的升级,补偿机制可以设计成通用的。

4:表设计

固件版本同步失败记录表:

重要字段:status:判断是否同步成功;biz_type: 业务类型,本次升级可以设为1(需要补偿的业务类型);biz_msg:业务信息(需要补偿的信息)

5:代码逻辑

更新版本信息接口:

@Override
public String updateVersionInfo(String macId, String currentVersion, String modelId) {

     /**更新前置代码**/

    try {
        //将更新后的设备信息用kafka同步给C,加入升级后的通道数
        JSONObject kafkaData = new JSONObject();
        kafkaData.put("macId", macId);
        kafkaData.put("version", currentVersion);
        kafkaData.put("modelId", modelId);
        kafkaData.put("videoCapability", 2);
        //升级通道数的是nvr总线设备(1nvr总线设备(总设备)可以理解为总设备是一个大的机盒,下面挂了许多子设备,这次升级的就是设备SDK可以上报通道数量(可以挂子设备的数量)
        if (cameraDaoMybatis.getDbCameraInfo(macId).getNvrType() == 1) {
            //通过macID获取nvr的信息(设备id,(state 1:在线),nvrList(这个的size就是通道数));因为获取nvr信息的方法是走网络掉接口,所有可能出现网络异常掉用失败的情况
            NvrDetailInfo nvrChannels = dcsManager.getNvrChannels(macId);
            //当调用成功,并且nvr状态为在线
            if (nvrChannels != null && nvrChannels.getState() == 1) {
                //在kafka中加入升级后获取到的通道数
                kafkaData.put("channelNumber", nvrChannels.getNvrChannelList().size());
            }
            //当调用失败,将设备id,版本,已经kafka的信息全部存入固件版本同步失败记录表
            Integer row = syncFailureRecordMybatis.addSyncFailureMsg(macId, currentVersion, kafkaData.toString());
            LOG.info("addSyncFailureMsg success, rows={} affected, macId={}", row, macId);
        }

       /**更新后置代码**/
       
    } catch (Exception e) {
        LOG.error("updateVersionInfo error: ", e);
        result = JsonUtil.addErrorCode(EErrorCode.ERROR_SYSTEM, result);
    }

    return result.toString();
}

6:定时任务补偿

@Component
@Slf4j
public class SyncFailureRecordJob {
    @Autowired
    private LittlecConfig littlecConfig;

    @Autowired
    private SyncFailureRecordMybatis syncFailureRecordMybatis;

    @Autowired
    private DcsManager dcsManager;

    @Autowired
    private DeviceVersionProducer deviceVersionProducer;

    @XxlJob("SyncFailureRecord")
    public ReturnT<String> syncFailureRecord(String param) {
        //配置一次升级的条数
        long limitSize = littlecConfig.getConfigAsLong("camera.SyncFailureRecordMybatis.querySyncFailureRecord.limitSize", 5000L);
        //记录每次启动定时器,开始扫描的起始id
        Integer startId = 0;
        log.info("syncFailureRecord param:limitSize:{} startId:{}", limitSize, startId);
        boolean isCompleted = false;
        //记录循环次数
        int reconTimes = 0;
        //查t_firmware_version_sync_failure_record表,一天内的数据
        while (!isCompleted) {
            reconTimes++;
            //通过limitSize和startId查出的list集合
            List<SyncFailureRecordDO> syncFailureRecordDOList = syncFailureRecordMybatis.querySyncFailureRecordList(limitSize, startId);
            //取出list里的所有mcaid
            String macIds = syncFailureRecordDOList.stream().map(n -> n.getMacId()).collect(Collectors.joining(","));
            //日志记录循环次数,与这一次扫描的所有macid
            log.info("In querySyncFailureRecordList: recon {} time with syncFailureRecordDOList size {} , collect macIds={}", reconTimes, syncFailureRecordDOList.size(),macIds);
            //如果扫描出的集合小于定下的升级条数,结束循环(代表已经扫描到了最后的一组数据)
            if (syncFailureRecordDOList.size() < limitSize) {
                isCompleted = true;
            }
            //如果扫描出的集合大小大于0(代表查出数据)
            if (syncFailureRecordDOList.size() > 0) {
                //修改下次扫描的起始id为集合的最后一个id
                startId =syncFailureRecordDOList.get(syncFailureRecordDOList.size() - 1).getId();
                //循环取出list里的对象
                for (SyncFailureRecordDO dto : syncFailureRecordDOList) {
                    if (dto != null) {
                        //同步需要放入kafuka的所有数据给安防管理平台
                        NvrDetailInfo nvrChannels = dcsManager.getNvrChannels(dto.getMacId());
                        JSONObject bizMsgObject = JSONObject.parseObject(dto.getBizMsg());
                        org.json.JSONObject kafkaData = new org.json.JSONObject();
                        kafkaData.put("macId", bizMsgObject.getString("macId"));
                        kafkaData.put("version", bizMsgObject.getString("version"));
                        kafkaData.put("modelId", bizMsgObject.getString("modelId"));
                        kafkaData.put("videoCapability", 2);
                        //加入升级后的通道数
                        kafkaData.put("channelNumber", nvrChannels.getNvrChannelList().size());
                        //同步方法
                        deviceVersionProducer.sendDeviceVersionMessage(dto.getMacId(), kafkaData.toString());
                        log.info("sendDeviceVersionMessage success, macId={}, channelNumber={}", dto.getMacId(), nvrChannels.getNvrChannelList().size());
                        //修改表中的status,为已经升级
                        Integer row = syncFailureRecordMybatis.updateRecordStatus(dto.getMacId());
                        log.info("updateRecordStatus success,rows={} affected,macId={}",row,dto.getMacId());
                    }
                }
            }
        }
        log.info("syncFailureRecord success");
        return ReturnT.SUCCESS;
    }
}

7:mybatis

List<SyncFailureRecordDO> querySyncFailureRecordList(@Param("limitSize") long limitSize, @Param("startId") Integer startId);

Integer updateRecordStatus(@Param("macId") String macId);

8:xml

<select id="querySyncFailureRecordList"
        resultType="com.cmcc.littlec.camera.dao.entity.SyncFailureRecordDO">
    SELECT uc.mac_id AS macId, uc.biz_msg AS bizMsg
    FROM t_firmware_version_sync_failure_record uc
    WHERE uc.id<![CDATA[ > ]]>#{startId}
      AND uc.biz_type = 1
      AND uc.status = 0
      AND created &gt;= DATE_SUB(NOW(), INTERVAL 1 DAY)
</select>

<update id="updateRecordStatus">
        UPDATE t_firmware_version_sync_failure_record
        SET modified = NOW(),
            status   = 1
        WHERE mac_id = #{macId}
    </update>

9:提交任务

开开心心提交代码给老大code review,老大说:这补偿为什么要我们来做,不合理;几个电话加个会议后决定:

让A平台上报SDK信息的时候带上升级后的通道数,我们只需要加个字段就可以了。。。。

好嘛!两天白干

10:总结

遇到问题能抛出去就抛出去!能麻烦别人就别麻烦自己

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/224258.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

U-boot(八):官方uboot移植

本文主要探讨从ubboot官方移植uboot到x210。 基础 确定设备的配置文件 通过board.cfg中的cpu型号(s5pc1xx)确定设备的配置文件 头文件:include/configs/s5p_goni.h cpu: u-boot-2013.10\arch\arm\cpu\armv7 board: u-boot-2013.10\b…

JVM 执行引擎篇

机器码、指令、汇编语言 机器码 各种用二进制编码方式表示的指令&#xff0c;叫做机器指令码。开始&#xff0c;人们就用它采编写程序&#xff0c;这就是机器语言。机器语言虽然能够被计算机理解和接受&#xff0c;但和人们的语言差别太大&#xff0c;不易被人们理解和记忆&a…

用23种设计模式打造一个cocos creator的游戏框架----(八)适配器模式

1、模式标准 模式名称&#xff1a;适配器模式 模式分类&#xff1a;结构型 模式意图&#xff1a;适配器模式的意图是将一个类的接口转换成客户端期望的另一个接口。适配器模式使原本接口不兼容的类可以一起工作。 结构图&#xff1a; 适用于&#xff1a; 系统需要使用现有的…

【从0配置JAVA项目相关环境2】node.js + 前端 从配置到运行

运行前端项目 写在最前面一、安装node.js二、运行前端项目1. 运行 npm install2. 运行 npm run serve报错Error: error:0308010C:digital envelope routines::unsupported方法1&#xff1a;设置 NODE_OPTIONS &#xff08;没用&#xff09;方法2&#xff1a;更改Node.js版本方法…

2023字节跳动软件测试工程师面试题及答案分享

相信大家都有这样一个忧虑就是面试&#xff0c;不管我们要找什么工作&#xff0c;面试都会是必不可少的&#xff0c;下面是整理出来的面试题和我的一些见解觉得不对的在评论区留言&#xff01; 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&…

2022年拉丁美洲中东和非洲医疗机器人市场及全球概况报告

今天分享的是机器人系列深度研究报告&#xff1a;《2022年拉丁美洲中东和非洲医疗机器人市场及全球概况报告》。 &#xff08;报告出品方&#xff1a;Apollo Reports&#xff09; 报告共计&#xff1a;195页 研究方法论 2.1通过桌面研究和内部存储库的假设 a)最初&#xff…

多传感器融合SLAM在自动驾驶方向的初步探索的记录

1. VIO的不可观问题 现有的VIO都是解决的六自由度的问题, 但是对于行驶在路面上的车来说, 通常情况下不会有roll与z方向的自由度, 而且车体模型限制了不可能有纯yaw的变换. 同时由于IMU在Z轴上与roll, pitch上激励不足, 会导致IMU在初始化过程中尺度不准以及重力方向估计错误,…

AWS 日志分析工具

当您的网络资源托管在 AWS 中时&#xff0c;需要定期监控您的 AWS CloudTrail 日志、Amazon S3 服务器日志和 AWS ELB 日志等云日志&#xff0c;以降低任何潜在的安全风险、识别严重错误并确保满足所有合规性法规。 什么是 Amazon S3 Amazon Simple Storage Service&#xff…

C#图像处理OpenCV开发指南(CVStar,07)——通用滤波(Filter2D)的实例代码

1 函数定义 void Filter2D (Mat src, Mat dst, int ddepth, InputArray kernel, Point anchor Point(-1,-1), double delta 0, int borderType BORDER_DEFAULT ) 1.1 原型 #include <opencv2/imgproc.hpp> Convolves an image wit…

搜维尔科技:Varjo如何提高汽车设计和驾驶测试的生产力

增强和虚拟现实技术有助于提高汽车、航空航天、工业生产等各个领域的工人生产力。尽管这些应用程序的上下文通常相当具体&#xff0c;但其中许多用例的某些方面是通用的。 在本文中&#xff0c;我们将具体探讨基于LP-RESEARCH的LPVR操作系统的 Varjo头戴式显示器的姿态跟踪主题…

AI伦理专题报告:2023年全球人工智能伦理治理报告

今天分享的是人工智能系列深度研究报告&#xff1a;《AI伦理专题报告&#xff1a;2023年全球人工智能伦理治理报告》。 &#xff08;报告出品方&#xff1a;钛媒体&#xff09; 报告共计&#xff1a;239页 摘要 人工智能(ArtificialIntelligence)作为新一轮科技革命和产业变…

Linux(centos)学习笔记(初学)

[rootlocalhost~]#:[用户名主机名 当前所在目录]#超级管理员标识 $普通用户的标识 Ctrlshift放大终端字体 Ctrl缩小终端字体 Tab可以补全命令 Ctrlshiftc/V复制粘贴 / &#xff1a;根目录&#xff0c;Linux系统起点 ls&#xff1a; #list列出目录的内容&#xff0c;通常用户查看…

Python BeautifulSoup 选择器无法找到对应元素(异步加载导致)

文章目录 问题原因解决方案找到包含内容的 XHR 异步请求无头浏览器 个人简介 问题 使用 Python BeautifulSoup 爬取一个股吧帖子发现某个样式无法找到&#xff0c;但是在网页中确实存在这个元素&#xff1a;网页使用 document.querySelector 可以正常查找&#xff1a; 但是 Py…

Http请求(bug)——路径变量传参遇到特殊符号的问题 URL中的#,?,符号作用

前言 本篇博客分析路径变量传参遇到特殊符号的问题&#xff0c;阐述了URL中的#&#xff0c;&#xff1f;&#xff0c;&符号作用。 目录 前言引出路径变量传参遇到特殊符号的问题问题描述问题分析 URL中的 #&#xff0c;&#xff1f;&#xff0c;&符号的作用URL中# 的作…

基于深度学习yolov5行人社交安全距离监测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介系统工作原理主要组成部分技术实现优势和特点应用场景和前景 二、功能三、系统四. 总结 一项目简介 基于深度学习 YOLOv5 的行人社交安全距离监测系统是一种…

2022年第十一届数学建模国际赛小美赛C题人类活动分类解题全过程文档及程序

2022年第十一届数学建模国际赛小美赛 C题 人类活动分类 原题再现&#xff1a; 人类行为理解的一个重要方面是对日常活动的识别和监控。可穿戴式活动识别系统可以改善许多关键领域的生活质量&#xff0c;如动态监测、家庭康复和跌倒检测。基于惯性传感器的活动识别系统用于通过…

学习记录---Kubernetes的资源指标管道-metrics api的安装部署

一、简介 Metrics API&#xff0c;为我们的k8s集群提供了一组基本的指标(资源的cpu和内存)&#xff0c;我们可以通过metrics api来对我们的pod开展HPA和VPA操作(主要通过在pod中对cpu和内存的限制实现动态扩展)&#xff0c;也可以通过kubectl top的方式&#xff0c;获取k8s中n…

近期复习三

目录 nginx.conf文件介绍 一.文件共享功能 1.清空html目录下文件并新建你要共享的文件 2.修改nginx.conf文件&#xff0c;开启autoindex功能 3.测试 二.状态模块 1.修改nginx.conf文件 2.测试 &#xff08;1&#xff09;使用刚才定义的IP/nginx_status进行访问 &#…

计算机图形图像技术(图像锐化处理与图像解析)

一、实验原理&#xff1a; 1、拓展Sobel算子锐化 void Sobel(Array src, Array dst, int ddepth, int dx, int dy, int ksize); ①参数&#xff1a;src为输入图像&#xff1b;dst为输出图像&#xff0c;大小和通道数与源图像一致&#xff0c;必要时重建&#xff1b;ddepth为目…

我把springboot项目从Java 8 升级 到了Java 17 的过程总结,愿为君提前踩坑!

项目从jdk8升级到jdk17&#xff0c;我不是为了追求java 17的新特性&#xff08;准确来说也还没有去了解有什么新特性&#xff09;&#xff0c;也不是为了准确与时俱进&#xff0c;永远走在java行列的最前端&#xff0c;纯粹因为项目需要&#xff0c;因为我们都知道&#xff0c;…
最新文章