返回文章列表

物聯網應用程式系統效能監控設計與實作

本文探討物聯網應用程式中系統效能監控的設計與實作,涵蓋受限裝置應用程式(CDA)和閘道器裝置應用程式(GDA)的開發。文章首先介紹了軟體設計的關鍵原則:模組化、介面和驗證,並將這些原則應用於系統效能管理器的設計中。接著,文章詳細說明瞭如何在CDA中實作系統效能監控功能,包括CPU和記憶體使用率的收集,並使用APSche

物聯網 軟體設計

在物聯網專案開發中,系統效能監控是確保應用程式穩定性和效率的關鍵環節。本文將探討如何在受限裝置應用程式(CDA)和閘道器裝置應用程式(GDA)中設計和實作系統效能監控功能。首先,我們回顧了軟體設計的三大原則:模組化、介面設計和驗證,這些原則指導我們構建了系統效能管理器。接著,我們逐步展示瞭如何在CDA中實作系統效能監控,包括使用psutil函式庫取得CPU和記憶體使用率,並利用APScheduler實作定時資料採集。此外,我們還闡述瞭如何將這些資料整合到SystemPerformanceManager中,以便統一管理和處理。最後,我們簡要介紹了GDA的系統效能管理元件設計,並強調了其在資料傳輸和雲端整合方面的重要性。

軟體設計概念與初始應用程式開發

在前一章中,我們簡要介紹了物聯網(IoT)專案的整體架構與目標。現在,讓我們進一步探討軟體設計的核心概念,並開始構建初始的邊緣層應用程式。

設計原則

首先,回顧一下第一章中的問題陳述: 「我想了解家中的環境,它如何隨著時間變化,並進行調整以提高舒適度同時節省資金。」

為瞭解決這個問題,我們的應用程式需要具備一些重要的功能。同時,考慮到測試系統行為和效能的重要性,我們需要在設計初期就考慮到以下三個關鍵的設計原則:

  1. 模組化:建立執行特定任務(或相關任務)的軟體元件。模組化背後的概念是關注點分離(Separation of Concerns),這是電腦科學和應用程式設計中常用的術語,用於定義系統的架構方式。簡單來說,就是建立具有特定功能的軟體模組,避免過度複雜化。

  2. 介面:定義良好的介面或契約可以使軟體設計既優雅又高效。糟糕的介面設計則可能導致系統當機。介面提供了與模組互動的規則,並為系統的行為提供了一定的規範。

  3. 驗證:驗證是測試系統品質的一部分,包括檢查和平衡,以強制系統內部的一定行為,例如正常運作條件,排除可能引起問題的條件。例如,一個測試可能允許廣泛的值範圍,但如果該測試是針對家庭供暖系統的抽象,則更合理的最大值應該要低得多。系統必須足夠智慧以處理這種情況並採取相應的行動(例如,丟棄該值並記錄警告或錯誤訊息)。

這些設計原則將在本章中開始體現,因為我們將探討CDA(Constrained Device Application)和GDA(Gateway Device Application)的第一組練習。

追蹤需求

為了有效管理專案,我們需要追蹤即將實作的需求。有許多方法可以做到這一點,包括使用GitHub內建的問題追蹤器,或是建立一個單獨的儲存函式庫來追蹤跨CDA和GDA的需求。

程式設計練習

現在,讓我們開始進行程式設計練習。在這些練習中,我們將探討系統效能的需求,並將此功能新增到CDA和GDA中。

系統效能是系統驗證的一部分,它允許我們追蹤每個IoT應用程式執行時所使用的記憶體、CPU和磁碟儲存空間。此外,這個功能的設計將開始實踐模組化和介面定義的原則。

系統效能管理器設計

圖2-2和圖2-3展示了CDA和GDA的系統效能管理器設計。這些設計與圖1-15和1-16所示的設計略有不同。在第三章中,我們將對此進行「修正」,這意味著在本章中引入了一小部分的技術債(technical debt)。這樣做的目的是為了教育目的,幫助你快速建立並獲得一些功能性的程式碼。

# 以下是一個簡化的範例,展示如何實作系統效能管理器
import psutil

class SystemPerformanceManager:
    def __init__(self):
        pass
    
    def get_memory_usage(self):
        return psutil.virtual_memory().percent
    
    def get_cpu_usage(self):
        return psutil.cpu_percent(interval=1)

# 使用範例
if __name__ == "__main__":
    spm = SystemPerformanceManager()
    print(f"Memory Usage: {spm.get_memory_usage()}%")
    print(f"CPU Usage: {spm.get_cpu_usage()}%")

內容解密:

  1. 我們定義了一個名為SystemPerformanceManager的類別,用於管理系統效能。
  2. get_memory_usage方法使用psutil.virtual_memory().percent來取得記憶體使用率。
  3. get_cpu_usage方法使用psutil.cpu_percent(interval=1)來取得CPU使用率。這裡的interval=1表示每隔1秒測量一次CPU使用率。
  4. if __name__ == "__main__":區塊中,我們建立了一個SystemPerformanceManager例項,並列印出記憶體和CPU的使用率。

透過遵循這些原則和實踐,我們可以為CDA和GDA新增更多的功能,並確保系統的可擴充套件性和可維護性。

建構初始邊緣層應用程式:受限裝置應用程式的系統效能管理

在開始撰寫程式碼之前,值得注意的是,本章節中對於受限裝置應用程式(Constrained Device Application, CDA)和閘道器裝置應用程式(Gateway Device Application, GDA)的初始設計將會非常相似。它們將會收集一些基本的遙測資料,目前包括 CPU 使用率和記憶體使用率,並簡單地將這些資料記錄到控制檯。

將系統效能任務新增到受限裝置應用程式

首先,檢視第二章節中對於 CDA 的需求。每個需求都以「PIOT-CDA-02」開頭。注意到「PIOT-CDA-02-000」指示您為本章節建立一個新的分支,而後續的需求則指示您建立(或更準確地說,編輯)與本章節任務相關的模組。

ConstrainedDeviceApp 是應用程式的入口點,它建立了 SystemPerformanceManager 的例項並對其進行管理。此外,還有兩個其他效能任務元件:SystemCpuUtilTaskSystemMemUtilTask。顧名思義,這些元件將會收集系統 CPU 使用率和系統記憶體使用率。它們將由 SystemPerformanceManager 管理,並作為非同步執行緒執行,更新您在 SystemPerformanceManager 中定義的方法。

檢視受限裝置應用程式模組

首先,從 Programming the IoT 專案中檢視「PIOT-CDA-02-001」需求活動。主要步驟包括:

  • programmingtheiot\cda 源資料夾中建立一個名為 app 的 Python 套件,並導航到該資料夾。
  • 匯入 Python 的 logging 模組:import logging
  • 建立一個名為 ConstrainedDeviceApp 的 Python 模組,並在其中定義一個同名的類別 ConstrainedDeviceApp
  • 新增 startApp() 方法,並記錄一條資訊訊息,指示應用程式已啟動。
  • 新增 stopApp() 方法,並記錄一條資訊訊息,指示應用程式已停止。
def main():
    cda = ConstrainedDeviceApp()
    cda.startApp()
    while True:
        sleep(60)  # 1 分鐘,或者您可以選擇 2 分鐘(120 秒)
    cda.stopApp()

if __name__ == '__main__':
    main()

測試您的實作

執行 ConstrainedDeviceAppTest 單元測試。日誌輸出應該與以下內容類別似:

2020-07-20 10:08:20,169:INFO:Initializing CDA...
2020-07-20 10:08:20,169:INFO:Loading configuration...
2020-07-20 10:08:20,169:INFO:Starting CDA...
2020-07-20 10:08:20,169:INFO:CDA started.
2020-07-20 10:08:20,169:INFO:CDA stopping...
2020-07-20 10:08:20,170:INFO:CDA stopped with exit code 0.
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
---
Ran 1 test in 0.001s
OK

建立和整合系統效能管理器模組

下一個需求是建立(或者說,更新)SystemPerformanceManager 類別。如「PIOT-CDA-02-002」所述,這個需求指示您建立一個名為 SystemPerformanceManager 的 Python 模組,其中包含同名的類別。

這個元件將位於 cda 套件下的 system 資料夾中。主要活動涉及兩個簡單的任務:在 startManager() 中新增一條日誌訊息,指示管理器已啟動;以及在 stopManager() 中新增另一條日誌訊息,指示管理器已停止。

將 SystemPerformanceManager 整合到 CDA 中

檢視「PIOT-CDA-02-003」卡片中的動作,以將此模組整合到您的 CDA 中。主要步驟包括:

  • ConstrainedDeviceApp 建構函式中建立一個類別範圍的 SystemPerformanceManager 例項,名為 sysPerfManager
self.sysPerfManager = SystemPerformanceManager()
  • 編輯 startApp() 方法,以包含對 self.sysPerfManager.startManager() 的呼叫。

#### 程式碼解析:
此段程式碼建立了 SystemPerformanceManager 的例項並在適當的時候啟動它
1. **self.sysPerfManager = SystemPerformanceManager()**這行程式碼在 ConstrainedDeviceApp 類別中建立了一個名為 sysPerfManager 的屬性並將其初始化為 SystemPerformanceManager 的例項這使得 CDA 能夠管理和控制系統效能監測的功能
2. **編輯 startApp() 方法**在 startApp() 方法中呼叫 self.sysPerfManager.startManager()確保當 CDA 啟動時SystemPerformanceManager 也會跟著啟動開始監測系統效能

透過這些步驟,受限裝置應用程式開始具備收集系統效能資料的能力,並為後續的遙測資料生成奠定了基礎。

系統效能監測模組開發

介紹

本章節將指導如何開發系統效能監測模組,包括建立SystemPerformanceManagerBaseSystemUtilTaskSystemCpuUtilTaskSystemMemUtilTask等模組,以實作對系統CPU和記憶體使用率的監測。

修改ConstrainedDeviceApp類別

首先,需要修改ConstrainedDeviceApp類別中的startApp()stopApp()方法,以呼叫SystemPerformanceManager的啟動和停止方法。

def startApp(self):
    # ... 其他程式碼 ...
    self.sysPerfManager.startManager()

def stopApp(self):
    # ... 其他程式碼 ...
    self.sysPerfManager.stopManager()

內容解密:

  • startApp()stopApp()方法分別用於啟動和停止應用程式。
  • 呼叫self.sysPerfManager.startManager()啟動系統效能管理。
  • 呼叫self.sysPerfManager.stopManager()停止系統效能管理。

建立基礎系統工具任務類別

根據PIOT-CDA-02-004的描述,建立BaseSystemUtilTask類別作為基礎系統工具任務的抽象類別。

class BaseSystemUtilTask:
    def __init__(self, name, typeID):
        self.name = name
        self.typeID = typeID

    def getName(self):
        return self.name

    def getTypeID(self):
        return self.typeID

    def getTelemetryValue(self) -> float:
        # 這個方法需要在子類別中實作
        pass

內容解密:

  • __init__方法初始化物件,接受nametypeID兩個引數。
  • getName()getTypeID()方法分別傳回物件的名稱和型別ID。
  • getTelemetryValue()方法是一個範本方法,需要在子類別中實作具體的遙測資料取得邏輯。

建立CPU利用率監測任務類別

建立SystemCpuUtilTask類別,繼承自BaseSystemUtilTask,用於監測系統CPU利用率。

import psutil

class SystemCpuUtilTask(BaseSystemUtilTask):
    def __init__(self):
        super(SystemCpuUtilTask, self).__init__(
            name=ConfigConst.CPU_UTIL_NAME,
            typeID=ConfigConst.CPU_UTIL_TYPE
        )

    def getTelemetryValue(self) -> float:
        return psutil.cpu_percent()

內容解密:

  • 使用psutil函式庫取得系統CPU利用率。
  • getTelemetryValue()方法傳回當前CPU利用率的百分比。

建立記憶體利用率監測任務類別

建立SystemMemUtilTask類別,同樣繼承自BaseSystemUtilTask,用於監測系統記憶體利用率。

class SystemMemUtilTask(BaseSystemUtilTask):
    def __init__(self):
        super(SystemMemUtilTask, self).__init__(
            name=ConfigConst.MEM_UTIL_NAME,
            typeID=ConfigConst.MEM_UTIL_TYPE
        )

    def getTelemetryValue(self) -> float:
        return psutil.virtual_memory().percent

內容解密:

  • 使用psutil.virtual_memory().percent取得系統記憶體利用率的百分比。
  • getTelemetryValue()方法傳回當前記憶體利用率的百分比。

連線監測任務到系統效能管理器

將建立的SystemCpuUtilTaskSystemMemUtilTask連線到SystemPerformanceManager,以實作對系統效能的監測。

使用APScheduler進行排程

使用APScheduler函式庫來實作對監測任務的排程執行,以定期取得系統效能資料。

from apscheduler.schedulers.background import BackgroundScheduler

def main():
    scheduler = BackgroundScheduler()
    # 新增任務到排程器
    scheduler.start()

if __name__ == "__main__":
    main()

內容解密:

  • 使用BackgroundScheduler來建立一個背景排程器。
  • 可以透過排程器新增任務,以定期執行系統效能監測任務。

系統效能管理元件整合與實作

在物聯網(IoT)系統中,裝置的效能監控至關重要。本章節將介紹如何在受限裝置應用程式(CDA)中整合系統效能管理元件,並進一步擴充套件至閘道器裝置應用程式(GDA)。

CDA系統效能管理元件實作

CDA的系統效能管理元件主要負責監控系統的CPU和記憶體使用率。以下為實作步驟:

1. 初始化系統效能管理器

首先,需要更新SystemPerformanceManager類別的建構子,以初始化所需的元件,包括CPU使用率任務、記憶體使用率任務和排程器。

import logging
from apscheduler.schedulers.background import BackgroundScheduler
from programmingtheiot.common.IDataMessageListener import IDataMessageListener
from programmingtheiot.cda.system.SystemCpuUtilTask import SystemCpuUtilTask
from programmingtheiot.cda.system.SystemMemUtilTask import SystemMemUtilTask
from programmingtheiot.data.SystemPerformanceData import SystemPerformanceData

class SystemPerformanceManager(object):
    def __init__(self):
        configUtil = ConfigUtil()
        self.pollRate = configUtil.getInteger(
            section=ConfigConst.CONSTRAINED_DEVICE,
            key=ConfigConst.POLL_CYCLES_KEY,
            defaultVal=ConfigConst.DEFAULT_POLL_CYCLES)
        # 初始化其他必要的屬性
        self.scheduler = BackgroundScheduler()
        self.cpuUtilTask = SystemCpuUtilTask()
        self.memUtilTask = SystemMemUtilTask()
        # 設定排程器任務
        self.scheduler.add_job('self.handleTelemetry', 'interval', seconds=self.pollRate)

2. 實作系統效能資料處理

handleTelemetry方法負責處理系統效能資料,包括讀取CPU和記憶體使用率,並記錄日誌。

def handleTelemetry(self):
    cpuUtil = self.cpuUtilTask.getSystemCpuUtil()
    memUtil = self.memUtilTask.getSystemMemUtil()
    logging.info(f"CPU utilization is {cpuUtil} percent, and memory utilization is {memUtil} percent.")

3. 啟動和停止系統效能管理器

需要實作startManagerstopManager方法,以控制排程器的啟動和停止。

def startManager(self):
    logging.info("Started SystemPerformanceManager.")
    if not self.scheduler.running:
        self.scheduler.start()

def stopManager(self):
    logging.info("Stopped SystemPerformanceManager.")
    try:
        self.scheduler.shutdown()
    except:
        logging.warning("SystemPerformanceManager scheduler already stopped. Ignoring.")

GDA系統效能管理元件設計

GDA的系統效能管理元件設計與CDA類別似,但GDA將負責處理來自CDA的資料,並將其傳送至雲端進行進一步處理。

GDA系統效能設計UML圖

此圖展示了GDA的系統效能設計詳細資訊。

關鍵技術與考量

  1. 排程器使用:本實作使用了APScheduler函式庫來實作排程任務,這使得系統效能資料的收集變得更加靈活和可控。
  2. 組態檔案使用:透過ConfigUtil類別,可以從組態檔案中讀取必要的引數,如輪詢率等,這提高了程式的靈活性。
  3. 模組化設計:系統效能管理元件被設計為獨立的模組,這使得未來擴充套件和維護變得更加容易。