摘 要:本文設(shè)計(jì)了一種海量傳感器數(shù)據(jù)存儲(chǔ)系統(tǒng),使用MongoDB作為數(shù)據(jù)庫(kù),同時(shí)使用Boos.Asio網(wǎng)絡(luò)庫(kù)應(yīng)對(duì)終端高并發(fā)請(qǐng)求。
【關(guān)鍵詞】MongoDB Asio 傳感器數(shù)據(jù) 存儲(chǔ)系統(tǒng)
1 引言
在物聯(lián)網(wǎng)當(dāng)中,每個(gè)終端節(jié)點(diǎn)每隔幾秒鐘就會(huì)將多個(gè)傳感器采集的數(shù)據(jù)傳輸?shù)椒?wù)器中,在大量終端節(jié)點(diǎn)的情況下會(huì)產(chǎn)生海量的數(shù)據(jù)。傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)已經(jīng)無(wú)法滿足海量數(shù)據(jù)的存儲(chǔ)和管理,MongoDB是專門為解決海量數(shù)據(jù)而產(chǎn)生的,本系統(tǒng)使用MongoDB存儲(chǔ)海量傳感器數(shù)據(jù)。服務(wù)器端必須能夠處理大量終端節(jié)點(diǎn)的高并發(fā)請(qǐng)求,本系統(tǒng)使用Boost.Asio網(wǎng)絡(luò)庫(kù)應(yīng)對(duì)終端海量高并發(fā)請(qǐng)求。
2 MongoDB及其部署
2.1 MongoDB簡(jiǎn)介
MongoDB的文檔、集合相當(dāng)于關(guān)系型數(shù)據(jù)庫(kù)中的行和表,其文檔使用BSON格式存儲(chǔ),其典型格式如:{ id:123,temperature:23, humidity: 60}??梢娖浞浅_m合物聯(lián)網(wǎng)終端節(jié)點(diǎn)的傳感器數(shù)據(jù)的存儲(chǔ)。
MongoDB通過分片(Shard)和副本集(replica set)實(shí)現(xiàn)對(duì)數(shù)據(jù)的備份和高性能處理。分片,就是將一份數(shù)據(jù)分成多個(gè)片段,每個(gè)分片儲(chǔ)存不同的部分,分片不僅分擔(dān)了數(shù)據(jù)在硬盤的存儲(chǔ),還分擔(dān)了數(shù)據(jù)操作對(duì)機(jī)器內(nèi)存、CPU、網(wǎng)絡(luò)的IO和硬盤的讀寫壓力。如圖1所示。
2.2 MongoDB集群部署
典型的MongoDB集群部署模型如圖1所示。每個(gè)分片就是mongod程序的實(shí)例,在進(jìn)行數(shù)據(jù)的增刪查改操作時(shí)需要通過mongos程序?qū)⒄?qǐng)求分發(fā)到對(duì)應(yīng)的分片上,mongos起到了路由的功能,它需要從配置服務(wù)器(config server)讀分片和路由等元數(shù)據(jù)信息。replica set就是數(shù)據(jù)的備份,也是mongod程序的實(shí)例。在生產(chǎn)環(huán)境下根據(jù)業(yè)務(wù)的需求來(lái)確定服務(wù)器的數(shù)量和mongos、mongod以及config server的數(shù)量。在程序連接數(shù)據(jù)庫(kù)時(shí),只要連接mongos的地址和端口即可。
3 程序設(shè)計(jì)
本程序的主要功能是處理終端海量的高并發(fā)請(qǐng)求,將數(shù)據(jù)解析后寫入MongoDB數(shù)據(jù)庫(kù)。
3.1 Boost.Asio簡(jiǎn)介
Boost.Asio是一款非常優(yōu)秀的C++開源網(wǎng)絡(luò)庫(kù),支持同步編程和異步編程,能夠構(gòu)建出能夠承受數(shù)千并發(fā)連接的應(yīng)用程序,并且不必涉及顯式鎖定和線程并發(fā)模型,從而避免使用多線程編程帶來(lái)的死鎖、條件競(jìng)爭(zhēng)等。
3.2 配置模塊和日志模塊設(shè)計(jì)
在程序中,服務(wù)器端口號(hào)、MongoDB集群地址、程序并發(fā)執(zhí)行線程數(shù)等配置信息采用JSON格式文件存儲(chǔ)。使用Boost庫(kù)中的property_tree作為程序解析JSON文件的工具。日志可以幫助程序員在開發(fā)中快速定位bug,本程序使用boost::log記錄日志。
3.3 MongoDB模塊設(shè)計(jì)
在高并發(fā)請(qǐng)求下,為避免每次請(qǐng)求到來(lái)頻繁連接和關(guān)閉數(shù)據(jù)庫(kù),MongoDB的C++驅(qū)動(dòng)提供了線程安全的連接池。本模塊設(shè)計(jì)了Mymongo類,內(nèi)部封裝了mongo::ScopedDBConnection類,實(shí)例化該類,便獲得一個(gè)數(shù)據(jù)庫(kù)連接。在Mymongo類的構(gòu)造函數(shù)中完成對(duì)數(shù)據(jù)庫(kù)的連接認(rèn)證等,在析構(gòu)函數(shù)中釋放連接到連接池。本程序只需要將終端數(shù)據(jù)插入到數(shù)據(jù)庫(kù)中,因此Mymongo類只實(shí)現(xiàn)了數(shù)據(jù)的插入功能。
3.4 請(qǐng)求處理模塊
本模塊實(shí)現(xiàn)了Service類,包含start()、accept_handler()、read_handler()三個(gè)成員函數(shù)。使用該類時(shí),其執(zhí)行流程如圖2所示:首先執(zhí)行其start成員函數(shù),在函數(shù)中采用異步accept方式等待連接到來(lái),其回調(diào)函數(shù)為accept_handler,當(dāng)連接到來(lái)后,執(zhí)行回調(diào)函數(shù),在其中采用異步方式讀取套接字,并注冊(cè)回調(diào)函數(shù)read_handler,因?yàn)槭钱惒阶x取,不等待讀取完畢,再次調(diào)用start函數(shù),等待下一個(gè)連接到來(lái)。當(dāng)套接字讀取完畢后,會(huì)調(diào)用read_handler,在函數(shù)中會(huì)解析終端發(fā)來(lái)的請(qǐng)求,并使用Mymongo類將數(shù)據(jù)寫入MongoDB數(shù)據(jù)庫(kù)。如圖2所示。
3.5 io_service模型選擇
io_service類是Boost.Asio的核心,相當(dāng)于前攝器模式中的Proactor角色,asio的任何操作都需要其參與。在主函數(shù)中首先實(shí)例化一個(gè)io_service對(duì)象,在實(shí)例化Service對(duì)象時(shí)作為其參數(shù),啟動(dòng)Service對(duì)象的start()函數(shù)后,在多個(gè)線程中調(diào)用這個(gè)io_service對(duì)象的run()函數(shù)。這相當(dāng)于在多個(gè)線程中同時(shí)阻塞等待異步操作的完成,當(dāng)有異步操作完成時(shí),便會(huì)調(diào)用相應(yīng)的回調(diào)函數(shù)。這是其最為常用的模型,可以編寫出非常健壯的應(yīng)用程序,本程序選擇一個(gè)io_service實(shí)例多個(gè)線程的模型。
4 結(jié)語(yǔ)
本文所設(shè)計(jì)的傳感器數(shù)據(jù)存儲(chǔ)系統(tǒng),使用了MongoDB數(shù)據(jù)庫(kù)存儲(chǔ)管理海量數(shù)據(jù),并使用Boost.Asio網(wǎng)絡(luò)庫(kù)的異步編程方式,配合多線程技術(shù),編寫了能夠接收海量高并發(fā)請(qǐng)求的服務(wù)器端程序,在程序中使用MongoDB連接池來(lái)連接數(shù)據(jù)庫(kù),避免資源的浪費(fèi)。
參考文獻(xiàn)
[1]郭匡宇.基于MongoDB的傳感器數(shù)據(jù)分布式存儲(chǔ)的研究與應(yīng)用[D].南京郵電大學(xué),2013.
[2]MongoDB.sharding. https://docs.mongodb.org/manual/core/sharding-introduction/.
[3]Boost.Asio. http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio.html.
作者簡(jiǎn)介
李曉(1989-),男,現(xiàn)為中國(guó)海洋大學(xué)信息科學(xué)與工程學(xué)院信號(hào)與信息處理專業(yè)在讀研究生。
作者單位
中國(guó)海洋大學(xué)信息科學(xué)與工程學(xué)院 山東省青島市 266100