• 设备接入服务组件->微服务and容器化改造说明文档


    SVN路径

    https://192.0.0.241/USTA-dac/branches/dev/V1.10.500/dac

    目录结构

    在这里插入图片描述

    • das为设备接入服务,负责驱动管理,资源同步,订阅下发。下面有两个文件夹分别对应了openssl1.0的版本和后面更换接口后openssl1.1的版本。
    • das_proxy为设备信令下发代理服务,主要控制云台等下发信令的转发。
    • dms为设备管理服务,负责数据持久化。
    • 微服务打包工具,负责将驱动成果物和das壳子打包成驱动微服务版本。

    驱动微服务如何部署

    在这里插入图片描述

    1. 编译

    在das目录用源码编译出来libConfigMgr.so(配置管理),libDevResMgr.so(设备管理),libDriverMgr.so(驱动管理),libProtocolProxy.so(协议代理)这四个库之后。将这几个库放入servicepackage文件夹。

    1. 放入驱动成果物

    将驱动包放到driverpackage文件夹里面

    1. 运行脚本

    运行脚本
    ./package.sh
    打包出来的微服务成果物在output文件夹下面

    1. 修改配置文件

    把包放到安装环境
    在驱动包的META-INF文件夹下driver.xml的加上event能力

    (重要!不然会导致订阅下发不下去)

    1. 安装微服务

    执行包下面的install.sh脚本
    systemclt restart 程序名启动程序

    ok,执行完这五部,驱动微服务版本部署完成。

    驱动das改动

    相对于基线设备接入服务有一些改动点

    1. 加入了新的注册接口
      主要改动在数据管理这个定时器里面
      CDataSrcMgr::OnTimer
      接口为,向dms注册。
    //RegisterDrvToDMS
    //驱动注册DMS的格式.
    POST /dac/driverManager/v1/driverRegister HTTP/1.1 
    Host: 10.14.69.25:8080 
    TOKEN: SElLIFRvdVBhWFFmd0xkdVNKRTI6bFFTY1ZUYTlpcEFkTjEyblZhYmVYTU5uQlN4TnVxS0VyVlhlbnVtWGdEOD0= 
    Cache-Control: no-cache 
    Postman-Token: 99498a85-4ff7-6e2a-24af-d4d78c4694fc 
    { 
       "indexCode":"test1", 
       "deviceKey":"drv_vss_hiksdk_general_1.10.100", 
       "addr":"10.19.133.74", 
       "port":8000
       "ehomePort":15000
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 服务标识生成的方式。与dms的地址读取方式
      基线das组件的服务标识与dms的地址ip信息,是运管生成,从配置文件中读取。
      而微服务版本的服务标识是驱动微服务第一次启动的时候随机生成,以文件的形式保存在本地,同时要向注册中心去注册。dms的地址从cousal注册中心中读取。
    //CConfigWrapper::Initialize
    //服务标识生成代码
    
    std::fstream fstr;
    const char* fileName = "dasIndexCode.txt";
    std::ios_base::openmode openMode = (std::ios::in | std::ios::out | std::ios::app);
    fstr.open(fileName, openMode);
    string dasIndexCode("");
    if(fstr)
    {
        std::ostringstream oStrStrDicCata;
        oStrStrDicCata << fstr.rdbuf();
        dasIndexCode = oStrStrDicCata.str();
        if(dasIndexCode.empty())
        {
            dasIndexCode=GetUUIDStr(8)+"-"+GetUUIDStr(4)+"-"+GetUUIDStr(4)+"-"+GetUUIDStr(4)+"-"+GetUUIDStr(12);
            fstr << dasIndexCode;
        }
        fstr.close();
    }
    else
    {
        DAF_ERROR("open file dasIndexCode.txt error.");
        nRet = CONFIGMGR_ERR_CSF_INIT;
        break;
    }
    
    //向注册中心注册
    char* config[] = {"dms", "bic"};
    //驱动直接向dms注册,此处所有不同类型驱动的名称相同,不能用于服务发现
    HPR_Strncpy(CsfParam.serverName,"dac-dasdvr",MAX_SERVER_NAME_LEN - 1);
    HPR_Strncpy(CsfParam.serverID,m_strIndexcode.c_str(),m_strIndexcode.size());
    CsfParam.nEnableFunctions = kAddress | kRegister;//向consul注册后所有类型驱动的名字都是dac-dasdvr
    CsfParam.extraConfigSize = 2;
    CsfParam.extraConfigArray = config;
    
    
    //在CConfigWrapper::OnTimer这个定时器中UpdateDmsHostInfo这个函数定时去获取dms的信息。
    //从注册中心获取dms地址。如果获取不到则用默认地址
    if (true != CsfDocker::instance()->GetSvrAddrArray("dac-dms", addarr, &chDmsIpSize))
    {
    	strIp = "127.0.0.1";
    	strPort = "8081";
    	DAF_ERROR("CsfDocker::instance()->GetSvrAddr dmsinfo from cfs error[err=%d]", Csf::GetLastError());
    }
    else
    {
    	for (int i = 0; i < chDmsIpSize; i++) {
    		string straddr = to_string(addarr[i].serverIP) + ":" + to_string(addarr[i].serverPort);
    		strIp = to_string(addarr[i].serverIP);
    		strPort = to_string(addarr[i].serverPort);
    		//如果地址没有变则退出
    		if (straddr == m_strDmsInfo) {
    			break;
    		}
    	}
    
    	DAF_INFO("CsfDocker::instance()->GetSvrAddr dmsinfo [ip=%s][port=%s]", strIp.c_str(), strPort.c_str());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    1. 支持event能力
      支持全能力下发
     //CDriverMgr_SyncDevSubEventInfo
     if (events.size() == 1 && ((events[0].asString() == "0") || events[0].asString() == "*")) {
    	listEvents.push_back(0);
    }
    else {
    	for (unsigned int j = 0; j < events.size(); ++j)
    	{
    		int iEvent = HPR_Atoi32(events[j].asString().c_str());
    		if (iEvent != 0)
    		{
    			listEvents.push_back(iEvent);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 设备信息修改之后的订阅
      设备信息修改了之后迁移之后会额外的去一个个单独获取一下设备的订阅信息。因为基线是das管理所有驱动所以并没有这个逻辑。而微服务是一个das对应一个驱动所以需要再获取一下,防止订阅信息丢失。
    //CDeviceMgr::ModifyDeviceInUserThread
    if (cListDevice.size()>0)
     {
          DEVRESMGR_INFO("SubDevEventInUserThread start");
          CDataSrcMgrSingleton::Instance()->SubDevEventInUserThread(cListDevice);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 其他
      其他还有一些小的改动,比如接口转换啥的,就一一列举了。

    问题排查

    目前遇到的问题最多的就是订阅问题。所以说解决了订阅下发的问题就解决了90%的问题。
    我改了很多bug之后,das壳子本身的问题应该是没有了。
    日志打的很多很详细。可以配合pluginframe的同事一起看下。如果没有发送到pluginframe就可以排查下das的问题。
    可以从下面几个方向切入

    1. 下发订阅的时间点。
      订阅在这几个时间点会下发:1.微服务重启的时候会全量像dms拉订阅信息 2.添加设备的时候dms会调/daf/v1/subEvent接口下发订阅。3.设备迁移的时候会去单个单个拉设备信息。
      如果是情况1.可以搜索GetDevEventInfoData和GetEventInfoData来确定有没有从dms拉到订阅信息。
      如果是情况2.可以搜索/daf/v1/subEvent来确定dms有无下发。如果有下发可以搜索subscribe查看对应的设备编号和下发的订阅信息。
      如果是情况3.可以搜索GetSingleDevEventInfoData begin,看下有无去获取单个设备订阅信息。如果有,则可以dms抓包看这个/dms/v1/device/indexCodes/eventInfo接口获取的订阅信息来排查
    2. 加解密。
      有时候获取到了订阅信息,驱动那边却说没有下发。可以根据日志报错看下有没有解密失败。如果是解密失败了的话,可以从密钥交互方向切入。
    3. 日志信息
      所有订阅下发都会经过Subscribe这个函数。可以搜索日志中一段时间Subscribe begin的打印来确定下发订阅的数量。下发前会把订阅地址解密后打印出来确保加密是没有问题的。
    4. 设备数量
      驱动有最大设备数量的限制,如果超过了最大设备数量,则超出的设备就直接不下发了,同样订阅也发不下来。

    补充

    其他还有啥需要补充的可以说下我再补充下。

    在这里插入代码片
    
    • 1
  • 相关阅读:
    常用的IO工具类
    763.划分字母区间——之打开新世界
    基于 FastAPI 的房源租赁系统设计与实现
    【面试题精讲】SpringTemplate使用
    跳跃游戏 I - VII
    我HTTP协议用的好好的,为什么还要用RPC协议?
    设计高并发秒杀系统:保障稳定性与数据一致性
    猜数字游戏(Rust实现)
    α微管蛋白研究丨SYSY α微管蛋白抗体案例分析
    什么是多线程环境下的伪共享(false sharing)?
  • 原文地址:https://blog.csdn.net/weixin_38616018/article/details/129142752