gatewayworker中需要定時給設(shè)備發(fā)送modbus命令讀取數(shù)據(jù),一個柜子下理論最多有255個探頭,我現(xiàn)在的思路是把所有探頭根據(jù)參數(shù)生成命令存放在session中,每個柜子一個定時器定時遍歷發(fā)送命令
因為modbus下存在一種寄變模式,根據(jù)返回的值無法確定這包數(shù)據(jù)是屬于哪個探頭的,所以需要延時等待結(jié)果,完成一個過一個,但框架不能用sleep
我現(xiàn)在有三個解決思路:
1,用globaldata組件共享數(shù)據(jù),專門寫一個worker來處理定時發(fā)送命令,里面使用sleep[有個疑問?這里使用sleep只是對應(yīng)的這個worker進(jìn)程不能處理其他請求,還是整個框架都進(jìn)入睡眠停止工作,比如負(fù)責(zé)連接設(shè)備的gateway進(jìn)程會不會受影響];
2,用http把參數(shù)傳出去用網(wǎng)頁那邊發(fā)送命令;
3,遍歷生成定時器,每個定時器執(zhí)行時間岔開固定時間,也可以實現(xiàn)延時發(fā)送效果;
因為以上三個思路存在額外開銷或者需要生成最大大于原思路200倍以上的定時器數(shù)量,比較擔(dān)心性能和穩(wěn)定性,如果拋開以上三個思路,您有更好的思路推薦嗎?或者沒有其他更好的思路,以上三個思路您推薦哪個,非常感謝
如果你的設(shè)備不支持同時處理多個探頭數(shù)據(jù)(因為返回結(jié)果無法確定是哪個探頭的結(jié)果),那么就需要把數(shù)據(jù)存儲成一個類似隊列的存儲結(jié)構(gòu)里,比如存在mysql里,每條數(shù)據(jù)需要標(biāo)記是否發(fā)送給了設(shè)備,發(fā)送時間,是否返回了結(jié)果,返回結(jié)果時間。設(shè)備上線后從數(shù)據(jù)庫里讀一個這個設(shè)備未收到回復(fù)的請求,然后發(fā)送。服務(wù)端onMessage收到回復(fù)后標(biāo)記收到回復(fù)及時間,然后再查一遍是否有下個等待發(fā)送的請求,有的話繼續(xù)。
以上邏輯不需要什么延遲等待結(jié)果。但是需要考慮一些極端情況,比如發(fā)給設(shè)備請求后,設(shè)備一直沒返回響應(yīng),那么如何處理?比如斷開連接,讓設(shè)備重連重新發(fā)送?還是直接重新發(fā)送,如果直接重新發(fā)送會不會得到2個響應(yīng),導(dǎo)致錯誤標(biāo)記到下一條請求被響應(yīng)? 建議弄個定時任務(wù),查詢超時的請求,然后斷開對應(yīng)的連接。
老大,我可能邏輯沒說清楚,場景是這樣的,柜子負(fù)責(zé)聯(lián)網(wǎng)并轉(zhuǎn)發(fā)服務(wù)器指令到對應(yīng)的探頭,探頭反饋結(jié)果也會經(jīng)由柜子中轉(zhuǎn)發(fā)送給服務(wù)器,它們使用MODBUS RTU協(xié)議,柜子充當(dāng)一個終端設(shè)備,它底下可能拖了N+<255個探頭,探頭與服務(wù)器是通過柜子中繼通訊的,服務(wù)器需要周期性的不停發(fā)送讀取指令給每個探頭,探頭反饋的數(shù)據(jù)存放在Session中并不斷更新,我會寫另一個定時器去周期性讀取該數(shù)據(jù)進(jìn)行存儲,也可以通過gatewayclient去獲取,這是業(yè)務(wù)主邏輯
讀取指令是當(dāng)柜子上線后實時算出來的,比如A柜子下有三個探頭,那么我便存三條命令到session中,周期性發(fā)送,不用數(shù)據(jù)庫存儲是因為每次柜子上線需要做的準(zhǔn)備工作中有足夠的因素實時計算出讀取指令,這樣即可以保證準(zhǔn)確性也避免了多余的數(shù)據(jù)庫讀操作
而前面提到的需要延遲等待是因為,探頭因為各種原因,工作環(huán)境,本身的配置及網(wǎng)絡(luò)等因素影響,未必能快速及時的反饋結(jié)果,而且無間隔發(fā)送指令會導(dǎo)致卡頓或認(rèn)為是無效指令進(jìn)行丟棄,畢竟那里面只是一個單片機(jī)和計算機(jī)比簡直天淵之別,所以需要服務(wù)器這邊控制好發(fā)送間隔
為保證穩(wěn)定我打算每條指令之間延遲2s,我已經(jīng)寫完設(shè)備匹配部分了,大致思路和你寫的一樣,因為匹配在網(wǎng)頁中進(jìn)行那邊是接口操作,可以進(jìn)行sleep,通過gatewayclient發(fā)送讀取指令,在發(fā)送讀取指令前,updateSession把讀取的設(shè)備編號存進(jìn)去,gateway拿到數(shù)據(jù)更新并清空上一步傳過來的編號,進(jìn)入下一個邏輯循環(huán)往復(fù)就可以了,現(xiàn)在的問題是框架中不能sleep所以才遇到問題,因為考慮的東西比較多,主要是性能,所以走的思路和您的不太一樣,如果是這樣的情況,您推薦怎么做,謝謝指點~
用sleep會導(dǎo)致進(jìn)程睡眠,會影響當(dāng)前進(jìn)程的其它業(yè)務(wù)處理。如果這個進(jìn)程只負(fù)責(zé)一個柜子,那么沒有什么影響。
workerman的定時器也有延遲的效果,我覺得每個柜子一個定時器簡單些。如果你的定時器是動態(tài)創(chuàng)建的,比如在柜子連接上來的時候創(chuàng)建,記得在連接斷開的時候刪除定時器。否則只創(chuàng)建定時器又不刪除會不斷占用內(nèi)存,導(dǎo)致內(nèi)存泄漏。