目錄
表目錄 11
圖目錄 13
第一章引言 1
1.1項目背景 1
1.2項目意義 2
1.3國內外現狀 3
1.4本文主要工作 4
1.5本文的組織結構 4
第二章相關技術概述 6
2.1微服務 6
2.2Spring 7
2.2.1Spring 框架 7
2.2.2Spring Boot 8
2.2.3Spring Cloud 9
2.3MyBatis 10
2.4Redis 12
2.5MongoDB 12
2.6本章小結 14
第三章新風設備信息管理子系統的需求與設計 15
3.1系統需求分析 15
3.1.1系統總體需求分析 15
3.1.2短信功能需求分析 17
3.1.3支付功能需求分析 18
3.1.4空氣質量模塊需求分析 20
3.1.5用戶行為統計需求分析 21
3.1.6數據開放平臺需求分析 21
3.2系統總體架構設計 24
3.3系統模塊設計 26
3.3.1短信模塊設計 26
3.3.2支付模塊設計 29
3.3.3空氣質量模塊設計 32
3.3.4用戶行為統計模塊設計 35
3.3.5數據開放平臺模塊設計 37
3.4本章小結 38
第四章新風設備信息管理子系統的詳細實現 39
4.1 短信模塊 39
4丄1發送短信代碼實現 39
4.1.2短信管理代碼實現 41
4.2支付模塊 42
4.2.1支付訂單代碼實現 42
4.3空氣質量模塊 45
4.3.1獲取數據代碼實現 45
4.3.2 數據整合實現 47
4.4用戶行為統計模塊 49
4.4.1行為數據整合實現 49
4.4.2定時備份數據實現 50
4.5數據開放平臺模塊 52
4.5.1第三方平臺注冊實現 52
4.5.2數據開放代碼實現 54
4.6 本章小結 56
第五章新風設備信息管理子系統測試 57
5.1測試環境與思路 57
5.1.1測試環境 57
5.1.2測試思路 58
5.2測試過程與結果 58
5.2.1功能測試 58
5.2.1.1短信功能測試 58
5.2.1.2支付功能測試 59
5.2.1.3獲取城市空氣質量數據功能測試 60
5.2.1.4用戶行為數據統計功能測試 60
5.2.1.5數據開放功能測試 61
5.2.2性能測試 62
5.3 本章小結 63
第六章總結與展望 64
6.1總結 64
6.2工作展望 65
參考文獻 66
簡歷與科研成果 69
致謝 70
版權與原創性說明 71
表目錄
3.1批量發送短信用例描述表 18
3.2短信查詢用例描述表 18
3.3微信小程序支付用例描述表 19
3.4訂單管理用例描述表 19
3.5用戶查詢室外空氣用例描述表 20
3.6管理員查詢城市空氣質量用例描述表 20
3.7管理員查詢用戶行為信息用例描述表 21
3.8訂閱設備用例描述表 23
3.9獲取設備列表用例描述表 23
3.10獲取設備運行狀態用例描述表 24
3.11獲取城市空氣數據用例描述表 25
3.12移除設備用例描述表 25
3.13短信模塊發送短信數據表 28
3.14短信模塊接收短信數據表 29
3.15短信模塊短信模板數據表 29
3.16賬單信息數據表 31
3.17交易渠道數據表 32
3.18交易快照數據表 32
3.19墨跡信息數據表 35
3.20每日空氣質量指數統計數據表 35
3.21省份空氣質量指數統計數據表 35
3.22每小時設備風量統計數據表 36
3.23每日設備模式統計數據表 37
3.24用戶操作設備組件統計數據表 37
3.25第三方平臺信息表 38
3.26用戶訂閱設備關聯表 38
5.1測試環境部署詳情 57
5.2服務部署端口配置 57
5.3發送短信功能測試用例 58
5.4查詢短信記錄功能測試用例 59
5.5支付功能測試用例 60
5.6獲取城市空氣質量數據用例 60
5.7用戶行為數據統計測試用例 61
5.8數據開放測試用例 61
5.9支付模塊性能測試服務器表現 62
5.10數據開放模塊性能測試服務器表現 63
圖目錄
2.1Spring IoC 實現原理 8
2.2Spring Cloud 組件結構圖 10
2.3從功能流程層次描述MyBatis的整體架構圖 11
2.4關系型數據庫與MongoDB數據存儲形式對比圖 13
3.1新風設備信息管理子系統用例圖 15
3.2短信模塊用例圖 17
3.3數據開放平臺模塊用例圖 22
3.4系統總體架構圖 26
3.5發送短信流程圖 27
3.6短信模塊結構圖 28
3.7支付模塊結構圖 30
3.8支付模塊邏輯層類圖 30
3.9支付模塊數據庫ER圖 31
3.10空氣質量模塊結構圖 33
3.11空氣質量模塊邏輯層類圖 34
3.12用戶行為統計模塊結構圖 36
3.13授權平臺方操作設備流程圖 38
4.1發送短信功能邏輯時序圖 39
4.2發送短信功能前端頁面 40
4.3調用第三方服務發送短信代碼實現 40
4.4短信模塊實現發送短信功能代碼實現 41
4.5查詢外發短信頁面截圖 42
4.6查詢回復短信頁面截圖 42
4.7微信小程序端下單支付邏輯時序圖 43
4.8 訂單查詢頁面截圖 44
4.9處理微信支付結果代碼實現 44
4.10獲取城市空氣質量邏輯時序圖 46
4.11調用第三方服務獲取空氣數據代碼實現 46
4.12微信公眾號查看空氣質量頁面截圖 47
4.13整合每小時空氣質量數據代碼實現 48
4.14查詢城市空氣質量頁面截圖 48
4.15用戶行為數據整合邏輯時序圖 49
4.16用戶行為數據整合代碼實現 50
4.17用戶行為統計頁面截圖 51
4.18導出MongoDB中數據代碼實現 51
4.19整理MongoDB磁盤空間腳本代碼 52
4.20第三方注冊代碼實現 53
4.21查詢第三方平臺信息代碼實現 53
4.22查詢注冊第三方信息頁面截圖 54
4.23數據開放模塊邏輯時序圖 55
4.24訂閱設備代碼實現 55
4.25第三方訂閱設備管理頁面截圖 56
5.1系統給用戶發送短信結果 59
5.2查詢授權平臺方已訂閱的設備結果 62
第一章 引言
1.1 項目背景
隨著計算機技術的高速發展, 互聯網已經成為了幾乎每一個人生活、工作的 必需, 各種軟件技術漸漸得到普及,服務器等硬件成本也越來越低。而對于企業 管理者來說, 構建一套設備信息管理系統, 可以更高效更低成本地對用戶和設備 進行管理,實現數據的透明化,被逐漸認可。通過信息管理系統, 不僅可以使數 據更透明更易管理和操作, 也會大大節省人力資源和時間成本, 從而獲得更高效 益。而隨著移動互聯和智能終端技術的日新月異 [1],越來越多的人希望在家庭 生活中更多的使用科技,既可以便捷生活,也可以達到環保的目的 [2]。
因此,智能家居、信息家電已經成為了當下更多用戶選擇家居商品時的首 選 [3]。智能家居不僅可以通過數字化和網絡技術多方面的進入家庭生活,并且 可以通過網絡系統與用戶進行交互,為家庭生活創造更高品質的生活環境。而 基于微信平臺的企業公眾號不僅是用戶獲取企業最新消息的一個渠道, 同時也可 以作為傳輸控制命令的入口, 這為遠端在聯網狀態下直接控制設備提供了又一接 口。
某公司是一家主要銷售新風設備的創新型環保科技公司。用戶可以通過線 上和線下兩種方式購買產品。線上主要是指通過天貓、京東等電商平臺購買,線 下是指傳統人工銷售的方式。傳統的空氣凈化設備都是由物理硬件直接控制,通 過直接觸控機器表面的開關或者通過紅外遙控控制設備,達到用戶的需求。并 且,對于種類不同,甚至型號不同的設備,都需要提出一種不同的控制方法要求 用戶掌握。傳統設備都屬于單機狀態,對于用戶的大量行為數據無法收集,無法 更準確地了解用戶需求。而用戶的個體行為多呈現規律性,如果可以對數據進 行統計分析,就可以為定制用戶個性化方案的研發奠定基礎。同時,采用人工 統計數據的方式,數據量有限并且不夠精準,不足以提供可靠有效的數據支撐 并且,沒有掌握用戶的行為數據也給售后服務人員增加了工作負擔。并且在用 戶使用時的很多場景中,如果設備可以更智能化地增加與用戶的交互,在很大 程度上可以提升用戶體驗。
而新風設備的效果主要體現在室內空氣質量是否有所提升,是否達到了用 戶想要凈化室內空氣的目的。因此單一展示出室內空氣質量并不足以提升用戶 體驗。如果可以獲取到用戶當前所在城市的空氣質量指數,再對比安裝新風設 備后的室內空氣質量,數據的展示會使凈化效果會非常直觀。
另外,當今的市場上某些大型企業已經開始運營自身的企業生態鏈模式。對 于小型單一產品企業來說,加入其他企業的生態圈,使用戶可以在其他平臺內 使用到本公司的產品,可以擴大產品的銷售渠道,拓展市場 [4]。而怎樣把自有 產品加入到其他企業的生態鏈中,提供給第三方集成,這也給企業提出了新的 需求。
而公司原有的信息管理系統雖然已經滿足訂單管理、發貨管理、安裝管理 等基礎功能,完整實現線上線下銷售、安裝設備、提供售后服務的流程,并對 所有信息系統化管理,但隨著對于銷售渠道的拓展和產品推廣的訴求日益強烈 從設計研發、銷售再到用戶使用,原有系統已經不足以滿足上述的需求。例如 在特定場景下管理員需要及時通知用戶信息,原本只能采用手動發送短信或電 話的方式,并手動對記錄進行存儲和管理,系統相關的業務支撐能力有待加強 目前用戶線上購買商品只能通過天貓、京東等電商平臺,系統中還沒有構建自 己的銷售平臺因此對于銷售渠道的拓展和產品的推廣有強烈訴求;用戶可以在 微信公眾號內控制設備的同時,也可以查看到設備所監控到的室內空氣質量,但 是用戶并不能直觀感受到空氣被凈化的程度,即新風設備所實現的效果;并且 目前的信息管理系統對大量的用戶行為數據沒有進行處理,對數據利用率低,統 計分析能力弱,難以提供更好的服務與體驗。最后,基于智能家居在當下的發展 趨勢,該公司的信息管理系統也需要提供數據開放的能力。
1.2 項目意義
當前,智能家居已經逐漸進入到越來越多的家庭,用智能手機和 APP 與智 能家具相連接建立的智能家居系統,可以進一步方便消費者的生活 [3]。而對于 每個智能家居企業來說,無論是從公司運營還是產品管理角度,都需要研發一 套信息管理系統,來對從產品研發、產品銷售,再到用戶使用、提供售后服務等 流程中產生的一系列信息進行高效、便捷的管理。
在考察和調研了大量真實用戶需求和上文所提到的業務場景變化所帶來的 新需求,并且對原有的信息管理系統進行細致分析后,基于當前公司對于一款 新風設備產品的營銷推廣的強烈訴求,本文提出了在原有的信息管理系統中加 入新的板塊的方案,旨在于提升產品競爭力,支撐產品的營銷推廣,為優化產品 提供數據支持,同時減少企業工作人員的工作內容。具體體現在于在原有的信 息管理系統中添加短信功能、支付功能、獲取城市空氣質量功能、用戶行為統計 功能和數據開放平臺功能。并且,將由以上添加的功能所產生的信息進行規范 化管理,提升企業管理者的工作效率。通過此系統,公司可以在微觀上優化個 體服務,在宏觀上可以收集大量真實數據,為技術團隊更有針對性地優化和開 發產品提供數據支撐,也提高了用戶端數據的利用率。并且通過搭建開放平臺 為授權平臺方提供數據接口,為公司加入其他大型企業生態鏈提供必須的技術 支持,使用戶可以在其他第三方智能家居平臺內使用本公司的產品,增加產品 的銷售渠道,拓展產品市場。
系統的運行從公司角度,減少了工作人員的工作任務,提升了工作效率,提 高了企業的信息化程度;從用戶的角度,提升了使用體驗;綜合提高了產品的市 場競爭力。
1.3 國內外現狀
智能家居的初始形態最先出現在美國。芝加哥世界博覽會上展示的阿爾法 機器人,實際上是第一個應用智能家居這一概念的。它雖然不能像時下的機器 人一樣靈活移動,但是已經可以正確回答人們的問題,這在當時無疑已經是極 為智能的了。因此從某種程度上來說,阿爾法機器人便是一個智能家居產業出 現的標志。到目前為止,美國已經對智能家居產品研究了近30年,雖然美國的 智能住宅區占地面積已經達到了3359畝,有約8000小別墅,與此同時在世界 的其他國家和地區,智能家居悄然間也慢慢成為市場主流。但是有研究者表明 國際智能家居市場仍處于早期階段 [5]。
同樣,國內察覺到這一產業后也開始漸漸將其弓入市場。但是雖然很多大 型企業和科研院所都一直在進行宣傳,但是因為技術和市場環境等等因素,始 終在國內沒有激起太大的研究進展[6]。直到2014年,谷歌收購Nest為國內市 場在這一行業掀起高潮。一時間,包括家電企業和互聯網公司, 都開始謀劃進入 智能家居行業。不同行業間的企業合作也不免成為了一個共謀發展的契機, 開放 生態也使得市場得以良心運作。智能家居漸漸成為媒體報道的常規方向, 也成為 大眾耳熟能詳的詞匯, 在用戶購買商品時自然會成為其考慮的選項之一。
近幾年,我國已經出現了很多自有品牌在做智能家居的解決方案。僅僅在 2018年一年,華為、百度、阿里巴巴紛紛不約而同成立了智能家居的相關部門 小米生態鏈也發布了獨立品牌米家。從這些企業行為中就可以明顯看出,我國 智能家居的市場還在逐漸擴大,自主研發的勢頭蒸蒸日上。而隨著企業生態鏈 的擴大,也就說明企業所掌握越來越多的用戶信息[7],這些信息既包括用戶注 冊所需要的姓名、手機號等基本信息,也包括用戶操控機器等等的行為信息。大 量用戶信息在用戶無感知情況下被企業獲取,進行分析和研究,以此作為優化 產品的研究數據。相比于傳統手工收集數據的方式,這種方式雖然對于用戶來 說信息安全性降低,但數據真實且海量,更利于進行數據挖掘等研究 [8]。
1.4本文主要工作
本文的主要工作是基于一款新風設備產品,從產品本身到企業銷售,在原有 的信息管理系統基礎上構建新的設備信息管理子系統,對于此系統進行需求分 析、軟件設計、代碼開發和部署運行。前端基于 HTML、CSS、JS 語言和 React Redux 框架。后端使用 Java 語言,基于 Spring Boot 和 Spring Cloud 實現微服務 架構。
系統包含了 Web 端和微信端的多端應用,為了提高后端接口復用率和開發 效率,對于前后端平臺同時開發并分別部署。而后端的模塊劃分中,新增的主要 功能模塊包括短信模塊、支付模塊、空氣質量模塊、用戶行為統計模塊和數據開 放平臺模塊。本文利用微服務的特性,將每個模塊作為一個獨立的微服務進行 開發,降低相比使用單體結構時的模塊間的耦合性 [9]。同時每個模塊也可以有 獨立的數據結構,本文也會對根據每個模塊不同的數據結構而設計的數據庫圖 表以表格的形式進行展示。
本文的主要工作包括:
1.根據系統需求和技術特點選擇主要開發的技術。通過研究和對比,本文在 使用微服務框架的基礎上,選擇使用Java語言進行后端開發,使用Ajax 進行前后端的交互,接口設計參照 Restful 規范;
2.分別針對每個模塊不同的業務場景分析系統不同用戶所產生的需求,給出 用例圖并進行解釋。
3.根據需求對于不同模塊設計主要的數據接口和數據模型,并給出 ER 圖和 由此產生的數據庫圖表結構。
4.進行實際的代碼開發,并根據需求分別對每個模塊進行功能測試和性能測 試。
5.將本地開發好的代碼上傳至服務器進行部署和運行。
1.5 本文的組織結構
本文的組織結構如下:
第一章 弓言部分主要介紹了本文的研究背景和意義, 國內外的研究現狀, 以及本文的主要工作和組織結構。
第二章 對該信息管理子系統所用到的技術進行簡述,包括所用到的后端 框架、數據庫、消息中間件等等,并介紹選擇這些框架和技術的原因。
第三章 概述了系統的總體需求以及模塊如何劃分,再分別對每個模塊針 對不同的業務場景分析不同用戶角色的需求,根據需求給出每個模塊的數據結
構和概要設計。
第四章 分模塊依次對每個微服務進行開發和部署,并給出時序圖和核心 代碼邏輯,并對具體如何實現功能進行解釋。
第五章 搭建測試環境,對系統分模塊進行功能測試和性能測試,并給出 測試用例圖和測試流程,最后給出測試結果和分析。
第六章 方向。 對本文所做的工作做出總結,并提出本系統可繼續開發和優化的
第二章 相關技術概述
新風設備信息管理子系統的后端開發主要基于Spring Boot和Spring Cloud 實現微服務架構,搭建微服務集群。使用MyBatis作為Spring持久層與數據庫 的中間件簡化代碼開發。在數據庫的選擇上,在使用了主流數據庫 MySQL 的基 礎上使用了 Redis用于提高熱數據的查詢速度。為了加快對大尺寸的源數據的寫 入和讀取速度,系統將機器和手機端發來的數據包存儲在了 MongoDB中。本文 將對上述的相關技術進行研討。
2.1微服務
微服務這個概念在2014年剛剛被提出。微,指的是體積小,指的是對于整 個服務,從設計到開發再到測試和運維,只需要一個 5到6人的小型團隊。而 服務區別系統的是,服務是一個獨立的功能單元,是組成系統的一個獨立的部 分,是用戶所能感知的一個最小功能集。而系統需要為每個微服務提供基礎架 構,讓微服務可以在獨立部署運行和升級。而服務與服務之間,需要是松耦合 的,不會彼此強依賴而降低性能,而在整體上卻是一個統一的整體 [10]。而這種 統一表現在除了業務之外的在開發方法上的統一,包括使用相同的日志和設計 方法等等。這樣,既可以在個體上進行獨立的敏捷開發和部署,又可以在整體上 具有一致性。
一般情況下,會按業務功能對進行微服務的劃分,每個微服務只完成一部 分特定的功能,例如支付服務只負責用戶進行賬單支付,而短信服務只負責收 發短信、對短信記錄進行管理。而微服務之間通過REST API或者RPC這樣的 輕量級通信機制來進行通信[11]。
并且,在整個架構的開發過程中,微服務架構都具有很強的親和性。首先 在開發過程中,開發每個微服務的人員可以把這個微服務當成一個獨立的項目 去做。可以隨意選擇開發語言、技術工具,并可以構建獨立的數據結構。比如用 戶管理微服務和設備管理微服務的后端開發都是用Java語言編寫,而外部空氣 質量數據模塊需要使用Python語言編寫爬蟲腳本可以提升10速度,而Web端 HTML5頁面可以用NodeJS進行開發。并且如果想要更換技術,更換成本相比 單體架構也會少很多。每個微服務不會受到技術棧的限制,只需要關心服務內 部的代碼邏輯, 在業務層面不必關心業務間的相互 [12],極大地提升了開發人員 的舒適度,代碼量和邏輯復雜度都會降低,降低了開發和維護的工作量。并且 在啟動時只需要部署并啟動當前模塊即可,而不需要將整個系統重新發布再啟 動 [13]。在服務運行時,系統也會每個微服務提供獨立的進程,由進程共同支撐 整個系統的運行。在想要擴展某個模塊時,也不要考慮對于其他模塊的影響,對 于我們微服務來講便可以按需伸縮, 單個模塊通過哪些方式來提升性能并不必考 慮其它模塊的情況, 為開發帶來很多可擴展性[14]。
但是,對于單體架構,需要維護一整個項目,而一個項目包含多個模塊。因 此,如果有一個模塊出現問題,則整個項目都將執行異常 [15]。并且運維人員 無法逐步跟蹤調試器去發現是哪個模塊出錯導致了問題,這對運維人員提出了 很高的要求,并且維護成本也會大大增加。而微服務架構要求采用分布式技術 微服務架構的復雜性也由于分布式技術本身的復雜性而增加。例如,用戶微服 務由訂單微服務和電影微服務調用。如果用戶微服務的接口發生重大變化,則 所有依賴的微服務都需要相應地進行調整。由于所有被依賴的微服務可能很多 那么在這種情況下協調接口的成本就會大大增加。并且在單體結構中,如果多 個模塊都使用了某個特定業務,會將該部分代碼抽象為工具類,而微服務架構 中,如果多個微服務的工具類是另一個微服務,那么就必須為每個微服務構建 這樣的工具類,增加了代碼的重復率。
因此,基于上述微服務相比單體結構優缺點的衡量,本系統采用微服務架 構進行開發。
2.2Spring
2.2.1Spring 框架
在傳統的 JavaEE 應用程序開發過程中,開發者需要關注底層的實現,比如 狀態管理、連接池、事務處理等,為了使應用程序編寫起來更加容易,開發人員 能把更多的精力用于業務邏輯的處理,EJB應運而生。EJB是分布式JavaWeb開 發框架,雖然簡化了很多底層功能的實現,但由于功能的完整性,導致應用的復 雜性更高了,整體比較厚重,而且學習成本相對而言也更大,甚至會有很多潛在 的問題。同時受應用功能的復雜性、功能實現的必要性的影響,代碼的耦合性和 復雜性也非常大,冗余或者重復的代碼會比較多,運維和再次開發難度比較大。
在Spring框架中可以使用基本的JavaBean來完成,使開發人員無需再使用 EJB那種冗余并且低效的開發模式[16]。它有效的降低了代碼的耦合性,使代碼 編寫能夠非常的友好和簡潔,而且給代碼的升級維護和再次擴展提供的極大地 便利。已然成為當下最流行的JavaEE開發框架。
作為一個輕量級開發框架,完整Spring程序可以在甚至可以以不到1M的 jar包發布,處理開銷也足以忽略不計。如圖2.1為Spring IoC的基本實現原理。 通過IoC(Inversion of Control)控制反轉,開發者無需在頻繁的新建對象,只需 要通過配置項,把類依托給Spring容器控制,每次使用的時候只需要將類對象 注入進來,不需要關注對象的狀態,更不需要頻繁的創建對象[17]。通過AOP (Aspect Oriented Programming)面向切面,開發者可以降低重復代碼,更多的關 注業務邏輯的實現,降低功能代碼的耦合。應用于異常處理時,只需要通過切面 構造一個完整的統一異常處理,而無需針對某一個方法某一個業務邏輯的異常 情況;應用于日志時,無需要方法體里面重復的塞入日志打印邏輯,只需要通過 切面構造一個統一日志處理方法即可,當然AOP的用處不僅僅是這,它使得開 發者的代碼更加的靈活多變,易于維護和擴展。
圖 2.1: Spring IoC 實現原理
2.2.2Spring Boot
2013年】Pivotal團隊基于Spring Framework推出SpringBoot這個全新框架, 主要用來快速方便的開發單個個體微服務[18]。Spring Boot主要有以下幾個特 點:首次,由于很多配置已經針對開發獨立微服務配置完成,對于開發人員的搭 建十分便捷;其次,Spring Boot內置了包括Tomcat、Underflow等多種服務器, 所以并不需要再打包成War包,而是直接打包成Jar包,在服務器內使用命令 行運行即可;第三,SpringBoot具有很多生產級別的功能幫助開發,例如對于 Bean的生存周期的管理等等;最后,Spring Boot可以使用注解而不是XML文 件對 Bean 進行配置,并且可以設定不同的條件對注解進行加載 [19]。
因此,用戶在使用SpringBoot框架時,無需再進行繁瑣的配置,減少了開 發人員的配置工作。同時,SpringBoot又可用于多層架構體系的模型業務層,實 現模塊之間的“高內聚、低耦合”,從而成為業界流行的開發框架[20]。
2.2.3 Spring Cloud
在基于Spring開發的應用框架中,服務與服務之間的處理需要Spring Cloud 來進行協調。 Spring Cloud 在各個維度為每個獨立的微服務提供了很多集成服 務,用來治理并構建分布式框架,這些集成服務包括服務發現、分布式會話等 等。相比更早被廣泛使用Dubbo而言,也是因為Spring Cloud提供了眾多的集 成服務,使開發人員在開發云服務等框架時無需修改底層代碼調用其他產品的 服務,而直接使用Spring Cloud本身提供的組件,既減少了代碼量也使結構十分 清晰。Spring Cloud中的組件之間的調用關系如圖2.2所示。下面對其中的幾個 主要組件進行介紹。
首先, Eureka 是對 Netflix Eureka 的封裝,主要用于注冊和發現服務,由服 務端和客戶端兩部分組成。服務端提供服務注冊功能,各個微服務啟動后,部署 在服務節點上的客戶端如果首次加入系統,則會先在服務端進行注冊自己的 IP 地址和端口號等信息,然后與服務端保持心跳連接。這樣如果服務端在長時間 內沒有收到某一個微服務的心跳包,則會認為該服務出現問題。而如果 Eureka Servicer 出現問題導致不可用, Spring Cloud 并不會像 Zookeeper 一樣采用選舉 的方式重新選擇master節點導致集群長時間不可用,而是會自動切換至其他節 點提供注冊和發現的服務,保證了系統可用性和分區容錯性。
Ribbon的主要作用是用來負載均衡。首先Ribbon會從注冊中心獲取到所有 服務的地址信息,然后當服務被調用時,Ribbon會幫助系統決定選擇哪個服務 建立連接,默認會使用輪詢的方法進行選擇。而Feign集成了 Ribbon,目的是希 望開發人員可以更便捷地編寫Http客戶端。只要在代碼中加入FeignClient的注 解,指明希望調用的服務名稱,注解底層就會幫助開發人員實現調用的整個過 程,而無需手動用 IP 地址與其他服務建立連接,對于開發來說十分便捷,代碼 也簡潔明了 [21]。當Feign需要發起請求時,Ribbon如果未被指定會默認使用輪 詢算法去找到合適的ip和端口號通知Feign, Feign再去構造請求。
Hystrix熔斷器主要有3個功能:隔離、熔斷和降級。Hystrix為每一個服務 提供一個小線程池,每個服務最多只可以把自己線程池里的線程用完,而當某 個微服務不可用時,Hystrix中會有一個閾值,如果調用報錯次數超過這個閾值 會直接熔斷該節點微服務的調用,不需要再去走網絡請求,快速返回“錯誤”的 相應信息。然后這些失敗請求等到該服務恢復會根據記錄重新啟動。Hystrix通 過這些功能保證了服務的穩定性[22]。
除了以上介紹的組件之外,SpringCloud的開源社區支持也非常強大[23],為 微服務的分布式框架從各個維度提供了一系列的解決方案,從整體上和細節上 滿足了微服務框架的開發,方便開發人員便捷高效地進行開發。
2.3MyBatis
JDBC、 Hibernate 和 MyBatis 是當前主流持久層操作方式, Hibernate 和 My- batis都是基于JDBC封裝的持久性框架。相對于JDBC而言,Hibernate和Mybatis 不需要處理底層事務、處理數據類型;無需關注是否正確釋放了資源;減少了 代碼和SQL語句的耦合。相對于Hibernate來說,MyBatis作為半自動化的持久 性框架[24],可以定制化復雜類型的SQL,靈活使用數據庫本身帶來的功能多 樣性,對于SQL導致的性能問題更是可以進行優化。同時,Mybatis還有一些 優秀的增強工具,如Mybatis-plus,對于簡單的數據庫操作來說,也可以做到如 Hibernate 這樣快速便捷。
如圖2.3展示了 MyBatis的整體架構圖[25]。如圖所示,基礎層主要包括連 接池、日志、反射、事務、緩存這五個部分。下面將會對這五個基本功能一一進 行介紹。
首先是MyBatis的連接池,也可以稱為數據源,為核心層提供連接數據的服 務。而稱為連接池,是因為它的實現類似線程池,用來存儲已經創建的連接。這 樣當需要與數據庫建立連接的時候,可以提高效應速度,同時也可以減少創建 連接的系統消耗。
核心層
圖23從功能流程層次描述MyBatis的整體架構圖
在日志功能上,Mybatis并沒有自己的日志實現,而是采用了設計模式中 常見的適配器模式,由第三方組件去實現它的日志模塊。由于適配器模式的特 性,Mybatis可以使用最主流的日志實現,包括日志門面Slf4j,日志框架Log4j、 Log4j2或者Logback。通過第三方優秀日志框架的功能特性,可通過日志配置靈 活打印SQL執行語句、SQL的執行情況,快速定位問題。尤其是在和Springboot 框架的結合上,幾行配置就可以實現,更是方便快捷。
在事務方面,Mybatis提供了兩種管理事務的方式。一類通是通過底層JDBC 本身的事務管理,即通過Connection對象完成事務的操作,需要設置AutoCommit 為Off。一種是通過外層Managed管理事務,這種管理方式是通過容器來控 制,最常見的是Tomcat或者Spring。可通過Transaction接口中的兩個實現類 JDBCTransaction 和 ManagedTransaction 來確定使用哪一種方式。
Mybatis有強大的緩存功能。有基于會話的一級緩存,這是Mybatis默認開 啟的緩存方式。另一種是基于SQL的二級緩存,即針對于一條SQL查詢的結果 緩存數據,需要配置開啟。開啟了二級緩存,Mybatis的效率無疑會更高,但是 對于分布式來說架構來說,需要借助第三方緩存框架。
因此,本系統為了降低程序代碼和SQL語句的耦合性[26],并提高代碼可 讀性,節省開發成本,選擇MyBatis作為與數據庫交互的中間件。
第二章相關技術概述
2.4Redis
Redis是時下在開發中被廣泛使用的非關系型緩存數據庫[27],同時也支持 多種數據類型 [28]。由于是用內存進行數據的存儲,而且也可以使用虛擬內存, 其絕大部分請求都是純粹的內存操作, 訪問內存的速度要遠高于訪問硬盤的速 度可以達到超過每秒100k的讀寫頻率,與此同時其類似HashMap的存儲方式 大大提升了對Key的檢索速度,使其對任意Key指的檢索和操作的時間復雜度 都能收斂到 O(1)。
Redis相比Memecache來說,有一個重要的區別在于Redis有AOF (Append- Only-File) 和RDB (Redis-DataBase)兩種方式,可以實現數據的持久化[29]。 追加持久化,是記錄對數據庫操作的所有寫指令,等到Redis重啟時將所記錄的 所有指令重新運行,就可以達到持久化的效果。但這種方式通常文件較大,恢 復時間較長。Redis默認情況下不使用這種方式,可以通過修改配置文件來開啟。 而RDB (Redis-DataBase)快照持久化,是將某個時間的數據庫狀態存儲在RDB 文件中,在服務重啟時會直接加載文件中的數據。這種方式相比AOF速度更快, AOF會實現更好的數據完整性。Redis會默認開啟RDB模式。
Redis 使用單線程的方式處理數據操作。由于數據全部在內存里,采用單線 程操作的效率是最高的,避免了 CPU 模擬出多個線程帶來的不必要的上下文切 換等方式的CPU消耗。但由于Redis本身的讀寫效率,單線程處理對Redis的 性能并沒有太大影響。
Redis 支持主從復制 [30],使數據庫獲得更大的存儲容量并承受高并發訪問 量,將一臺Redis服務器(Master)的數據分別存儲到其他多個網絡節點(Slave) 上,實現對數據的冗余備份,從而保證數據和服務的高可用 [31]。
在本系統中,Redis作為數據庫的緩存使用,實現上述特性的同時,實現上 述特性的同時,又提高了系統響應速度。
2.5MongoDB
在實際的業務場景當中,經常會面對海量數據查詢的情況,而這時MySQL 的查詢速度會大幅減低,不利于業務處理,因此非關系型數據庫MongoDB應運 而生。對比于傳統的關系型數據庫,其最主要的不同點即在于數據的存儲形式 非關系型數據庫不再以表格的形式存儲數據,并且也不再使用SQL語言進行查 詢。而正是由于沒有了復雜的關系作捆綁,非關系型數據庫相比關系型在使用 上會更加靈活,具有了高可拓展性,并且由于key-value的結構,極大的加快了 查詢速度。
MongoDB 一名的來源就是Humongous —詞,可以看出MongoDB對存儲大 數據更存在優勢[32]。MongoDB的主要特性可以概括為3點:文檔模型、高可 用和水平擴展[33]。上文即對文檔模型作了介紹,并且圖 2.4也展示出了該模 型。而高可用,指的是MongoDB支持集群和多數據中心,來實現自動復制和 故障恢復,可以支持滾動維護最多 50 個成員無需關機。而水平擴展,則指的是 MongoDB可以支持增加服務器數量來對系統進行擴容。
由以上的特性,可以推出,MongoDB比較適合在以下的場景中使用:由于 MongoDB 對實時修改數據有更快的相應速度,可以用來存儲網站數據;由于高 性能,MongoDB同樣也可以類似Redis用來作為持久化緩存層來避免下層數據 源過載;基于其高可用和水平擴展的特性,對于由數十或數百臺服務器組成的 數據庫這種高伸縮性的場景,MongoDB也可以進行更好的處理。
而在本文中,由于系統會與近萬臺設備保存TCP長連接,每臺設備每30秒 就會向系統發送數據包,這樣導致數據會進行快速大量堆積。對于這種大尺寸 且低價值的數據存儲,并且基于上述對MongoDB特性的分析,因此本文選擇 MongoDB 作為存儲設備日志文件的數據庫。
Document (文檔)
{Name: Lucy, Age: 24}
圖24關系型數據庫與MongoDB數據存儲形式對比圖
2.6 本章小結
第二章主要介紹了本系統所選擇的幾項相關框架和技術。首先,系統基于 Spring搭建了微服務框架,簡要介紹了微服務的概念和Spring的相關技術。其次, 概述了 Java與數據庫交互的持久層框架MyBatis,以及用于加快查詢速度的緩 存數據庫Redis,最后介紹了基于分布式文件存儲的非關系型數據庫MongoDB, 以及本文選擇這些技術的原因。
第三章 新風設備信息管理子系統的需求與設計
本章節首先介紹了系統的總體需求,給出了系統的總體用例圖,對于每個 功能模塊進行更細致的需求分析。接著根據需求分析,本章給出了每一個模塊 的內部設計以及重要的數據結構,并通過ER圖、類圖等圖表進行輔助展示。
3.1 系統需求分析
3.1.1 系統總體需求分析
在公司原有的信息管理系統中,首先用戶在天貓、京東等電商平臺選擇公 司的產品,下單購買,該平臺將訂單推送給系統進行管理。用戶在安裝好產品 后,可以通過微信公眾號綁定設備在公眾號內控制設備,例如開關機器、調節風 量等等,同時也可以在該頁面查看由設備檢測到的室內空氣質量。在使用的過 程中,如果系統需要通知用戶信息,可以采用微信公眾號推送的方式或者客服 手動發送短信或打電話。基于商業角度的考慮,為了拓展產品的銷售渠道,提高 產品的核心競爭力,本文需要在原有的系統之上構建信息管理子系統,針對上 述的業務場景在系統中添加新的功能,并對這些功能所產生的信息進行管理。
圖 3.1: 新風設備信息管理子系統用例圖
對于用戶在購買設備、使用設備、享受設備所帶來的售后服務的這個過程 來說,首先,為了增加產品銷售的渠道,在線上銷售的方式中,除了借助第三方 電商平臺,系統需要搭建更多的自有購物商城,并提供可以選擇多種第三方平 臺進行支付的能力,例如微信支付、支付寶支付等等。其次,為了使用戶可以更 及時的接收到通知信息,并提高管理員的工作效率,系統需要具有發送短信的 功能,其中包括系統自動發送響應式短信和管理員手動編輯短信內容發送短信 第三,為了向用戶更好的展示出設備凈化室內空氣的能力,系統需要獲取到設 備所在位置的室外空氣指數,并與室內空氣質量做對比。第四,用戶在每天操 作設備的過程中產生了大量的行為數據,系統需要對這些數據進行整合和統計 以提供給研發和銷售人員作為優化產品、分析用戶需求以及提供個性化服務方 案的數據支撐。最后,為了擴大生態挖掘更多潛在用戶,系統需要搭建一個數據 開放平臺,使用戶可以在其他第三方平臺中使用系統中的設備,拉取更多用戶 擴大產品市場。在這個過程當中,每個環節圍繞設備所產生的數據和信息,系統 都需要對其生命周期進行規劃和管理。
因此,該信息管理子系統中用戶主要分為三類用戶,分別為普通用戶、管 理員和授權方平臺。首先,用戶除了可以通過第三方電商平臺購買商品外,還 可以在系統搭建的購物平臺通過第三方支付渠道上支付訂單完成對商品的購買 然后在使用設備時通過手機端操控設備的同時,在微信公眾號內不僅可以監控 到室內的空氣質量,還可以監測到室外的空氣質量來進行對比。第三方平臺可 以通過在系統中注冊和被授權,在訂閱某臺設備之后,對目標設備進行操控,或 查詢設備的運行狀態等等。而管理員需要具有對上述行為產生的信息進行管理 的權限和能力,并且可以使用系統給指定用戶發送短信,并對所有短信記錄進 行管理。同時,還可以查詢到用戶的行為統計數據,進行針對性銷售或服務。系 統整體需求的用例圖如圖 3.1 所示。
因此,本文所構建的新風設備信息子系統所需要的功能主要包括發送短信 功能、支付功能、獲取城市空氣質量數據功能、用戶行為數據統計功能和數據開 放功能,而所管理的信息主要就是所有短信記錄、用戶交易信息、城市空氣質量 數據、用戶行為數據和第三方平臺的注冊和訂閱設備等信息。
所以,本文將系統分為以下 5 個模塊分別實現上述的功能并對相應產生的 信息進行管理,分別為短信模塊、支付模塊、空氣質量數據模塊、用戶行為統計 模塊和數據開放平臺模塊。下面將分別對這5個模塊進行詳細的需求分析。
3.1.2 短信功能需求分析
本文的短信功能主要有兩個方面,分別是發送短信和短信管理。首先,發 送短信有分為兩個場景,一是基于市場營銷或其他目的,管理員通過系統手動 編輯短信,單一或批量給指定用戶發送短信;二是由條件觸發系統可以自動響 應給用戶發送短信,例如用戶使用手機號登錄系統,系統需要發送包含驗證碼 的短信,安裝工人在給用戶安裝完機器后,系統需要向用戶發送請求提交滿意 度反饋的短信等等。并且系統也需要接收到用戶的回復短信,例如系統會向用 戶發送公司最新產品的推廣短信,用戶在不想要接收此類短信的情況下,可以 選擇回復短信進行取消訂閱通知,提高用戶信息接收的自由度和舒適感。而短 信管理功能也包含兩個方面,管理員可以通過系統查詢到系統的外發短信,作 為歷史記錄的留存;同時也需要查詢用戶的回復短信,以便于根據用戶的反饋 進行相應的處理。圖 3.2 展示了該模塊的用例圖。如圖所示和上述分析,短信模 塊的調用者可以是管理員也可以是用戶。管理員需要單發短信、批量發送短信 查詢所有外發短信記錄和系統接收到的用戶回復的短信記錄。而用戶則可以在 需要時向系統回復短信發送需求。
管理員批量發送短信的具體用例描述表如表 3.1所示。管理員在登錄系統 后,需要上傳發送用戶群體的手機號列表文件,確認文件添加成功和短信內容 無誤后,觸發系統開始批量發送短信。單發短信的用例中,管理員不需要上傳手 機號文件而是采用直接輸入的方式,其他步驟與批量發送類似。
除此之外,系統除了具備發送短信的能力,還應具備查詢已發送的短信和 已收到的回復短信的能力。管理員在登錄系統后,可以根據不同的篩選條件進 行查詢,并且系統支持對于手機號的模糊查找。關于管理員在系統上查詢已發
表 3.1: 批量發送短信用例描述表
ID UC1
名稱 批量發送短信
參與者 管理員
描述 管理員給指定用戶手機號批量發送短信
優先級 高
前置條件 管理員登錄系統,并且具有發送短信的權限
后置條件 無
正常流程 1.管理員登錄系統,進入發送短信的頁面
2.管理員輸入短信正文
3.管理員導入用戶手機號列表文件
4.管理員確認添加手機號
5.管理員確認短信正文和手機號信息
6.系統批量發送短信
異常流程 3a.如果手機號文件導入失敗,系統提示客戶信息文件導入失敗
6a.管理員如果沒有發送短信的權限,那么系統提示權限錯誤
送的短信信息的具體用例描述如表3.2所示。從表中可以看出,正常流程分為3 步:首先是管理員登錄系統并進入查詢短信的頁面,包括外發短信的查詢頁面 和回復短信的查詢頁面;然后管理員可以選擇查詢的條件進行查詢,并且系統 需要支持根據手機號的模糊查詢;最后,系統返回符合條件的數據,并且按照時 間順序的倒序排序。
表 3.2: 短信查詢用例描述表
ID UC2
名稱 短信查詢功能
參與者 管理員
描述 管理員查詢需要的短信信息
優先級 高
前置條件 管理員已經登錄,并且具有查詢短信的權限
后置條件 無
正常流程 1.管理員登錄系統,進入查詢短信外發管理的頁面
2.管理員選擇查詢的條件并確認提交,支持手機號的模糊匹配
3.系統返回符合條件的數據,并且按照時間順序的倒序排序
異常流程 2a.管理員如果沒有查詢短信的權限,系統提示無操作權限
3a.不存在符合篩選條件的短信,系統提示沒有相關的短信信息
3.1.3 支付功能需求分析
支付模塊在功能上同樣可以分為兩個部分。首先,在搭建的自有購物平臺 上提供借助第三方支付平臺完成交易支付的能力。例如,在微信小程序端開發 的企業旗艦店,用戶在下單后系統需要提供可以幫助用戶完成微信支付的能力
完成微信小程序、系統、微信后臺的正常交互,完成支付流程。或者在其他Web 頁面搭建的官方購物平臺,系統也需要提供包括微信支付、支付寶支付等對應 的多種支付渠道,提高用戶支付的自由度。系統目前需要搭建微信小程序端的 購物平臺,提供在微信小程序端進行支付的能力。表 3.3 展示了相應的用例表。
表 3.3: 微信小程序支付用例描述表
ID UC3
名稱 微信小程序內支付訂單
參與者 用戶
描述 用戶可以在微信小程序內下單,購買商品
優先級 咼
前置條件 無
后置條件 無
正常流程 1.用戶進入微信小程序
2.選擇商品提交訂單,請求下單支付
3.小程序拉起微信支付,用戶選擇付款渠道,確認支付
4.用戶輸入密碼等完成支付
5.小程序端返回支付成功的信息
異常流程 3a.下單失敗,沒有彈岀微信支付,顯示下單失敗原因
5a.微信支付處理失敗,顯示支付失敗
其次,用戶在第三方支付平臺進行訂單支付時,系統需要首先根據用戶選 擇的商品信息、下單時間、用戶信息等生成交易訂單,發送給第三方支付平臺的 同時保存到數據庫中,以供管理員進行查詢和管理。因此,系統需要提供支付信 息管理的功能,一方面便于管理員進行訂單管理,另一方面便于作為處理交易 爭議時的數據證據。具體的用例描述表如表 3.4 所示。
表 3.4: 訂單管理用例描述表
ID UC4
名稱 訂單管理功能
參與者 管理人員
描述 管理員查詢訂單的詳細信息
優先級 高
前置條件 管理員已經登錄,并且具有查詢訂單的權限
后置條件 無
正常流程 1.管理員登錄系統,進入查詢訂單的頁面
2.管理員選擇查詢的條件并確認
3.系統返回符合條件的數據,按照時間順序的倒序排序
異常流程 2a.用戶無操作權限,系統提示權限錯誤
3a.不存在符合條件的賬單,系統提示無相關數據
3.1.4 空氣質量模塊需求分析
在原有的系統中,用戶可以通過微信公眾號綁定設備,在公眾號里查看設 備運行狀態和使用設備,并且檢測到設備所檢測到的實時室內空氣質量。而為 了讓用戶可以隨時觀察到新風設備給室內空氣帶來的凈化效果,系統也需要展 示出設備所在城市當前的室外空氣質量數據。這樣,通過室內外AQI的對比,可 以使用戶直觀感受到設備新風的效果,提升產品的競爭力。因此,本文的空氣 質量模塊所要具備的能力就是獲取到國內所有城市最新的空氣質量數據,包括 AQI、PM2.5、PM10、CO、主要污染物等指數,并進行整合,提供給前端。具體 的用例描述如表3.5所示。
表 3.5: 用戶查詢室外空氣用例描述表
ID UC5
名稱 查詢室外空氣質量指數
參與者 用戶
描述 用戶查詢當前設備所在城市的空氣質量指數
優先級 中
前置條件 用戶已經關注該企業微信公眾號,并且已綁定設備
后置條件 無
正常流程 1.用戶進入微信公眾號
2.用戶查看設備信息
3.系統返回當前設備所處的室內外空氣質量數據,展示給用戶
異常流程 2a. 用戶沒有綁定的設備,那么系統提示無綁定設備
2b. 如果設備處于離線狀態,系統提示設備已離線,需要重新接入
3a. 獲取設備所處的地址失敗,系統提示獲取當前室外空氣質量數據失敗
3b. 獲取所處城市的空氣數據失敗,系統提示獲取室外空氣質量數據失敗
表 3.6: 管理員查詢城市空氣質量用例描述表
ID UC6
名稱 查詢城市空氣質量數據
參與者 管理員
描述 用戶查詢全國城市的空氣質量數據
優先級 中
前置條件 管理員已經登錄系統,并具有權限
后置條件 無
正常流程 1.管理員登錄系統,并選擇空氣質量信息的頁面
2.管理員選擇查詢的城市和日期,發送請求
3.返回相應的空氣質量數據
異常流程 3a.管理員如果沒有查看空氣質量的權限,提示權限錯誤
3b.系統未查詢到該城市的空氣質量數據,提示未查詢到結果
同樣,管理員也具備查詢室外空氣質量數據的權限。管理員在登錄系統Web 端頁面后,可以根據城市和日期查詢到最新的室外空氣質量,默認返回所有城 市的最新數據。具體的用例描述表如表 3.6 所示。
3.1.5 用戶行為統計需求分析
在原有的系統中,用戶可以通過微信公眾號,向系統發送指令數據包,對應 的機器控制模塊再將指令發送給用戶綁定的機器,實現用戶遠端控制設備的功 能。而由于這些原始的用戶行為數據價值較低尺寸較大,原系統將這些數據存 儲在了 MongoDB中。而管理員或者企業其他管理者并不能直接對這些數據進行 管理和查詢。因此,在新的子系統中,需要開發一個針對用戶行為數據的統計功 能,對用戶的數據根據業務基于不同維度進行整合,然后提供給系統管理員根 據不同篩選條件進行查詢的能力。同時,企業的研發人員可以根據這一能力進 行針對性的研發,更深入地了解用戶的真實需求和行為習慣,為其研發方向提 供數據支撐。并且,企業的銷售人員也可以通過這一能力,為用戶提供個性化 定制化服務。例如,公司推岀新產品,銷售人員可以通過用戶行為統計推斷岀大 概率會購買該產品的人群,進行推銷。
因此,這一功能的需求分析如表 3.7 所示。管理員首先登錄系統后,找到用 戶行為統計模塊,然后輸入用戶名或日期等篩選條件,查詢岀整合后的用戶行 為信息。
表 3.7: 管理員查詢用戶行為信息用例描述表
ID UC5
名稱 查詢用戶行為
參與者 管理員
描述 管理員查詢用戶的行為數據
優先級 中
前置條件 管理員已經登錄系統,并且具有管理該功能的權限
后置條件 無
正常流程 1.管理員登錄系統,找到用戶行為統計站點
2.輸入用戶名、日期等篩選條件
3.系統返回該用戶在該日期的所有行為信息
異常流程 3a.管理員如果沒有查詢用戶行為的權限,那么系統提示權限錯誤
3b.如果不存在符合篩選條件的信息,系統提示沒有相關信息
3.1.6 數據開放平臺需求分析
在當下的智能家居市場,已有很多大型企業開始營造自己的生態圈,而如 果把該產品加入到其他生態鏈中,使用戶可以在其他的第三方平臺使用到本公 司的產品,可以挖掘到更多潛在用戶,擴大產品市場。因此,系統需要搭建一個 數據開放平臺,向第三方平臺提供該新風設備的數據開放接口,以供第三方平
臺集成。系統中包含以下幾種成員:
圖 3.3: 數據開放平臺模塊用例圖
1.管理員:第三方平臺首先需要向管理員提交企業資料,管理員進行審核, 待審核通過后,管理員向系統注冊該企業的信息,系統向管理員返回一個 隨機生成的 appId 作為該企業的唯一身份標識,然后管理員將該 appId 返 回給該企業。
2.系統SDK:該角色為平臺集成于第三方應用中的一個SDK,第三方所有 對設備的相關操作經由該SDK來完成,包括開關機、調節模式、調整風量 等等。
3.第三方平臺:第三方平臺向管理員申請注冊并獲取到appId后,即可與SDK 進行交互。
以上三種成員分別組成兩個后端服務子系統:部署在云端的數據開放平臺 子系統和集成于第三方應用的SDK子系統各司其職,構成完整的數據開放平臺。
數據開放平臺子系統支持SDK和管理員完成相應指令的能力,管理員通過 注冊第三方信息來獲取對應的appId, SDK開放式集成應用提供訂閱設備、獲取 設備列表、移除設備、開/關設備、調節設備運行風量的API等功能。如圖3.3所 示,展示了該子系統的用例圖。
表 3.8: 訂閱設備用例描述表
ID UC7
名稱 訂閱設備
參與者 用戶
描述 SDK根據用戶提供的appId和設備二維碼進行關聯和記錄
優先級 高
前置條件 用戶提供的appId和qrcode已驗證合法,并且不存在訂閱關系
后置條件 無
正常流程 1.SDK請求訂閱設備
2.系統完成appId與設備的綁定
異常流程 2a. 若 appId 非法,則提示請提供有效的 appId
2b. 若 qrcode 不存在,則提示請提供有效的 qrcode
2c. 若 appId 與 qrcode 的訂閱關系已存在,則返回成功,但并不在此存儲 綁定記錄,并提示已訂閱該設備
在完成注冊之后,為實現對于設備的數據查詢和控制,第三方(下文稱為用 戶)首先需要訂閱所需設備,用戶需提供appId和設備編號(qrcode)來完成訂 閱。具體的用例描述如表 3.8 所示。
用戶完成訂閱設備后,可以根據當前的appId批量查看已訂閱的設備列表進 行驗證,來核實是否有遺漏或多余設備。具體用例描述如表 3.9 所示。
表 3.9: 獲取設備列表用例描述表
ID UC8
名稱 獲取訂閱設備列表
參與者 管理員或用戶
描述 SDK根據用戶提供的appId獲取已訂閱的設備列表
優先級 高
前置條件 用戶提供的appId已經驗證有效
后置條件 無
正常流程 1.SDK請求訂閱設備列表
2.系統返回所有當前該用戶已綁定的設備列表信息
異常流程 2a.若appId不存在,貝U提示請提供有效的appId
2b.若該appId暫無綁定記錄,貝U提示用戶當前訂閱列表為空
批量管理多臺設備時,會需要獲取其中某一臺設備的運行狀態方便獨立式 管理,用戶根據appId和設備二維碼即可獲取運行狀態。具體用例描述如表3.10 所示。
批量管理的設備會分布在一個或幾個城市,此時如果想觀察某臺新風設備 的凈化情況和當前城市的空氣質量對比,需要獲取此設備所處的城市的空氣數 據,此時用戶根據appId和當前設備二維碼即可獲取當前城市空氣數據。具體用 例描述如表 3.11 所示。
表 3.10: 獲取設備運行狀態用例描述表
ID UC9
名稱 獲取設備運行狀態
參與者 用戶
描述 SDK根據用戶提供的appId和設備二維碼獲取設備運行狀態
優先級 高
前置條件 管理員已經登錄,并且具有發送短信的權限
后置條件 無
正常流程 1.SDK 請求獲取設備運行狀態
2.系統返回該設備的運行狀態信息。該信息以JSON格式返回:{qrcode : xxx, online : true, status : { pm2_5 : xxx, co2 : xxx, power : xxx, temperature : xxx, humidity : xxx}}{qrcode : xxx, online : f ase, status : {}}
異常流程 2a. 若 appId 不存在,則提示請提供有效的 appId
2b.若該appId與該二維碼之間不存在訂閱關系,則提示用于當前無權限 查看該二維碼所對應設備的運行狀態
2c. 若設備處于未聯網狀態,則系統提示設備當前未聯網,無法獲取數據
提供移除設備的能力,當用戶因某種原因想移除某臺設備取消訂閱關系時 提供appId及設備二維碼即可完成移除。具體用例描述如表3.12所示。
3.2 系統總體架構設計
新風設備信息管理子系統的系統架構總體圖如圖 3.4 所示。系統采用前后端 分離的架構設計,前端和后端同時開發,分別部署。從圖中可以看出,該系統的 展示層主要有微信小程序、微信公眾號和H5頁面三個部分。前端主要通過Ajax 對后端接口進行異步調用,接口設計規范符合RESTful協議。
當前端請求通過網關到達服務集群時,Spring Cloud的組件Zuul會首先進 行過濾和路由,通過各個微服務在Eureka注冊中心所注冊的IP和端口號等信 息,請求被分配到相應的微服務。在本信息管理子系統中,主要包含了短信服 務、支付服務、空氣質量服務、用戶行為分析服務和數據開放平臺服務五個部 分。而當這些服務需要調用其他服務時,使用第二章所提到的Feign組件進行通 信。由于Feign中集成了 Ribbon,還可以起到負載均衡的作用。同時對于短信服 務、空氣質量服務和數據開放平臺服務都會與第三方平臺進行交互,本文使用 Http 請求的方式將請求通過網關發到外網。
請求到達對應微服務后,會由控制層進行對業務的處理、邏輯層進行類之 間的相互調用、持久層進行對數據庫的操作。在服務集群與MySQL數據庫的交 互中,使用了 MyBatis作為中間件來簡化代碼動態生成SQL語句,進行對數據 庫的增刪改查等操作。為了便于管理,并將每個微服務所配置的數據庫均部署 在了同一臺服務器上。同時,為了提高系統查詢速度與相應速度,將一部分熱數
表3.11: 獲取城市空氣數據用例描述表
ID UC10
名稱 獲取設備所處城市空氣數據
參與者 SDK
描述 SDK根據用戶提供的appId和設備二維碼獲取當前城市空氣數據
優先級 高
前置條件 用戶提供的appId已經驗證有效
后置條件 無
正常流程 1.SDK請求獲取設備當前城市的空氣數據
2.系統返回城市的空氣數據。該信息以JSON格式返回:{aqi : xxx, pm2 5 : xxx}
異常流程 2a. 若 appId 不存在,貝提示請提供有效的 appId
2b.若該appId與該二維碼之間不存在訂閱關系,則提示用于當前無權限 查看該二維碼所對應城市的空氣數據
2c. 若設備未設置所處的城市,貝提示無法獲取設備所處的城市
表 3.12: 移除設備用例描述表
ID UC13
名稱 移除設備
參與者 SDK
描述 SDK根據用戶提供的appId和設備二維碼移除設備
優先級 高
前置條件 用戶提供的appId已經驗證有效
后置條件 無
正常流程 1.SDK請求移除設備
2.系統刪除設備在該appId下的訂閱記錄
異常流程 2a. 若 appId 不存在,貝提示請提供有效的 appId
2b.若該appId與該二維碼之間不存在訂閱關系,則提示訂閱關系不 存在,移除成功
據存儲在了緩存數據庫Redis中,將一部分設備操作日志文件和系統日志文件存 儲在了 MongoDB 中。
為了防止外網對系統微服務進行惡意調用,系統使用阿里云輕量級服務器 進行部署,統一部署在內網上,只通過一個開放模塊與外網進行連接,并對所有 連接進行管理。并且,在前端通過調用這個開放微服務時,需要進行安全認證 來保證系統安全性,避免被惡意調用的情況。然后這個微服務再去調用相應的 模塊,進行邏輯處理。同樣,返回結果時依然需要經過該開放模塊完成交互。采 用這樣的部署方式,在內部服務相互調用時不需要進行安全認證,簡化了系統 內部的調用。
同時,子系統中的模塊也會通過Spring Cloud中的Feign組件與原有系統中 的模塊進行交互,例如在支付模塊,支付微服務需要通知原系統中訂單微服務
新風設備信息管理子系統
展示層
A
RESTful
個
RESTful
△
RESTful
\k
注冊發現
Eureka注冊中心
7K
注冊發現
注冊發現
圖 3.4: 系統總體架構圖
修改對應的訂單狀態,數據開放平臺需要通知原系統中的機器控制微服務發送 操控設備的指令等等。新構建的子系統是在原有的系統中添加功能模塊,并與 原有模塊進行交互,同時在數據層構建新的數據結構。
3.3 系統模塊設計
系統模塊根據功能進行垂直劃分,每一個模塊都獨立成微服務,每個服務 擁有多個實例。根據上文的需求分析,將系統分為 5個模塊分別對應和實現短 信功能需求、支付功能需求、獲取城市空氣質量功能需求、用戶行為統計功能需 求以及數據開放功能需求。本章將依次詳細介紹這5 個模塊的設計思路。
3.3.1 短信模塊設計
基于上文對于短信模塊的需求分析,該模塊的結構設計同樣分為兩個部分 分別是發送短信和短信管理。在發送短信的部分,由前端或系統其他模塊發起請 求,短信模塊會將接收到的參數和身份認證token等發送給第三方平臺Luosimao 服務器,通過該平臺將發送短信的請求發送給運營商平臺,實現給用戶發送短 信的功能同時將該條短信記錄保存到數據庫。由前端發起發送短信請求并處理 的流程圖如圖3.5所示。而在短信管理的部分,由前端頁面發起請求,將查詢條 件發送給短信模塊,該模塊再對數據庫進行查詢和讀取。
圖3.5: 發送短信流程圖
從圖中可以看出,后端實現發送短信的功能的主要流程是:接收到前端發 來的請求和參數,基于防御式編程,首先進行權限和參數校驗,如果發起者沒有 發送短信的權限或者有必要字段沒有填寫,返回給前端錯誤信息。在確定參數 無誤后,向第三方平臺發起請求并傳參數,并且將此次發送短信的記錄寫入數 據庫。最后,將發送是否成功的結果返回給前端進行展示。
圖 3.6 表示的是短信模塊的結構圖。首先,本文關于前后端的交互均采用 RESTful的架構,是因為使用該架構時,服務器的主要壓力都放在了接口,優化 了服務器的性能;而且,使用RESTful結構,開發人員都可以根據請求的路徑 以及請求方法就看出接口的主要操作對象、操作方法和返回數據的規則,格式 清晰便于開發。
在數據庫設計中,系統中所有的數據庫表在創建時都會統一分配兩個字段 分別是create_time字段和block_flag字段。create_time字段即這條數據創建時的 時間戳。block_flag作為一個軟刪除的標識位,默認值為0,表示數據有效。所 以,當刪除某一條數據的時候,并不會采取硬刪除將該記錄徹底從數據庫中刪 掉,而是將對應的的block_flag字段置為1來表示刪除。并且,一旦置為1之后 即表示已刪除,恢復這條記錄只能采用重新插入的操作。采用這種方法,雖然浪 費了少部分的數據庫空間,但無需對刪除的數據實時進行數據備份,也可以避 免潛在的數據丟失。
圖 3.6: 短信模塊結構圖
text_message發送短信表主要記錄的是系統發送過的所有短信數據。主要包 括發送對象的手機號、發送短信的正文內容和發送短信的時間。管理員通過系 統單一給指定用戶發送短信或者批量發送都會記錄在這張表中。具體的表結構 如表3.13所示。
表3.13: 短信模塊發送短信數據表
名稱 類型 主鍵 外鍵 唯一 備注
message id varchar(20) 是 否 是 主鍵
phone varchar(45) 否 否 否 用戶手機號
text varchar(150) 否 否 否 發送短信正文
create time datetime 否 否 否 記錄添加時間
block flag tinyint(1) 否 否 否 數據是否有效標志位
由于短信數據過多和提高系統的查詢效率,將發送的短信數據和接收到的 短信數據分開存儲。in_text_message接收短信表主要記錄系統接收到所有短信 的數據,主要包括發送的對象手機號,發送的短信正文內容等。數據表的具體結 構如表 3.14 所示。
message_template 短信模板表主要存儲管理員手動添加的發送短信的模板 信息。其中, message_catalog 表示管理員定義的模板編號,便于使用模板發送短 信時進行選擇, message_content 表示短信模板的主要內容。系統通過對這張表 的查詢,就可以實現系統在特定條件觸發下自動給用戶發送短信的功能。例如 在用戶登錄手機號登錄微信小程序時,為了保證用戶信息安全,會觸發系統自
表 3.14: 短信模塊接收短信數據表
名稱 類型 主鍵 外鍵 唯一 備注
message id varchar(20) 是 否 是 主鍵
mobile varchar(45) 否 否 否 發送用戶手機號
text longtext 否 否 否 短信正文
create time datetime 否 否 否 記錄添加時間
block flag tinyint(1) 否 否 否 數據是否有效標志位
動查詢模板內容并拼接隨機生成的驗證碼,發送給用戶,通過用戶輸入驗證碼
到系統來完成身份認證。具體的表結構如表3.15所示。
表3.15: 短信模塊短信模板數據表
名稱 類型 主鍵 外鍵 唯一 備注
template id varchar(20) 是 否 是 主鍵
message catalog tinyint(1) 否 否 否 模版編號
message_content varchar(100) 否 否 否 短信內容
create time datetime 否 否 否 記錄添加時間
block flag tinyint(1) 否 否 否 數據是否有效標志位
3.3.2 支付模塊設計
以用戶在微信小程序端進行支付為例,支付模塊的架構圖如圖 3.7 所示。支 付模塊涉及到與微信后臺通過Http請求的消息交互,系統內通過Feign組件與 訂單模塊的交互,還有通過Mybatis與數據庫MySQL的數據交互。
在持久層的設計中,系統集成了 MyBatis作為中間件。在開發中,會首先在 properities配置文件中指定該服務模塊所連接的數據庫端口號等信息,Spring會 自動根據該文件幫助連接。并且由于MyBatis是使用SqlSession的方式操作數據 庫,所以本文構造了一個BaseDao抽象類,將SqlSession在該類中進行引用,這 樣所有持久層的類繼承該類即可進行交互。
在支付模塊的邏輯層設計中,主要包括支付類、賬單類和交易快照類。其 中,支付類主要處理由微信小程序發來的支付請求和第三方平臺推送來的支付 結果,交易快照類主要用來生成和查找交易訂單。支付處理涉及到訂單服務,系 統將訂單服務的調用封裝成Feign類型接口。邏輯層的類圖如圖3.8所示。
在數據結構類的設計中,支付模塊的數據庫ER圖如圖3.9所示。基于數據 庫三范式的原則,將數據分為3張表獨立存儲,分別為賬單表、交易快照表和交 易渠道表。表間的關系和每個表的主要數據結構也如圖所示。
trade_info 賬單信息表主要記錄了支付賬單的相關信息。賬單信息表和訂 單表是一一對應,由訂單編號order_id作為外鍵相聯系。和交易渠道表是多對
圖 3.7: 支付模塊結構圖
<<Interface>>
BillService
fetchBill(condition: Map): ResultData createBill(billInfo: BillInfo): ResultData updateBill(billInfo: BillInfo): ResultData deleteBill(billId: String): ResultData Buy(request: HttpServletRequest , response:
<<Interface>> SnapshotService
+ fetchSnapshot(condition: Map): ResultData
+ createSnapshot(snapshot: DealSnapshot): ResultData
+ deleteSnapshot(snapshotId: String): ResultData
BillServiceImpl
-driftService: DriftService
-snapshotservice: Snapshotservice
fetchBill(condition: Map): ResultData createBill(billInfo: BillInfo): ResultData updateBill(billInfo: BillInfo): ResultData deleteBill(billId: String): ResultData Buy(request: HttpServletRequest , response:
+
+
+
+
+
HttpServletResponse )
SnapShotServiceImpl
+ fetchSnapshot(condition: Map): ResultData
+ createSnapshot(snapshot: DealSnapshot): ResultData
+ deleteSnapshot(snapshotId: String): ResultData
圖 3.8: 支付模塊邏輯層類圖
圖3.9:支付模塊數據庫ER圖 一的關系,多條賬單可以對應相同的交易渠道編號,用 channel_id 作為外鍵 trade_status字段表示賬單的支付狀態,“0”表示未支付,“1”表示支付完成。其 他詳細的數據結構如表 3.16 所示。
表 3.16: 賬單信息數據表
名稱 類型 主鍵 外鍵 備注
trade id varchar(20) 是 否 主鍵,賬單編號
order id varchar(20) 否 是 訂單編號
order price double 否 否 訂單金額
actual price double 否 否 應結訂單金額
trade status tinyint(1) 否 否 賬單狀態
account id varchar(20) 否 是 賬單編號
channel id varchar(20) 否 是 交易渠道編號
create time datetime 否 否 賬單創建時間
block flag tinyint(1) 否 否 軟刪除標示位
payment_channel 支付渠道數據表用來表示用戶可選擇的多種支付渠道的相 關信息,例如微信支付、支付寶支付、京東支付等等。與賬單信息數據表是多對 一的關系。具體的表結構如表3.17所示。
deal_snapshot交易快照數據表用于記錄第三方平臺向系統推送的支付結果。 表中記錄了大多數的第三方平臺返回的用戶支付信息,包括付款銀行、貨幣種
表 3.17: 交易渠道數據表
名稱 類型 主鍵 外鍵 備注
channel id int(11) 是 否 主鍵
channel name varchar(45) 否 否 支付渠道名稱
create time datetime 否 否 支付渠道創建時間
block flag tinyint(1) 否 否 軟刪除標示位
類、支付完成時間等等,以及此筆交易是在哪個支付平臺進行,便于在發生數 據泄露或賬單狀態不明等情況時進行查詢。具體的表結構如表3.18所示。其中 channel_id 作為交易渠道表的外鍵,與交易快照表作為一對多的聯系,表示該比 交易是發生在具體哪個交易平臺,即系統接收到該支付信息的發送對象編號。其 他字段的信息由于篇幅限制不再贅述。
表 3.18: 交易快照數據表
名稱 類型 主鍵 外鍵 備注
snapshot id varchar(20) 是 否 主鍵
trade id varchar(20) 否 是 賬單編號
account id varchar(20) 否 是 賬戶編號
aPP」d varchar(20) 否 否 微信小程序編號
mch id varchar(20) 否 否 商戶編號
device info varchar(45) 否 否 設備號
is subscribe varchar(1) 否 否 是否關注公眾號
channel id varchar(20) 否 是 支付渠道編號
bank type varchar(20) 否 否 付款銀行
order price double 否 否 付款金額
actual price double 否 否 應結訂單金額
fee type varchar(20) 否 否 貨幣種類
transaction id varchar(32) 否 否 微信支付訂單號
time end varchar(14) 否 否 支付完成時間
create time datetime 否 否 交易快照創建時間
block flag tinyint(1) 否 否 軟刪除標示位
3.3.3 空氣質量模塊設計
空氣質量模塊主要是用于獲取全國各個省市的空氣質量指數,再將這些原 始數據整合供用戶訪問。在本文中,主要使用外部網站“墨跡赤必”作為數據 源。本文通過在其網站進行注冊和購買服務,再通過 Http 請求的方式來獲取數 據。首先,定時任務引擎會觸發向“墨跡赤必”獲取數據,在獲取數據后由于 這部分數據會進行較為頻繁的讀取,所以先把這部分數據同時存儲在Redis和 MySQL 中。當用戶在前端對這一模塊的數據進行查詢時,該模塊會先對 Redis 查找,如果結果為空再去請求MySQL。同時,設置了另外的定時任務來對這部 分數據基于不同維度進行整理和統計,包括時間維度和空間維度。例如,某個省 的平均城市空氣質量、某個城市的月平均空氣質量等等。該模塊的整體結構圖 如圖3.10所示。
圖 3.10: 空氣質量模塊結構圖
空氣質量模塊邏輯層的類圖設計如圖 3.11 所示。在此模塊中,主要有兩個 核心類,分別是 CityAQIService 調用第三方服務獲取原始數據類以及 AirQualityStatisticService 數據統計類。在接收到第三方返回的數據流之后,控制層會通 過解析和清洗獲取到需要的字段數據,并將這些數據同時寫入Redis和MySQL 數據庫。由于 Redis 為緩存數據庫,可以提高查詢速率和相應速率,并且最新獲 取到的數據會有較頻繁的查詢操作,因此將這部分數據同時寫入Redis當中。并 且,設置Redis中數據的存活時間為24小時,在緩存中存活超過24小時的數據 就會被刪除,保持了 Redis中始終保存獲取的最新數據。之后,定時任務引擎還 會觸發對這些數據在時間維度和空間維度上的整理和統計,再將整合后的數據 保存到數據庫中提供查詢。
空氣質量模塊的數據庫設計中,需要從3個角度進行設計。首先,由于本文 調用第三方服務“墨跡赤必”進行數據的獲取,關于其平臺的數據,例如購買服 務后獲取到的請求標識token等信息、其平臺的城市編號與系統內的城市編號的 對應關系等,為了保證數據的安全性,均需要建表存儲。其次,為了保證數據一 致性,系統需要將獲取到的原始數據進行存儲。第三,對于數據的整合和統計 分為時間維度和空間維度,都需要分別建表存儲,例如,每小時的每個城市的空
+ handleAirQualityHourlyStatistic(): ResultData
+ handleAirQualityDailyStatistic(): ResultData
+ handleAirQualityMonthlyStatistic(): ResultData
+ fetchLatestAirQuality(condition: Map): ResultData
+ fetchAirQualityHourlyStatistic(condition: Map): ResultData
+ obtainCityName(cityId: String)
圖3.11: 空氣質量模塊邏輯層類圖
氣質量數據,每個月每個省的平均空氣質量數據等等。在進行數據庫表的介紹 時,由于表結構類似,這里基于每個角度只選取一個進行展示。
moji_token 表中是存儲的所有與系統在墨跡平臺的身份信息相關的數據表 為了保證數據安全不暴露在代碼中,本文將這些數據存儲在數據庫。具體的數 據表結構如表 3.19 所示。
city_daily_aqi 表存儲的是根據時間維度統計的城市的每天的平均空氣質量 數據。由于pm2.5的數值很大程度上反應了空氣質量,為了提高查詢效率,在該 維度的統計表中本文只統計平均pm2.5的數值。具體的表結構如表3.20所示。
province_airquality 表存儲的是根據地理位置統計的每一個省份的平均的
PM2.5 指數。同樣,這張表的統計任務的數據源直接使用省內每一個城市的
PM2.5的數據。具體的表結構如表3.21所示。
表 3.19: 墨跡信息數據表
名稱 類型 主鍵 外鍵 備注
token id varchar(45) 是 否 主鍵
token varchar(45) 否 否 墨跡提供的請求標識
password varchar(45) 否 否 登錄密碼
url varchar(45) 否 否 請求地址
base varchar(45) 否 否 未加參數的請求地址
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
表 3.20: 每日空氣質量指數統計數據表
名稱 類型 主鍵 外鍵 備注
city id int(11) 是 否 主鍵
pm_25 double 否 否 一日內平均PM2.5指數
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
表 3.21: 省份空氣質量指數統計數據表
名稱 類型 主鍵 外鍵 備注
city id int(11) 是 否 主鍵
province name varchar(45) 否 否 省份名稱
pm_25 double 否 否 平均PM2.5指數
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
3.3.4 用戶行為統計模塊設計
用戶行為統計模塊的功能可以分為兩個部分,如圖3.12所示,分別是用戶 行為數據整合和數據清理。在數據整合部分,由于系統使用 MongoDB 存放所有 設備的日志文件以及用戶操作設備的原始數據,并且為了數據的及時清理避免 占有越來越多的資源空間,系統設置定時任務引擎,定時觸發從MongoDB中獲 取原始數據,并進行數據整合和統計。然后,將統計好的數據寫入MySQL中, 提供數據接口以便管理員通過前端進行相關數據的查詢。其次,由于原始數據 量越來越多,必須要對使用可能性較低的數據進行備份、刪除和清理,以及時釋 放 MongoDB 的磁盤空間存放新數據。在這個部分,系統采用 Linux 的 Crontab 進程定時執行Shell腳本來完成對數據庫中一個月前的數據的備份和刪除,繼而 整理磁盤碎片,釋放數據庫空間。
在用戶行為統計的數據庫設計中,由于系統需要針對每個組件進行統計,基 于數據庫三大范式,本文將每個組件單獨存儲在不同的表。而在時間維度上,系 統又需要整合不同周期內的統計結果。為了提高系統查詢的相應效率,本文又
圖 3.12: 用戶行為統計模塊結構圖
將每個組件的統計數據表拆分成不同時間段的統計數據表。因此,最后在次模 塊中,分為每小時對風量、模式、開關機等組件的操作統計,和每日、每月對獨 立組件的統計,依次類推。在介紹數據庫表中,本章只選取每個維度的一個表作 為樣例,其他表的結構類似。
volume_hourly 表中存儲了設備每小時的風量值相關的數據統計,包括在當 前時刻的前一小時內設備的最小風量、最大風量以及平均風量值等等。具體的 數據表結構如表3.22所示。
表 3.22: 每小時設備風量統計數據表
名稱 類型 主鍵 為空 備注
status id varchar(50) 是 否 主鍵
machine id varchar(50) 否 否 設備編號
average volume double 否 否 風量平均值
max volume int(11) 否 否 最大風量
min volume int(11) 否 否 最小風量
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
mode_daily 表存儲的是用戶在每日使用設備的不同模式的時長,目前設備 有 3 種模式可調節,分別為 cosy_minute、 warm_minute 和 manual_minute 字段。 例如設備處于手動模式的時長是3小時,處于制熱模式的時長為1小時等等。具 體的表結構如表 3.23 所示。
表3.23: 每日設備模式統計數據表
名稱 類型 主鍵 為空 備注
status id varchar(50) 是 否 主鍵
machine id varchar(50) 否 否 設備編號
manual minute int(11) 否 否 手動模式使用時長
cosy minute int(11) 否 否 制冷模式使用時長
warm minute int(11) 否 否 制熱模式使用時長
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
user_action 表存儲的是用戶在統計的前一天的時間里操作所有組件分別的 次數。例如,用戶在前一天操作風量3次、開關機4次、調節模式2次等等。具 體的表結構如表3.24所示。
表 3.24: 用戶操作設備組件統計數據表
名稱 類型 主鍵 為空 備注
record id varchar(50) 是 否 主鍵
machine id varchar(50) 否 否 設備編號
user id varchar(50) 否 否 用戶編號
component varchar(50) 否 否 操作組件
component timef int(11) 否 否 操作該組件的次數
block flag tinyint(1) 否 否 數據是否有效標志位
create time datetime 否 否 數據的創建時間
3.3.5 數據開放平臺模塊設計
數據開放平臺模塊主要提供第三方控制引入的能力,并支持第三方平臺完 成對設備的相關檢索及控制操作,該模塊主要提供訂閱設備、獲取設備列表、獲 取設備運行狀態、獲取設備所處城市空氣數據、移除設備、開/關設備、調節設 備運行風量的數據開放接口。第三方平臺通過該模塊控制設備的大致流程如圖 3.13。從圖中可以看出,當第三方平臺的請求經過參數驗證和權限驗證之后,并 不是由數據開放平臺模塊直接對設備進行操作,而是將請求發送給機器控制模 塊,由機器控制模塊發送指令到設備端。采用這樣的操作雖然多了一步請求流 程,需要進行調用其他微服務,但是一方面保證了系統的安全性,另一方面也便 于對第三方發來的請求進行管理。數據開放平臺模塊的數據庫主要由兩張數據 表組成,第三方平臺信息表用來記錄用戶相關身份信息,用戶完成注冊后,系統 會將用戶相關信息包括姓名corp_name、郵箱corp_email、生成的appId等信息 寫入 corp_profile 該表來記錄注冊狀態。具體的表結構如表 3.25 所示。
另一張 corp_machine_subscribe 表用來記錄用戶和設備的訂閱狀態,二者根
圖 3.13: 授權平臺方操作設備流程圖
表 3.25: 第三方平臺信息表
名稱 類型 主鍵 備注
corp id varchar(20) 是 主鍵,UUID隨機生成20位字符串
corp_name varchar(45) 否 第三方平臺注冊的名稱
corp email varchar(45) 否 第三方平臺注冊的郵箱
corp app id varchar(45) 否 管理員分配給用戶的唯一身份標識
block flag tinyint(1) 否 數據是否有效標志位
create time datetime 否 數據的創建時間
據corp_id和code_value進行綁定,串聯全量訂閱設備信息;appld合法且包含 訂閱設備id時,才能完成檢索、控制設備等操作,故需在HTTP Request中提供 appId及設備二維碼進行注冊驗證及訂閱驗證。表3.26展示了具體的表結構。
表 3.26: 用戶訂閱設備關聯表
名稱 類型 主鍵 備注
subs id varchar(20) 是 主鍵,UUID隨機生成20位字符串
corp id varchar(45) 否 第三方平臺id
code value varchar(45) 否 設備唯一標識符
block flag tinyint(1) 否 數據是否有效標志位
create time datetime 否 數據的創建時間
3.4 本章小結
本章主要介紹了該信息管理子系統的需求和設計。首先,對系統進行了總 體的功能分析,然后分別介紹了每個模塊的功能需求,并給出了具體的用例表 便于理解應用場景。然后對系統整體架構進行了設計,再對每個模塊依次從功 能實現流程、內部結構、邏輯層調用、數據庫的設計各個角度分別給出了相應的 圖表并進行說明,使設計清晰具體。
第四章 新風設備信息管理子系統的詳細實現
這一章會根據第三章的需求分析和模塊設計,分別對每一個模塊進行具體 的代碼實現。會給出一些主要的邏輯代碼,并用一些時序圖、系統截圖等進行輔 助介紹,詳細展示系統具體如何了實現前文所述的那些功能。
4.1 短信模塊
4.1.1 發送短信代碼實現
如圖 4.1 為短信模塊實現發送短信功能的邏輯時序圖。如圖所示,當管理員 在前端發起請求,短信微服務會將請求發給Luosimao服務器,通過該平臺將請 求發送給相應的移動、聯通等運營商平臺,最后運營商把短信發送給管理員指定 的手機號并返回發送結果。Luosimao服務器將實現結果返回給短信微服務,短 信微服務將返回結果進行解析。如果成功發送短信,則將記錄寫入數據庫。最后 再將處理結果返回給前端,完整實現發送短信的流程和功能。
圖4.1:發送短信功能邏輯時序圖
圖 4.2即展示了管理員登錄業務系統后實現發送短信功能的前端頁面。可以 看出,管理員需要首先輸入短信正文,然后如果是逐條發送給用戶,可以選擇直
圖 4.2: 發送短信功能前端頁面
接輸入手機號;如果是批量發送短信,也可以將手機號存儲在文件中發送給前 端,由前端進行解析處理,再發送給后端。這樣,當管理員點擊確認發送后,前 端就會將這些參數通過 Restful 接口通過網關校驗后發送給后端的短信微服務 由該服務進行處理。在代碼的具體實現中,當后端收到前端發送來的單發短信
public static ResultData sendOne(String phone, String text) {
ResultData result = new ResultData。;
Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("api", MessageProperties.getValue("message_api_key")));
WebResource webResource = client.resource( "http://sms-api.luosimao.com/v1/send.json");
MultivaluedMapImpl formData = new MultivaluedMapImpl(); formData.add("mobile", phone);
formData.add("message", text);
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED). post(ClientResponse.class, formData);
logger.info(JSON.toJSONString(response));
return result;
}
圖 4.3: 調用第三方服務發送短信代碼實現
或群發短信的請求后,后端首先按照防御式編程思想驗證參數:發送對象的手 機號列表和短信內容。然后分為兩步,因為該平臺提供了 3個不同的API分別 為:發送單條短信、批量發送和查詢賬戶余額,本文首先根據參數調用Luosimao 提供的對應的API,并傳入包括在其平臺注冊得到的API key等參數,Luosimao 使用 HTTP Basic Auth 方式進行身份驗證,使用 api 作為驗證用戶名, API key 是 驗證密碼,驗證通過后再按照手機號列表和內容進行短信發送。圖4.3展示了調 用其第三方接口發送單條短信的代碼實現。
然后同時,為了保證數據一致性,創建新的線程將已發送的短信數據保存
到數據庫。圖4.4即展示了用戶在Web端發送發送短信的請求后,后端進行的 分步操作。
@RequestMappi ng(method = RequestMethod.POST, value = "/se nd/si ngle") public ResultData sendOn e(MessageForm form) {
ResultData result = new ResultData();
String text;
if(Stri ngUtils.isEmpty(form.getSig nature())){
text = new
Stri ngBuffer(form.getText()).appe nd(MessageProperties.getValue("me ssage_sig nature")).toStri ng();
}else {
text = new
Str in gBuffer(form.getText()).appe nd(form.getSig nature()).toStr in g();
}
MessageUtil.se ndOn e(form.getPh on e().trim(), text.trim());
〃保存數據到數據庫
TextMessage message = new TextMessage(form.getPh on e().trim(), form.getText().trim());
new Thread(() -> messageService.createTextMessage(message)).start(); return result;
}
圖4.4: 短信模塊實現發送短信功能代碼實現
4.1.2 短信管理代碼實現
短信業務中,系統需要對短信進行多維度統計,既包括系統發送給用戶的 短信,也包括用戶對于系統的回復短信。而在整合和統計時,既要在用戶維度進 行統計,也需要在時間維度統計。而如果針對不同的查詢條件都在控制層開發 出一個不同的接口,這樣會導致接口過多并且代碼大量重復的問題。因此,在 整個系統的開發過程中,系統需要盡量在持久層合并查詢條件以減少接口數量 提高代碼的復用率。因此,系統利用MyBatis和SQL支持if語句,for語句,以 及各種拼裝語句的特性,只需要在控制層就把查找條件封裝成Map,在邏輯層、 持久層依次傳遞,作為查找語句的參數,使代碼具有強伸縮性,提高代碼復用 率[34]。并且通過“CONCAT”和“%”實現了根據字段的部分字符串進行模糊 查找數據的功能。
如圖4.5即展示了 Web端查詢2020年3月2日到2020年3月11日系統發 送給手機號中含有“188”字符串的短信信息列表結果。管理員可以隨意選擇查 詢的時間范圍和手機號進行模糊查詢,系統會根據前端傳入的參數進行查找和
圖 4.6: 查詢回復短信頁面截圖
篩選。而圖 4.6 展示了在沒有篩選條件的情況下,系統查詢到的所有系統收到的 回復短信。從圖中可以看出,結果按照時間倒序進行展示,顯示了時間、手機號 和短信內容等信息。
4.2 支付模塊
4.2.1 支付訂單代碼實現
在這一業務場景中,首先由用戶在微信小程序的旗艦店里選擇商品通過訂 單模塊生成訂單,請求支付。支付模塊將前端傳來的參數按照微信的要求生成 賬單,寫入數據庫的同時將賬單發送給微信支付平臺,請求發起支付窗口。在微 信后臺同意后會返回一系列參數,支付模塊將這些參數發送給前端,使前端拉 起支付窗口。用戶選擇支付渠道確認交易信息輸入密碼后,微信小程序鑒權調
起微信后臺的支付接口。在微信后臺處理完這筆交易后,將處理結果推送給支 付模塊和前端。支付模塊會首先修改賬單狀態,然后通知訂單模塊修改訂單狀 態。圖 4.7 展示了用戶在微信小程序內下單后系統與微信后臺的完整交互流程。
圖 4.7: 微信小程序端下單支付邏輯時序圖
圖 4.8 即展示了管理員進行訂單查詢的頁面截圖。在用戶正常支付完成后 訂單狀態會立即更新為“未處理”,以供管理員進行查詢,而未完成支付的訂單 就不會出現在該頁面。當其他部門對訂單進行發貨、安裝等,訂單狀態即會更 新。管理員在訂單狀態一欄選擇“未處理”,即可查詢到所有已經完成支付但還 未進行其他任何處理的訂單。
在代碼實現上,圖 4.9 展示了支付模塊處理微信平臺推送支付結果的主要代 碼邏輯。從圖中可以看出,系統在收到微信后臺傳入的參數request后,將xml 解析成Map,如果返回支付結果為成功,解析出其他返回數據。然后進行簽名 驗證,校驗返回的訂單金額是否與商戶側的訂單金額一致。如果金額一致,根據
圖 4.8: 訂單查詢頁面截圖
public String payNotify(String notifyXml) {
〃讀取返回結果
MapvString, String〉notifyMap = XMLUtil.doXMLParse(notifyXml);
if ("SUCCESS".equals(notifyMap.get("result_code"))) {
〃找到對應賬單
String out_trade_no = notifyMap.get("out_trade_no");
queryMap.put("orderId", out_trade_no);
ResultData tradeResult = tradeDao.query(queryMap);
Trade trade = ((List<Trade>)tradeResult.getData()).get(O);
〃簽名驗證,并校驗返回的訂單金額是否與商戶側的訂單金額一致
MapvString, String> signMap二notifyMap;
String sign = PayUtil.generateSignature(signMap, key);〃重新簽名 if (StringUtils.isNotBlank(sign)&&sign.equals(notifyMap.get("sign"))) { 〃金額驗證
if (total_fee==total_fee_resp) {
〃支付完成,更新賬單狀態
trade.setTradeState (TradeState .P AYED);
〃調用并更改訂單的狀態
orderService.updateOrderPayed(trade.getOrderld());
〃返回給微信
paraMap.put("return_code", "SUCCESS");
String wxXml = PayUtil.mapToXml(paraMap);
return wxXml;
}
}
return null;
}
圖 4.9: 處理微信支付結果代碼實現 解析出的 out_trade_no 在數據庫查找到對應的 trade 對象,然后修改此條數據的 賬單狀態。同時使用 Feign 組件通知訂單模塊修改相應的訂單狀態,最后返回給 微信后臺接收到此Http請求的字符流。
在這個過程中,本文為了提高讀取字符流的效率,采用了 BufferedReader讀 取 Http 請求,其次,基于防御式編程的思想,系統會首先對支付返回結果失敗 的情況進行處理。在邏輯處理過程中,為了保證數據一致性,在更改賬單狀態 后是創建新的線程去通知訂單模塊修改訂單狀態,同時提高了程序的運行效率 第三,使用了 Webhooks來等待第三方平臺的推送,而不需要采用輪詢的方式時 刻監聽服務器調用 API。
在支付賬單的模塊中,由于定義“0”為賬單的未支付狀態,“1”代碼賬單的 支付狀態,因此本文選擇 EnumOrdinalTypeHandler 作為 Mybatis 的枚舉類型轉換 器,相比于Mybatis提供的默認轉換器EnumTypeHandler來說,EnumTypeHandler 會將值轉換成 String 類型,而 EnumOrdinalTypeHandler 會將枚舉類中的定義值 轉換為整性,適用于本文的場景。并且基于封裝的思想,將查詢條件封裝成Trade 類進行傳參,并利用其中的tradeId作為過濾條件,更新記錄中的trade_status字 段。
4.3 空氣質量模塊
4.3.1 獲取數據代碼實現
首先本文向第三方墨跡赤必官網申請獲取數據資源服務,在獲取授權后將 得到的請求標識token和password寫入數據庫。當前端發起請求請求當前設備 所在城市的空氣質量數據時,后端根據墨跡赤必提供的API請求地址請求格式, 構造Http請求獲取空氣質量數據。該模塊的邏輯實現如圖4.10所示,系統會在 定時任務引擎上設置定時任務,固定時間周期進行數據獲取。首先定時任務被 觸發后,空氣質量微服務會向墨跡赤必服務器發送數據請求,然后墨跡赤必根 據發來的參數進行數據查詢并返回給空氣質量微服務,該服務再將返回的數據 流進行解析和清洗,將有效數據寫入同時刷新到MySQL和Redis數據庫。當系 統對這一任務進行處理完成后,再向定時任務引擎返回處理結果。當用戶或管 理員在前端發起請求時,請求被指定到空氣質量模塊,該模塊會首先在Redis中 查詢,如果沒有在緩存中沒有查詢到相應結果,再向MySQL進行查詢,將最后 的結果返回到再通過空氣質量模塊返回給前端,展示給用戶。
圖4.11展示了調用接口根據cityId獲取數據的過程,與此相似的是根據lat (緯度)和lon (經度)獲取空氣數據的代碼。由代碼可以看出,為了保證數據安
圖 4.10: 獲取城市空氣質量邏輯時序圖
private CityAirQuality fetch(String lid, int cityld) {
MojiToke n mojiToke n = (((List<MojiToke n>) selectToke n().getData()).get(O));
Stri ngBuffer str in gBuffer = n ew.Stri ngBuffer(mojiToke n.getUrl()). append("?cityld=").append(cityld);
Stri ng url = str in gBuffer.toStr in g();
String subUrl = url.substring("https://api.mojicb.com".length(), url.indexOf("?")); logger .in fo(url);
Long timeValue = LocalDateTime. now(). tolnstant(ZoneOffset.of("+8")).toEpochMilli();
String timeStamp = timeValue.toString();
String nonce = UUID.randomUUID().toString();
Stri ng sig nature = En crypti on. md5(mojiToke n. getPassword() + "\n" + timeStamp + "\n" + nonce + "\n" + subUrl);
Map<String. String> map = new HashMap<>(); map.put("X-AC-Toke n", mojiToke n. getToke n()); map.put("X-Date", timeStamp);
map.put("X-AC-No nee", non ce); map.put("X-AC-Sig nature", sig nature);
Stri ng result = HttpDeal.getResp on se(url, map);
CityAirQuality quality = in terpret(lid, result);
return quality;
}
圖 4.11: 調用第三方服務獲取空氣數據代碼實現 全性,新建的 StringBuffer 實例對象只拼接了 cityId 或者經度、維度這樣的參數 字符串,而標識符存儲在了數據庫中,需要先從數據庫中讀取,再用 MD5 加密 算法加密,生成簽名。然后將token、時間戳、簽名封裝成Map,最后在發起Http 請求時再使用 for 循環語句將 Map 中的 value 取出放入請求頭,構造請求體發起 請求。
圖 4.12: 微信公眾號查看空氣質量頁面截圖
圖 4.12 即展示了用戶在手機端打開微信公眾號后,查看機器狀態的頁面 從圖中可以看出,借助地址解析模塊最上面即展示了設備當前所在城市,和當 前室外的AQI和PM2.5的數值。中間部分展示了設備當前所在室內的空氣質量 數據,包括PM2.5、二氧化碳、溫度等等。如圖中的38和30,即代表了這臺機 器當前的室內外空氣質量,從而可以明顯看出新風設備所帶來的空氣凈化效果。
4.3.2 數據整合實現
圖 4.13 是整合每小時每個城市的空氣質量數據的代碼實現。從代碼中可以 看出,整合每小時城市數據時,系統需要先從 city_aqi_full 表中根據時間范圍查 找出上一小時內的數據封裝成List,然后利用String的Stream流操作,簡化代 碼,減輕程序運行的壓力。將List中的每個CityAirPm25Vo對象利用Collectors的 groupingBy 方法根據 cityId 進行分組,然后再用 Collectors 的 averagingDouble 方 法計算每個城市上一小時的數據平均值,然后再將cityId和對應的平均值封裝成 Map,利用 Map 的 Stream 流方法再將 Key 和 Value 封裝成 CityAirQualityStatistic 對象添加到 List 中,這樣即實現了數據的整合,也方便了后續寫入數據庫的操 作。這里多次使用Stream方法,是因為Stream正適合本文中對List集合對象進 行分組取平均值的整合操作并重新封裝的場景。
public ResultData han dleAirQualityHourlyStatistic() {
ResultData result = new ResultData();
Map<Stri ng, Object〉con diti on = new HashMap<>();
Timestamp lastHour = new Timestamp((System.curre ntTimeMillis() - 300000) /.
(3600000) * 3600000);
con diti on .put("recordTime", lastHour);
//從city_aqi_full表屮查找數據
ResultData resp onse = cityAirQualityDao.select(c on diti on);
if (respo nse.getRespo nseCode() == Respo nseCode.RESPONSE_OK) { List<CityAirPm25Vo> list = (List<CityAirPm25Vo>) response.getData(); Map<String, Double> cityAqiMap = list.stream().collect(
Collectors.groupi ng By(CityAirPm25Vo::getCityld,
Collectors.averagi ngDouble(CityAirPm25Vo::getPm25)));
List<CityAirQualityStatistic> airQualityStatisticList =
cityAqiMap.e ntrySet().stream()
.map(e -> new CityAirQualityStatistic(e.getKey(), e.getValue()))
.collect(Collectors.toList());
if (!airQualityStatisticList.isEmpty())
resp onse = airQualityStatisticDao.i nsertHourlyData(airQualityStatisticList);
}
}
圖 4.13: 整合每小時空氣質量數據代碼實現
圖 4.14: 查詢城市空氣質量頁面截圖
從圖 4.12的下半部分也可以看出,通過數據整合,用戶可以隨時打開微信 公眾號查看一周內室內外空氣質量的變化曲線,并將室內外空氣質量進行對比。
例如圖中所展示的這臺設備,所在位置的室內空氣質量在7天內的空氣污染指 數均小于室外的空氣污染指數。這樣,就可以更明顯的看出設備在所帶來的長 期凈化效果,凸顯了設備的能力,提高用戶的滿意度。
圖 4.14 即展示了管理員在前端根據日期和城市查詢空氣質量的頁面。其中 日期是必要的輸入條件,如果不輸入城市則返回所有的城市空氣數據。
4.4 用戶行為統計模塊
4.4.1 行為數據整合實現
在統計用戶行為數據的模塊中,本文要從多個維度進行查找統計。在代碼 實現過程中,對于不同維度的統計,又主要分為3個步驟。圖4.15展示了這一 模塊的整體邏輯時序圖。
用戶行為統計微服務 MongoDB數據庫 MySQL數據庫
管理員
圖 4.15: 用戶行為數據整合邏輯時序圖
首先,由于系統使用 TCP 長連接管理超過萬臺設備, 來實現負載均衡減少 系統開銷 [35],每臺設備每 30秒就會向服務器發送數據包,這造成了會有海量 數據需要存儲和查詢。如果此時選擇MySQL存儲設備原始數據,由于MySQL 的特性查詢效率會顯著降低。而 MongoDB 與之相比則非常適合這種彈性場景 正適合存儲類似日志文件等海量并且低價值的數據 [36]。并且 MongoDB 以文 檔存儲的形式 [37],面向集合的存儲,具有較好的代碼親和性。因此,本文選擇 public ResultData probeByUserld2Component() {
//獲取過濾條件中的時間范圍,取前一天和當前時間時間戳
condition.put("start", lastDay);
condition.put("end", currentDay);
ResultData response = userActionMongoService.fetchData(condition);
〃獲取mongo數據,首先根據userid進行分組
List<UserAction> actionList = (List<UserAction>) response.getData(); response = userActionMongoService.getDataGroupByUserld(actionList);
〃獲取每個用戶的行為數據,再根據不同的component進行分組統計
List<List<UserAction>> userldLists = (List<List<UserAction>>) response.getData();
List<UserActionDaily> actionDailyList = new ArrayList<>();
for (List<UserAction> list : userldLists) {
MapvString, Long> map = list.stream().collect(Collectors.groupingBy (UserAction::getComponent,Collectors.counting()));
for (String componentKey : map.keySet()) {
int componentTimes = map.get(componentKey).intValue(); UserActionDaily userActionDaily = new UserActionDaily(userid, qrcode, componentKey, componentTimes);
actionDailyList.add(userActionDaily);
}
}
//list不為空,批量插入數據庫
response = userActionDailyService.insertBatchDaily(actionDailyList); return result;
}
圖 4.16: 用戶行為數據整合代碼實現
Mongo來存儲所有設備發來的日志文件,而將整合好的數據存儲在MySQL中。 因此,本模塊首先就需要從MongoDB根據時間范圍讀取原始數據。
其次,由于用戶或管理員關心的數據主要分為兩個維度,分別是用戶和操 作組件,所以本文需要將這些獲取到的原始數據進行統計與整合。最后,再將整 合的數據分別再存儲寫入MySQL數據庫之中。圖4.16即展示出了基于用戶維 度,統計每日每個用戶操作不同的組件數的次數的在控制層的部分代碼。
圖 4.17 展示了這一模塊對應的前端頁面設計。管理員在登錄系統后,在用 戶行為統計部分,可以輸入用戶id、設備編號和日期進行對用戶行為的查詢。結 果則會返回該臺設備在當天的所有具體操作信息。圖中的搜索結果即展示了該 用戶在2019年10月29日這天共6次操作設備。
4.4.2 定時備份數據實現
本文使用 Linux 內置的 Crontab 進程 [38] 搭配 Shell 腳本實現定時備份和刪 除指定時間范圍內的指定數據的功能。 Crontab 的指令格式是執行周期加上執行 對象,時間部分有5個參數分別對應分、時、日、月、周。例如本文在系統中 配置的0 2 */2 * * /root/export.sh指令表示每兩天的凌晨2點執行/root/路徑下的 export.sh 腳本,圖 4.18 即展示了其中之一腳本內容。代碼顯示出,腳本首先需
圖 4.17: 用戶行為統計頁面截圖
要讀取另外的配置文件,獲取時間范圍的參數,根據讀取到的配置確定時間范 圍,繼而再用 mongoexport 指令導出數據為 csv 格式文件,保存到服務器留作 備份。也就是說,如果從 export.txt 中讀取到的內容為“1 2”,則該腳本就會將 gmair_packet 數據庫中的 machine_status 表中在前兩天到前一天的對應字段的數 據導出到"/root/mongo”路徑下的"20200401_vl.csv"文件中。然后使用tar命 令,將該csv文件進行壓縮,從而節省服務器磁盤空間。再將原文件刪除,實現 備份。
#更新配置文件
if [ $# -eq 2 ];the n
cat>export.txt<<EOF
$1 $2
EOF
fi
#讀取配置文件
cat export.txt | while read a b
do
cd /root/mongo
#根據配置確認時間段
temp1='date -d -"$a"day +%s' temp2='expr $temp1 \* 1000'
#導出數據
mongoexport -d gmair_packet -c machine_status - q'{"createAt":{$gte:'$temp2'},"createAt":{$lte:'$temp4'}}' -f _id,_class,uid,pm2_5,temp,humid,co2,volume,power,mode,heat,light,lock,blockFlag,cre ateAt --type=csv -o /root/mongo/"$temp5"_v2.csv
#壓縮文件
tar zcvf "$temp5"_v2.tar.gz "$temp5"_v2.csv
rm "$temp5"v2.csv
圖4.1 &導出MongoDB中數據代碼實現
#整理磁盤空間碎片,釋放空間
#!/bin/bash
mongo gmair_packet <<EOF
db.ru nComma nd({compact:'machi ne_status'})
db.ru nComma nd({compact:'machi ne_v1_status'}) db.r un Comma nd({compact:'machi ne_partial_status'}) db.repairDatabase()
EOF
圖4.19:整理MongoDB磁盤空間腳本代碼
而后繼續利用crontab指令定時運行shell腳本,刪除數據庫中的指定數據, 以節省數據庫的使用空間。并且配置另外的腳本利用compact指令定時整理磁 盤空間碎片.圖4.19即為整理磁盤空間的腳本。因此,每臺配置MongoDB的服 務器對于數據的備份和刪除有三個定時任務,分別為導出數據、刪除數據和整 理釋放空間。例如系統中其中一臺服務器配置的指令為0 2 */2 * * /root/export.sh 30 2 */2 * * /root/remove.sh; 0 3 */2 * * /root/compact.sh,即表示系統會在每隔 兩天的凌晨2點執行export.sh腳本進行數據導出,在保證數據已完成導出操作 后,2點30分執行remove.sh腳本刪除MongoDB中的數據,然后在3點執行 compact.sh腳本整理刪除數據庫之后導致的空間碎片。
4.5 數據開放平臺模塊
4.5.1 第三方平臺注冊實現
圖4.20中的代碼是第三方平臺在后臺創建用戶的代碼實現。在第三方平臺 創建用戶的實現中,前端會提交該平臺的相關信息,然后服務端會對提交的信 息進行處理,包括平臺名稱、平臺郵箱等等。
系統首先對前端傳來的參數進行校驗,在參數檢查無誤之后,系統先根據 傳入的 corpName 和 corpEmail 去數據庫查找相關的記錄。如果在數據庫中查找 到了當前平臺的相關數據,說明該平臺已經注冊過信息,因為同時用corpEmail 進行數據庫查詢,并不會存在因為平臺同名導致不能注冊的情況。第三方平臺 注冊成功后,返回“創建成功”信息給前端,第三方平臺需要聯系管理員獲取特 定的appId,作為該平臺的唯一特定身份標識。
而圖 4.21 是查詢第三方平臺的注冊信息的代碼實現。除此,后端還提供了 另外一個接口,用戶可以通過前端傳入 corpName、 corpEmail、 appId 等參數進 行查詢該平臺的相關注冊信息,或判斷是否已經注冊。
圖 4.22即展示了對應的前端頁面,從圖中可以看出,管理員可以使用企業 public ResultData create(CorpProfileForm form) {
〃參數校驗
if (org.spri ngframework.util.Stri ngUtils.isEmpty(form.getCorpName()) || org.spri ngframework.util.Stri ngUtils.isEmpty(form.getCorpEmail())) {
result.setResp on seCode(Respo nseCode.RESPONSE_ERROR); return result;
}
con diti on. put("corpName", corpName);
con diti on. put("corpEmail", corpEmail);
con diti on. put("blockFlag", false);
ResultData resp onse = corpProfileService.fetch(c on diti on);
〃查重
if (respo nse.getRespo nseCode() == Respo nseCode.RESPONSE_OK) { result.setRespo nseCode(Respo nseCode.RESPONSE_ERROR); result.setDescriptio n(“ 企業名:“ + form.getCorpName() + "的用戶已存在“); return result;
}
〃創建用戶
CorpProfile corpProfile = new CorpProfile(corpName, corpEmail);
resp onse = corpProfileService.create(corpProfile);
if (respo nse.getRespo nseCode() == Respo nseCode.RESPONSE_OK) { respo nse.setDescriptio n("創建用戶成功“);
}
result.setDescriptio n("創建成功“);
return result;
}
圖 4.20: 第三方注冊代碼實現
public ResultData profile(Str ing corpName, Stri ng corpEmail, Str ing appld) {
〃參數校驗
if (Stri ngUtils.isEmpty(corpName) && Stri ngUtils.isEmpty(corpEmail) &&
Stri ngUtils.isEmpty(appld)) {
return result;
}
〃數據庫查詢
ResultData resp onse = corpProfileService.fetch(c on diti on);
if (respo nse.getRespo nseCode()!= Resp on seCode.RESPONSE_OK) { result.setRespo nseCode(Respo nseCode.RESPONSE_ERROR); result.setDescription(“查詢失敗,請稍后嘗試“); return result;
}
//返回結果
result.setData(((List) resp on se.getData()).get(O)); return result;
}
圖 4.21: 查詢第三方平臺信息代碼實現
CMAIR
杲麥新風
o數據字典
M統計
B短信系統
0系統管理
%前端管理
■空氣質量
豈用戶行為
數據開放平臺
b平臺信息
圖 4.22: 查詢注冊第三方信息頁面截圖
名和企業郵箱進行查詢,查看已經注冊到系統的第三方平臺的注冊信息。結果 會以時間順序排序。不輸入篩選條件點擊查詢,默認會返回所有結果。
4.5.2 數據開放代碼實現
圖 4.23 展示了數據開放平臺整體上如何實現的邏輯時序圖。從圖中可以看 出,首先在第三方平臺已經注冊并訂閱該設備的條件下,該第三方通過前端發 送操作設備的請求,數據開放模塊在進行參數校驗和權限校驗后將請求發送給 機器控制模塊,由該服務進行對設備具體的操控。當設備正確執行指令之后,將 結果信息返回給機器控制模塊,機器控制模塊再返回給數據開放平臺模塊,最 后再由數據開放模塊返回給前端。這樣做的目的是可以對授權平臺方的請求進 行統一管理,并保證系統安全性。
在使用代碼的具體實現過程中,在對前端傳入的參數:平臺身份標識 appId 和設備的唯一識別碼qrcode進行參數校驗后,后端通過查詢數據庫返回給用戶 是否成功訂閱設備的操作結果。圖 4.24 即是用戶訂閱設備的代碼實現,由于 篇幅限制,只展示出主要的代碼邏輯。所以當用戶再對設備進行調節模式、調 整風量等操作時,會先調用驗證用戶是否訂閱該設備的方法,再調用原有模塊 machineService 中的相應方法進行對設備的控制,大大提高了代碼復用性。
在授權平臺方調用接口訂閱設備后,管理員依然可以對這一關系進行查詢 和管理。圖 4.25 即展示了對應的前端頁面。管理員可以通過傳入企業名或企業 郵箱或者 appId 來查看指定授權平臺方訂閱的設備和訂閱時間。和上文設計相 同,不輸入參數發送請求,默認會返回所有的訂閱信息。
在第三方平臺操作設備調節模式的具體代碼實現中,開放平臺模塊中調用
圖 4.23: 數據開放模塊邏輯時序圖
public ResultData subscribe(String appId, String qrcode) {
ResultData result = new ResultData();
//檢查參數是否為空值
if (StringUtils.isEmpty(appld) || StringUtils.isEmpty(qrcode)) {
}
〃檢查appId的合法性
ResultData response = corpProfileService.fetch(condition);
〃檢查qrcode的合法性
response = machineService.exist(qrcode);
//檢查是否已經訂閱了該設備
response = corpMachineSubsService.fetch(condition);
〃訂閱設備
MachineSubscription machinesubscription = new MachineSubscription(corpId, qrcode);
response = corpMachineSubsService.create(machineSubscription);
return result;
}
圖 4.24: 訂閱設備代碼實現
圖 4.25: 第三方訂閱設備管理頁面截圖
了機器模塊中的方法實現對設備的操控。而通信方式則采用Spring Cloud的自 有組件Feign,來實現所依賴的服務的接口定義。具體的實現方式是只需要在 當前 Openplatform 模塊的邏輯層中,創建一個專門調用機器模塊的各種操作設 備的方法的接口文件,只需要在文件中添加@FeignClient(”machine-agent”)注 解,而”machine-agent”正是Machine模塊在配置文件中給自己起的服務名,這 樣Feign就會根據這個服務名幫助我們找到該服務并調用,使開發更加便捷和優 雅,并且由于Feign中集成了 Ribbon,可以在選擇服務時起到負載均衡的作用。
4.6 本章小結
本章節主要給出了系統的各個模塊的詳細實現。在短信模塊,主要分析了 系統調用第三方服務給用戶發送短信和存儲短信記錄后根據不同條件查詢短信 數據的代碼實現。在支付模塊的實現中,主要介紹了用戶在購物平臺下單后,系 統怎樣與第三方支付平臺進行交互,幫助用戶完成訂單支付。空氣質量模塊介 紹了請求外部數據和對獲取到的城市空氣質量數據整合并查詢的主要邏輯代碼 用戶行為統計模塊介紹了整合用戶操作設備的數據實現,并展示了系統如何對 設備發送的原始數據進行備份并清理,減輕數據庫和服務器壓力。最后,數據開 放平臺模塊展示了第三方平臺如何注冊、訂閱、集成系統內的設備的代碼實現。
第五章 新風設備信息管理子系統測試
這一章首先會對第四章的代碼實現進行單元或者系統的功能測試,測試是 否達到了第三章所提出的需求。然后根據后端代碼的實現方法和不同模塊的業 務場景選擇模塊進行性能測試,并將測試結果進行展示和分析。
5.1 測試環境與思路
5.1.1 測試環境
本文選擇阿里云輕量服務器作為系統的測試環境,首先需要對此環境進行 部署。詳細的測試環境如表 5.1 所示。
表 5.1: 測試環境部署詳情
設備與軟件 詳細
阿里云服務器 輕量應用服務器,1核2GB內存10M帶寬
數據庫 Mysql,MongoDB,Redis
部署軟件 Nginx,JDK1.8,Maven
測試軟件 Postman, JMeter
系統環境 Ubuntu16.04, Android手機并安裝微信7.0.9,新風設備樣機
表 5.2: 服務部署端口配置
服務名稱 端口號
網關 8010
注冊中心 8011
機器控制模塊 8012
定時任務模塊 8013
短信模塊 8014
支付模塊 8015
空氣質量模塊 8016
用戶行為統計模塊 8017
數據開放平臺模塊 8018
所有的服務和數據庫都部署在該服務器上。服務包括網關、服務注冊與發 現中心、定時任務、短信服務、支付服務、空氣質量服務、用戶行為統計服務 數據開放平臺服務,每個服務的端口號如表 5.2 所示。
5.1.2測試思路
本文主要針對系統的兩個方面進行測試:
1.功能測試。首先,將每個微服務都打包成 Jar 包進行部署和啟動,檢測是 否可以正常運行。其次,利用 Postman 等測試工具針對接口測試是否可以 返回預期結果。第三,驗證服務間的調用邏輯,例如在數據開放平臺模塊 對機器控制模塊的調用,檢查邏輯是否正確;最后,模擬用戶的行為在測 試環境上對每個模塊進行端到端的黑盒測試,測試是否完成了第三章所分 析的所有需求。
2.性能測試。首先,分析每個模塊的業務場景,根據情況選擇需要進行性能 測試的模塊。然后,使用 JMeter 測試工具創建不同數量等級的線程測試系 統的穩定性。
5.2 測試過程與結果
本節根據第三章所提出的需求,分模塊依次對該信息管理子系統的功能和 性能兩個方面進行測試。
5.2.1 功能測試
5.2.1.1 短信功能測試
表 5.3: 發送短信功能測試用例
用例編號 1
測試內容 發送短信功能
測試功能 系統給用戶單發和群發短信
測試步驟 1.登錄系統,進入發送短信的頁面;
2.輸入短信正文和手機號;
3.確認發送;
4.輸入短信正文,導入手機號列表文件;
7. 確認發送。
預期結果 1.前端頁面顯示短信已發送成功;
2.目標用戶收到測試短信;
3.前端頁面顯示短信已批量發送成功;
4.目標用戶群體收到測試短信;
如表5.3所示,對發送短信這一功能進行用例測試。測試由Web端發起,對 短信微服務的接口進行調用。包括單發短信和批量發送短信兩種情況,分別傳 入不同的參數發起請求,測試前端頁面能否收到正確的處理結果以及目標用戶 能否能收到短信。
當測試單發短信時,前端發送給短信模塊的參數為“phone: 18811114414, text:這是一條測試短信”后臺收到的返回信息的解析結果為Json格式,具體 內容為”error”:0,”msg”:”ok”。用戶收到短信的效果如圖5.1所示。群發短信的請 求方式和結果類似,不再進行展示。
1069385315452603〉
短信/彩信
今天10:24
【果麥新風】這是一條測試數
據
圖 5.1: 系統給用戶發送短信結果
然后檢測發送短信的行為是否被正確寫入數據庫并可以被查詢。表5.4展示 了對應的測試用例。結果顯示之前的測試數據被正確寫入了數據庫,生成記錄。
表 5.4: 查詢短信記錄功能測試用例
用例編號 2
測試內容 查詢短信記錄功能
測試功能 根據不同的篩選條件查詢短信記錄
測試步驟 1.登錄系統,進入查詢短信外發管理的頁面;
2.選擇篩選條件;
3.確認條件并查詢。
預期結果 1.前端返回符合條件的數據,并且按照時間順序的倒序排序。
綜上,短信模塊可以實現給指定用戶單發或群發短信的功能,并將記錄正 確寫入數據庫,同時提供管理員對短信記錄進行管理的能力,功能上滿足對此 模塊的預定需求。
5.2.1.2支付功能測試
如表5.5所示,對支付功能進行用例測試。首先在企業的微信小程序購物商 城中進行商品選擇并提交訂單,進行支付,測試是否可以完成正常的交易流程 而后驗證系統后臺收到的交易數據是否與支付結果相一致,是否保證了數據一 致。然后,再由前端發起對該筆訂單狀態查詢的請求,測試是否可以查詢到訂單 的狀態變化,確保產生交易記錄。
經上述流程后,用戶表現為可以通過第三方支付平臺支付訂單,系統也可 以接收到第三方平臺返回的支付結果并正確存儲交易快照,查詢數據庫驗證數 據保持一致,滿足預定需求。
表5.5: 支付功能測試用例
用例編號 3
測試內容 支付訂單功能
測試功能 在微信小程序端下單支付,完成交易
測試步驟 1.進入微信小程序購買商品生成訂單;
2.使用微信支付平臺支付訂單;
3.查詢訂單記錄,核對交易數據。
預期結果 1.微信小程序端顯示支付完成;
2.后臺正常生成交易快照,并且數據正確;
3.查詢結果與小程序端實際支付結果相一致。
5.2.1.3 獲取城市空氣質量數據功能測試
如表5.6所示,測試由微信公眾號端觸發,請求最新的室外空氣質量數據和 整合后的一周內空氣質量數據。查看是否可以返回結果并且數據是否是由定時 任務獲取到的數據庫最新數據。
表 5.6: 獲取城市空氣質量數據用例
用例編號 4
測試內容 獲取城市空氣質量功能
測試功能 系統獲取國內城市空氣質量數據
測試步驟 1.用戶進入企業公眾號頁面并登錄;
2.選擇想要查看的設備;
3.查看當前室內外空氣質量數據;
4.管理員登錄管理系統,找到空氣質量頁面;
5.選擇城市和日期進行查詢;
4. 查詢“墨跡赤必”官網,核對查看到的是否為最新數據。
預期結果 1.公眾號頁面正常展示最新室內外空氣質量數據;
2.公眾號頁面查看到的數據與“墨跡赤必”網站顯示的數據一致。
3.Web頁面查看到的數據與“墨跡赤必”網站顯示的數據一致。
綜上,系統可以正確獲取到第三方服務所提供的全國城市的空氣質量數據 并提供給前端,并且對數據進行了正確的整合,滿足預定要求。
5.2.1.4 用戶行為數據統計功能測試
如表5.7所示,對所有操作設備的行為信息的整合進行用例測試。后端單元 測試由Postman發起,通過Http請求調用接口;系統級測試由Web端發起,請 求查看用戶的行為信息。表中展示了后端的單元測試部分。
Postman發送的參數包括某臺設備的編號、組件名稱和時間范圍等等,后臺 首先需要驗證系統是否可以正常返回結果,然后人工驗證統計到的數據是否是 原始數據相一致。結果顯示系統已經對用戶行為源數據進行了正確的整合,滿
表 5.7: 用戶行為數據統計測試用例
用例編號 5
測試內容 查詢用戶行為信息
測試功能 用戶行為數據進行整合并提供管理接口
測試步驟 1.使用Postman調用接口,傳入不同參數發送請求;
2.手動驗證統計數據與原始數據是否一致。
預期結果 1.正常返回統計結果;
2.結果正確,與原始數據保持一致。
足預定要求。
5.2.1.5 數據開放功能測試
如表5.8所示,對數據開放功能進行用例測試。測試由Postman發起,通過 傳入授權平臺方的標識appId和設備的唯一標識符qrcode來測試是否可以訂閱 設備和操作設備。根據不同的操作指令,測試控制系統后臺的接收情況,并測試 設備是否按照接收到的指令正確執行。
表 5.8: 數據開放測試用例
用例編號 6
測試內容 數據開放功能
測試功能 Postman發送訂閱設備,操縱設備的不同指令,后臺接收并發送對 應的報文給設備,設備執行對應的指令。
測試步驟 1.使用 Postman 調用接口,發送 appId 和 qrcode 訂閱設備;
2.使用 Postman 調用接口,開機;
3.使用Postman調用接口,修改風量;
4.使用 Postman 調用接口,修改輔熱;
5.使用Postman調用接口,修改模式;
6.使用Postman調用接口,修改童鎖;
7.使用Postman調用接口,查詢該平臺已訂閱的設備;
預期結果 1.Postman返回執行成功的操作結果;
2.指定設備按照指令執行相應操作。
當查詢平臺所有訂閱設備時,使用Postman請求接口為“/openplatform/ma- chine/subscriptions?appid=GMA20190528752le88"的地址,可以看到返回 Json 格 式數據的請求結果,如圖 5.2 所示。
其他的指令請求由于篇幅限制不進行展示。由測試結果展示出,在平臺訂閱 設備后可以對設備進行操作,具有了和用戶相同權限。滿足對此功能的預定需求。
{
"responseCode": "RESPONSE_OK", "data": [
{
"qrcode": "42A112B674869", "createAt": 1559530206000 }, {
"qrcode": "42A112B961320", "createAt": 1583137847000 }
],
"description": null
}
圖 5.2: 查詢授權平臺方已訂閱的設備結果
5.2.2性能測試
由于本文中的短信模塊、用戶行為統計模塊由管理員進行調用,空氣質量 模塊由定時引擎觸發,間隔執行,并不會發生高并發的訪問請求。而支付模塊 在類似“雙十一”等購物節時某一時刻可能會發生高并發訪問。而數據開放平臺 也有這樣的可能,因此,本章將對這兩個模塊進行性能測試以衡量整個子系統 的性能。
本文主要使用 JMeter 作為性能測試的工具。創建不同數量的測試線程組和 對應數量的 JMeter 元組,再創建結果搜索元組,以監控指標數據[39]。
對于支付模塊,先后比較了 1至1000不同數量等級的線程在30秒內發生 支付行為時,服務器的CPU、內存的使用和系統相應時間。表5.9展示了測試結 果。
表 5.9: 支付模塊性能測試服務器表現
線程數 CPU (%) 內存(%) 平均響應時間(ms)
1 43 49.8 11
20 44 49.9 23
50 45 50.1 36
100 49 50.2 49
200 52 50.6 112
500 53 50.6 282
1000 56 50.8 423
從表中的測試結果可以看出,在并發數增加的同時,CPU和內存的使用也 會上升,但對比來看增加的速率較慢,可以滿足目前的業務量,在高并發場景下 不會產生系統異常的情況。
對于數據開放平臺模塊,也使用類似的方法進行測試。表5.10展示出了對 應的測試結果。從結果看出,在高并發狀態下,服務器雖然響應速度下降但依然
可以正確處理請求,并且在結束后沒有發生內存溢出等情況。
表 5.10: 數據開放模塊性能測試服務器表現
線程數 CPU (%) 內存(%) 平均響應時間(ms)
1 43 49.2 13
20 46 50.0 23
50 47 50.0 30
100 49 50.1 42
200 54 50.3 123
500 56 50.6 301
1000 58 50.8 419
綜上,本文所設計和實現的信息管理子系統在高并發場景下服務器可以快 速相應,在性能上可以滿足當前業務場景的用戶需要。
5.3 本章小結
本章根據第三章的需求分析,對短信模塊、支付模塊和空氣質量模塊、用戶 行為統計模塊和數據開放平臺模塊的主要功能進行了測試,并模擬高并發場景 對支付模塊和數據開放平臺模塊進行了性能測試。并對測試結果進行了展示和 分析。從結果來看,每個模塊都已經滿足了第三章所提出的功能需求,并且系統 整體上具有一定的穩定性,可以滿足目前的業務場景和用戶需要。
第六章 總結與展望
6.1 總結
本文基于智能家居和移動互聯的技術背景,從公司的新風設備的產品理念 和目標出發,基于提升用戶體驗、擴大產品市場、提高企業信息化管理程度的目 的,構建了一個基于微服務的新風設備信息管理子系統。本文的主要工作如下:
1.對于本文的項目背景和技術背景進行了介紹,針對本文主要使用的幾項技 術進行了展開。本文采用前后端分離的整體架構,后端基于 Spring Cloud 和Spring Boot構建微服務框架,搭建服務集群。使用MyBatis作為后端與 數據庫進行交互的中間件。在數據庫的選擇上,使用MySQL、MongoDB、 Redis,基于數據庫的不同特點在不同場景下使用。
2.本文從垂直維度分別對短信模塊、支付模塊、空氣質量模塊、用戶行為統 計模塊和數據開放平臺模塊進行了需求分析和概要設計。通過圖表清晰的 展示了設計的背景和思路。并且對每個模塊進行了數據庫設計,給出了具 體的數據表結構。
3.根據需求和設計完成了代碼開發,并將主要的實現邏輯和成果進行展示 管理員可以利用短信微服務,通過系統給任意用戶單發或批量發送短信 用戶也可以給系統進行回復,同時系統也提供了查詢所有發送和回復短信 記錄的功能;用戶在微信小程序內企業店鋪選擇商品下單后,系統可以和 微信支付平臺進行正確的交互,使用戶實現商品購買;系統可以調用第三 方服務獲取到最新的城市空氣質量數據并發送給前端進行展示;管理員可 以查詢到指定用戶的整合后的行為統計數據,進行針對性的銷售、服務或 產品研發;第三方平臺可以通過注冊集成系統內的設備,對指定設備進行 訂閱和操控。
4.對上述詳細的代碼實現分別進行了功能測試和性能測試,給出了具體的用 例描述和測試結果。通過測試結果可以看出,均滿足了預期的需求。
綜上所述,本文所設計的信息管理子系統已經實現。對比原有的信息管理 系統,該子系統的部署拓展了產品的銷售渠道,使用戶在使用產品的過程中獲 得了更好的用戶體驗,提高了系統管理員對管理信息的工作效率,使產品可以 加入第三方平臺生態鏈,開拓了產品市場,從多個角度提升了產品的市場競爭 力。
6.2工作展望
該新風設備信息管理子系統雖然已經實現短信、支付、獲取空氣數據等新 功能,但在此基礎上,還可以從以下三個方面來進行繼續開發和優化。
首先,在支付模塊,目前系統已經實現了基本數據結構和模塊結構的搭建 并且部署上線了微信支付的付款渠道,但基于業務層面,還需要繼續拓展其他 新的支付平臺,例如支付寶支付、京東支付等等,支撐業務拓展,提升購買環節 的用戶體驗。
其次,系統已經收集到關于短信、支付、空氣質量、用戶行為等方面的大量 數據,但是目前只是處于整合和統計層面,并沒有進行更深入的分析和挖掘,找 出內部的潛在規則。例如結合空氣質量數據和用戶行為數據,可以利用關聯規 則算法分析室外空氣質量對于用戶使用新風設備的影響,或者結合短信數據和 用戶行為數據,分析用戶收到短信后是否接納了短信內容中的建議,探索短信 營銷對影響用戶行為的程度等等。如何更有針對性的優化產品或服務,讓用戶 感受到更舒適的使用體驗是始終需要考慮的。
最后,對于該子系統中的短信模塊和空氣質量模塊,在實現功能上都調用 了第三方服務,這就需要考慮當第三方服務不可用時,系統應如果進行應急處 理,即在整體上提高系統可靠性。
因此,該系統還需要進行持續開發,提高系統性能,支撐業務拓展,提升產 品競爭力。
參考文獻
[1]Z. Z. S. Y. Weiyang Zeng, Yining Jin, The current condition and developing tendency of mobile communication interconnection technology, Materials Science and Engineering 466 (1).
[2]M. D.-R. Patricia Baudier, Chantal Ammi, Smart home: Highly-educated students' acceptance, Technological Forecasting:Social Change (2020) 153.
[3]張美平,吳德平,王燦杰,謝瑋銘, 基于樹莓派的智能家居設計與實現, 計 算機系統應用 28 (08) (2019) 109-114.
[4]王琳,肖軍,劉洲洲,基于nb-iot的智能家居系統的構建,計算機技術與發 展 30 (03) (2020) 194-197.
[5]S. K. Areum Hong, Changi Nam, What will be the possible barriers to consumers' adoption of smart home services?, Telecommunications Policy 44 (2).
[6]鄭夢蘭, 智能家居上市公司經營績效分析——基于因子分析, 湖北經濟學院 學報(人文社會科學版) 16 (10) (2019) 56-58.
[7]吳佳興,李愛國, 基于云計算的智能家居系統, 計算機應用與軟件30(07) (2013) 240-243+314.
[8]陸興華,林佳聰,謝欣殷,林家豪, 基于大數據的物聯網用戶行為模式挖掘, 計算機技術與發展29(12)(2019)99-103.
[9]鐘陳星,李杉杉,張賀,章程, 限界上下文視角下的微服務粒度評估, 軟件 學報 30 (10) (2019) 3227-3241.
[10]A. G. Roberto Pietrantuono, Stefano Russo, Testing microservice architectures for operational reliability, Software Testing:Verification and Reliability 30 (2).
[11]趙昱,基于servicecomb的多語言微服務平臺,計算機系統應用29 (04) (2020) 84-91.
[12]吳化堯,鄧文俊, 面向微服務軟件開發方法研究進展, 計算機研究與發展 57 (3) (2020) 525-541.
[13] 李春陽,劉迪,崔蔚, 基于微服務架構的統一應用開發平臺, 計算機系統應 用 26 (04)(2017) 45—50.
[14]K. P. Birman, Like it or not, web services are distributed objects, Communications of the ACM.
[15]吳俠,艾芳菊, 基于微服務架構的眾籌系統, 湖北大學學報(自然科學版) 42 (01) (2020) 103-108.
[16]胡啟敏,薛錦云,鐘林輝,基于spring框架的輕量級j2ee架構與應用,計算 機工程與應用 5 (2008) 115-118+133.
[17]符培炯,杜忠軍,Spring在實現mvc構架中的應用,計算機技術與發展6 (2006) 236-238+241.
[18]肖文娟,王加勝,基于vue和spring boot的校園記錄管理web app的設計與 實現,計算機應用與軟件37 (04) (2020) 25-30+88.
[19]葉為正,林聲肯,黃立軒,許志明,李晶,即時通訊系統的設計與實現,計 算機技術與發展20(02)(2020)216-220.
[20]趙子晨,朱志祥,蔣來好, 構建基于 dubbo 框架的 spring boot 微服務, 計算 機與數字工程46 (12) (2018) 2539-2543+2551.
[21]張宇,王映輝,張翔南,基于spring的mvc框架設計與實現,計算機工程 36 (04) (2010,36(04)) 59-62.
[22]馮志勇,徐硯偉,薛霄,陳世展, 微服務技術發展的現狀與展望, 計算機研 究與發展 57 (05) (2020) 1103-1122.
[23]張杰,滿曙光,劉凱,周立軍, 采用消息隊列實現數據一致性方法, 計算機 系統應用 28(09)(2019)185-189.
[24]苗京,李圓媛,余幼宇,應用數據詞典構造基于web結構的數據庫中間件, 計算機系統應用 (2004) 60-62.
[25]劉杰,孫浩,郭東旭,吳雨洽,基于spring mvc及mybatis框架的在線教育 平臺的設計與實現,沈陽師范大學學報(自然科學版) 37 (03) 268-273.
[26]陳鍛生,吳揚揚,利用api建造web數據庫系統的中間件技術,計算機應用 4 (1999) 17-20.
[27]翟雅榮,于金剛,基于filebeat自動收集kubernetes日志的分析系統,計算機 系統應用 27(09)(2018)81-86.
[28]胡鑫,姚宇,徐英杰, 基于 elasticsearch 的 tee 病例庫檢索系統設計與實現, 計算機應用 38(S1)(2018)91-94.
[29]黃裕,基于分布式redis集群的web共享管理研究,計算機與數字工程46 (10) (2018) 2078-2082+2130.
[30]黎勇,崔哲,余少劍, 內存數據庫在超寬帶實時定位系統中應用, 計算機應 用 34 (S2) (2014) 48-51.
[31]李瑾,顧敏皓,李飛,朱科軍,高能物理分布式數據獲取架構的設計與實現, 計算機工程與應用 55 (19) (2019) 228-234.
[32]梁海,Mongodb數據庫中sharding技術應用研究,計算機技術與發展24 (07) (2014) 60-62+67.
[33]陳敬靜,馬明棟,王得玉,Mongodb負載均衡算法優化研究[j/ol],計算機技 術與發展(2020)1-9.
[34]張晶,王琰潔,黃小鋒, 一種微服務框架的實現, 計算機系統應用 26 (04) (2017) 82-86.
[35]栗永勝,崔佳冬,秦會斌,一種自適應心跳間隔保活tcp連接的方法,計算機 應用與軟件35(01)(2018)149-153.
[36]Z. L.-M. Y. J. W. P. C. H. Q. T. Bobo Huang, Li Jin, Rdma-driven mongodb: An approach of rdma enhanced nosql paradigm for large-scale data processing, Information Sciences (2019) 502.
[37]J. B.L. C. G. V. S. P. M. P. F. M.-S. A. M.-C. Miguel Ramos, Ricardo Sanchez- de-Madariaga, An archetype query language interpreter into mongodb: Managing nosql standardized electronic health record extracts systems, Journal of Biomedical Informatics (2020) 101.
[38]張健,劉青昆,王異奇,周嬌,Linux實時化方法的研究與實現,計算機工程 37(11)(2011)253-256.
[39]陳建海,陳淼,浦云明,基于微服務架構b/s系統的性能分析,計算機系統應 用 29 (02) (2020) 233-237.