大家好,又見面了,我是你們的朋友全棧君。
基于java的多裝置類型物聯網架構實作
前言:19年11月開始從 【金融】行業轉 【物聯網】,路途坎坷,一個人摸索前進,不過也學到了很多新的東西,交了很多好朋友,在此感謝各位!
以下是一些經驗分享,希望能幫到有需要的朋友。
1、架構思路
考慮了很久打算用springboot + mysql 去實作,因為熟悉這個架構,而且能減輕70%的機械性開發工作量,以後改springcloud也友善(注意邏輯實作不然工作量很大)。
物聯網和網際網路可以說是有共同點的,但是也有很多的不一樣。
先說協定,網際網路很多都是https或者http,但是物聯網這塊就不僅僅是這兩種協定,會有UDP協定,TCP協定。
上幹貨:
環境:java+mysql+redis+rabbitMQ+Mqtt
圖解:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuEWOykjZyU2MyYWNlBzYjhzMyEjZiBDM0EGM4UWMjNGMvw1NzUzMyIDOtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
這個是比較簡單的邏輯圖,裡面的複雜邏輯還是不能說的。
這裡面涉及到幾個問題,好多物聯網裝置終端會有心跳,事件資料上來,怎麼保證并發?入庫的資料唯一?多種裝置的資料上行,怎麼存儲?怎麼管理?有多個第三方服務怎麼分發資料?
咱們一點點說:
1、根據協定解析資料
終端上行的資料有433協定,有藍牙的,有zigbee的,還有tcp、http的,還分1代、2代、3代等協定。我用了一個笨方法:根據協定的不同解析,存入不同的表
我整了個枚舉類來存放不同的類型,在解析方法裡面通過唯一性的一段上行資料去區分(為什麼這麼做?以為上行資料是16進制的)
HH0F22AEBB8200011100020001BB23AABB8637
複制
“HH0F”就是A協定的特有字元,那這個就入A協定庫。
A協定是A裝置專用的,那建表就是這樣的
A_tag —————— 裝置表
A_data ——————裝置資料表
A_gateway ——————網關表
複制
那麼問題來了,要是10種裝置不得30個表了?
做過物聯網的都知道,不同類型的裝置可能帶的屬性都是不一樣的,有的裝置可能就3個:
電量、包序、特征值
但是有的裝置可能就不止了,比方說:
電量、包序、心跳、呼吸、體溫、動态值。。。。
data表中資料不得爆掉?——我深思熟慮也隻是想到通用字段存儲,data1~data20
多裝置類型的暫時解決了,後面怎麼具體操作呢?
2、怎麼保證資料不會重複并快速入庫
上圖我采用了兩個服務,一個接受服務,一個處理服務,具體處理方法:
接受服務将受到的資料轉base64編碼後直接發到消息隊列(rabbitMQ),處理服務監聽rabbitMQ消息,走解析服務。就是這麼簡單!
但是,有一點,rabbitMQ要開啟ack模式!!!而且可以用負載來做這步!
問題二:裝置一多,并發問題就來了,怎麼搞?
Semaphore 這可是個好東西
如果來一條資料就insert,哪個資料庫都受不了,後來采用批量方式插入:
// ----------------------資料批量入庫開始-------------------------
private static List<NnData> listNnObjectSaveDO = new ArrayList<NnData>();
private static Long startTimeNnData = 0L;
//private static int countSend = 0;
private static Semaphore semaphoreNnData = new Semaphore(1);
@Override
public void saveDO(NnData nnData) {
try {
semaphoreNnData.acquire();
if (startTimeNnData == 0L) {
startTimeNnData = System.currentTimeMillis();
}
listNnObjectSaveDO.add(nnData);
if (System.currentTimeMillis() - startTimeNnData > 2000) {
List<NnData> listSaveDOOne = new ArrayList<NnData>();
listSaveDOOne.addAll(listNnObjectSaveDO);
asyncInsertBatch(listSaveDOOne);
listNnObjectSaveDO.clear();
startTimeNnData = 0L;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
semaphoreNnData.release();
}
}
@Async
private void asyncInsertBatch(List<NnData> list) {
this.insertBatch(list);
//countSend = countSend + list.size();
//System.out.println("=================入庫資料條數:" + countSend);
}
// ----------------------資料批量入庫結束-------------------------
複制
我做過測試,這樣的方式遠超2000條/秒,有眼尖的朋友看出來了:
System.currentTimeMillis() - startTimeNnData > 2000 //2秒批量入庫一次
複制
暫時就到這兒,後續想到我再補充!
版權聲明:本文内容由網際網路使用者自發貢獻,該文觀點僅代表作者本人。本站僅提供資訊存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌侵權/違法違規的内容, 請發送郵件至 舉報,一經查實,本站将立刻删除。
釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/192118.html原文連結:https://javaforall.cn