gatewayworker中需要定时给设备发送modbus命令读取数据,一个柜子下理论最多有255个探头,我现在的思路是把所有探头根据参数生成命令存放在session中,每个柜子一个定时器定时遍历发送命令
因为modbus下存在一种寄变模式,根据返回的值无法确定这包数据是属于哪个探头的,所以需要延时等待结果,完成一个过一个,但框架不能用sleep
我现在有三个解决思路:
1,用globaldata组件共享数据,专门写一个worker来处理定时发送命令,里面使用sleep[有个疑问?这里使用sleep只是对应的这个worker进程不能处理其他请求,还是整个框架都进入睡眠停止工作,比如负责连接设备的gateway进程会不会受影响];
2,用http把参数传出去用网页那边发送命令;
3,遍历生成定时器,每个定时器执行时间岔开固定时间,也可以实现延时发送效果;
因为以上三个思路存在额外开销或者需要生成最大大于原思路200倍以上的定时器数量,比较担心性能和稳定性,如果抛开以上三个思路,您有更好的思路推荐吗?或者没有其他更好的思路,以上三个思路您推荐哪个,非常感谢
如果你的设备不支持同时处理多个探头数据(因为返回结果无法确定是哪个探头的结果),那么就需要把数据存储成一个类似队列的存储结构里,比如存在mysql里,每条数据需要标记是否发送给了设备,发送时间,是否返回了结果,返回结果时间。设备上线后从数据库里读一个这个设备未收到回复的请求,然后发送。服务端onMessage收到回复后标记收到回复及时间,然后再查一遍是否有下个等待发送的请求,有的话继续。
以上逻辑不需要什么延迟等待结果。但是需要考虑一些极端情况,比如发给设备请求后,设备一直没返回响应,那么如何处理?比如断开连接,让设备重连重新发送?还是直接重新发送,如果直接重新发送会不会得到2个响应,导致错误标记到下一条请求被响应? 建议弄个定时任务,查询超时的请求,然后断开对应的连接。
老大,我可能逻辑没说清楚,场景是这样的,柜子负责联网并转发服务器指令到对应的探头,探头反馈结果也会经由柜子中转发送给服务器,它们使用MODBUS RTU协议,柜子充当一个终端设备,它底下可能拖了N+<255个探头,探头与服务器是通过柜子中继通讯的,服务器需要周期性的不停发送读取指令给每个探头,探头反馈的数据存放在Session中并不断更新,我会写另一个定时器去周期性读取该数据进行存储,也可以通过gatewayclient去获取,这是业务主逻辑
读取指令是当柜子上线后实时算出来的,比如A柜子下有三个探头,那么我便存三条命令到session中,周期性发送,不用数据库存储是因为每次柜子上线需要做的准备工作中有足够的因素实时计算出读取指令,这样即可以保证准确性也避免了多余的数据库读操作
而前面提到的需要延迟等待是因为,探头因为各种原因,工作环境,本身的配置及网络等因素影响,未必能快速及时的反馈结果,而且无间隔发送指令会导致卡顿或认为是无效指令进行丢弃,毕竟那里面只是一个单片机和计算机比简直天渊之别,所以需要服务器这边控制好发送间隔
为保证稳定我打算每条指令之间延迟2s,我已经写完设备匹配部分了,大致思路和你写的一样,因为匹配在网页中进行那边是接口操作,可以进行sleep,通过gatewayclient发送读取指令,在发送读取指令前,updateSession把读取的设备编号存进去,gateway拿到数据更新并清空上一步传过来的编号,进入下一个逻辑循环往复就可以了,现在的问题是框架中不能sleep所以才遇到问题,因为考虑的东西比较多,主要是性能,所以走的思路和您的不太一样,如果是这样的情况,您推荐怎么做,谢谢指点~
用sleep会导致进程睡眠,会影响当前进程的其它业务处理。如果这个进程只负责一个柜子,那么没有什么影响。
workerman的定时器也有延迟的效果,我觉得每个柜子一个定时器简单些。如果你的定时器是动态创建的,比如在柜子连接上来的时候创建,记得在连接断开的时候删除定时器。否则只创建定时器又不删除会不断占用内存,导致内存泄漏。
好的,谢谢
学习了学习了