Heim  >  Artikel  >  Backend-Entwicklung  >  So implementieren Sie die Prozessüberwachung in Golang

So implementieren Sie die Prozessüberwachung in Golang

PHPz
PHPzOriginal
2023-04-24 09:10:261861Durchsuche

In der Entwicklung sowie im Betrieb und in der Wartung müssen wir häufig Prozesse überwachen, um sicherzustellen, dass sie normal ablaufen und Probleme rechtzeitig erkannt und behoben werden können, wenn sie auftreten. In diesem Artikel stellen wir Ihnen die Verwendung der Go-Sprache zur Implementierung der Prozessüberwachung vor und helfen Ihnen, die Überwachungstechnologie besser zu verstehen und anzuwenden.

1. Grundprinzipien der Prozessüberwachung

Prozessüberwachung bezieht sich hauptsächlich auf eine Technologie zur Überwachung, Steuerung und Ausnahmebehandlung des laufenden Status von Anwendungen. Laienhaft ausgedrückt bedeutet dies, bestimmte Überwachungsmethoden zu verwenden, um den Laufstatus des Programms in Echtzeit zu überwachen und gleichzeitig sicherzustellen, dass das Programm normal ausgeführt wird und Fehler rechtzeitig behandeln kann.

Bei der Prozessüberwachung ist der Heartbeat-Mechanismus die am häufigsten verwendete Überwachungsmethode. Der sogenannte Heartbeat-Mechanismus besteht darin, während der Ausführung des Programms kontinuierlich Nachrichten nach außen zu senden, um seinen normalen Betriebsstatus anzuzeigen. Und wir bestimmen, ob das Programm fehlerfrei ist, indem wir diese Nachrichten erfassen und analysieren. Sobald eine Programmanomalie entdeckt wird, wird diese entsprechend verarbeitet, um den normalen Betrieb des Systems sicherzustellen.

2. Die Implementierungsidee der Prozessüberwachung in Golang

In der Go-Sprache können wir einige vorgefertigte Pakete verwenden, um die Prozessüberwachung zu implementieren. Die spezifischen Implementierungsschritte sind wie folgt:

1. Alle Prozessinformationen abrufen

Wir können das Prozesspaket im psutil-Paket verwenden, um relevante Informationen über alle Prozesse im System abzurufen. Zuerst müssen wir das Paket einführen:

import (
    "github.com/shirou/gopsutil/process"
)

Dann rufen Sie alle Prozesse im System ab, indem Sie die Funktion „process.Processes()“ aufrufen:

processes, err := process.Processes()
if err != nil {
    log.Fatalf("failed to get all processes: %v", err)
}

Diese Funktion gibt einen Prozessabschnitt zurück, von dem jedes Element ein Prozess ist, der einen Prozess enthält Informationsstruktur. Informationen zu bestimmten Strukturen finden Sie in der offiziellen Dokumentation von psutil.

2. Filtern Sie die Prozesse, die überwacht werden müssen

Um einen bestimmten Prozess zu überwachen, müssen wir unter allen Prozessen den Prozess finden, an dem wir interessiert sind, und seine PIDs aufzeichnen. Hier können wir einige bedingte Filter verwenden, um schnell die Prozesse herauszufiltern, die überwacht werden müssen. Beispielsweise können wir die benötigten Prozesse anhand des Prozessnamens, der Prozess-ID und anderer Bedingungen herausfiltern. Am Beispiel des Prozessnamens lautet der Code wie folgt:

targetProcessName := "myApp"
targetPidList := make([]int32, 0)

for _, proc := range processes {
    name, err := proc.Name()
    if err != nil || name != targetProcessName {
        continue
    }
    pid := proc.Pid
    targetPidList = append(targetPidList, pid)
    log.Printf("find target process %s, pid = %d\n", name, pid)
}

3. Führen Sie eine Heartbeat-Erkennung für den Prozess durch, der überwacht werden muss.

Für den Prozess, der überwacht werden muss, können wir feststellen, ob er normal ausgeführt wird Senden einer Heartbeat-Nachricht an ihn. Insbesondere können wir ein Urteil fällen, indem wir die CPU- und Speicherauslastung ablesen. Wenn Sie eine abnormale CPU- und Speicherauslastung feststellen, liegt möglicherweise ein Problem mit dem Prozess vor.

Um die Heartbeat-Erkennung zu implementieren, können wir eine Goroutine verwenden, um den Status des angegebenen Prozesses regelmäßig zu lesen und aufzuzeichnen. Der spezifische Implementierungscode lautet wie folgt:

type ProcessState struct {
    CpuPercent    float64
    MemResident   uint64
    MemVirtual    uint64
    MemSwap       uint64
}

func checkProcessState(targetPid int32, stateChan chan<- ProcessState) {
    ticker := time.NewTicker(5 * time.Second)
    for {
        select {
        case <-ticker.C:
            proc, err := process.NewProcess(targetPid)
            if err != nil {
                log.Printf("failed to get process %d: %v", targetPid, err)
                continue
            }
            cpuPercent, err := proc.CPUPercent()
            if err != nil {
                log.Printf("failed to get cpu percent for process %d: %v", targetPid, err)
                continue
            }
            memInfo, err := proc.MemoryInfo()
            if err != nil {
                log.Printf("failed to get memory info for process %d: %v", targetPid, err)
                continue
            }
            state := ProcessState{
                CpuPercent:  cpuPercent,
                MemResident: memInfo.RSS,
                MemVirtual:  memInfo.VMS,
                MemSwap:     memInfo.Swap,
            }
            stateChan <- state
        }
    }
}

Im obigen Code verwenden wir zunächst einen Ticker-Timer, um alle fünf Sekunden den Status des angegebenen Prozesses zu überprüfen. Während des Erkennungsprozesses erhalten wir das Prozesshandle der angegebenen PID über die Funktion „process.NewProcess()“ und verwenden die bereitgestellten Funktionen, um die CPU-Auslastung und die Speichernutzung zu ermitteln. Speichern Sie diese Informationen in einer oben definierten Struktur und senden Sie sie über stateChan nach außen.

3. Vollständiges Codebeispiel für die Golang-Prozessüberwachung

Basierend auf den oben genannten Implementierungsideen und dem Code können wir ein vollständiges Codebeispiel für die Golang-Prozessüberwachung schreiben. Der vollständige Code lautet wie folgt:

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/process"
    "log"
    "time"
)

type ProcessState struct {
    CpuPercent    float64
    MemResident   uint64
    MemVirtual    uint64
    MemSwap       uint64
}

func main() {
    targetProcessName := "myApp"
    targetPidList := make([]int32, 0)
    processes, err := process.Processes()
    if err != nil {
        log.Fatalf("failed to get all processes: %v", err)
    }
    for _, proc := range processes {
        name, err := proc.Name()
        if err != nil || name != targetProcessName {
            continue
        }
        pid := proc.Pid
        targetPidList = append(targetPidList, pid)
        log.Printf("find target process %s, pid = %d\n", name, pid)
    }
    stateChan := make(chan ProcessState)
    for _, pid := range targetPidList {
        go checkProcessState(pid, stateChan)
    }
    for {
        select {
        case state := <-stateChan:
            if state.CpuPercent > 100.0 || state.MemSwap > 0 || state.MemVirtual > 2*state.MemResident {
                log.Printf("process is not healthy: %+v\n", state)
            } else {
                log.Printf("process is healthy: %+v\n", state)
            }
        }
    }
}

func checkProcessState(targetPid int32, stateChan chan<- ProcessState) {
    ticker := time.NewTicker(5 * time.Second)
    for {
        select {
        case <-ticker.C:
            proc, err := process.NewProcess(targetPid)
            if err != nil {
                log.Printf("failed to get process %d: %v", targetPid, err)
                continue
            }
            cpuPercent, err := proc.CPUPercent()
            if err != nil {
                log.Printf("failed to get cpu percent for process %d: %v", targetPid, err)
                continue
            }
            memInfo, err := proc.MemoryInfo()
            if err != nil {
                log.Printf("failed to get memory info for process %d: %v", targetPid, err)
                continue
            }
            state := ProcessState{
                CpuPercent:  cpuPercent,
                MemResident: memInfo.RSS,
                MemVirtual:  memInfo.VMS,
                MemSwap:     memInfo.Swap,
            }
            stateChan <- state
        }
    }
}

In diesem Beispiel finden wir zunächst den Prozess, den wir überwachen müssen, und starten eine Goroutine für jeden Prozess, um seinen Status regelmäßig zu ermitteln. Das Programm empfängt kontinuierlich Statusmeldungen von Goroutine von Chan und bestimmt anhand des Status, ob das Programm normal läuft. Wenn eine Prozessanomalie festgestellt wird, werden entsprechende Eingabeaufforderungen über Protokolle bereitgestellt.

IV. Zusammenfassung

In diesem Artikel wird erläutert, wie Sie die Go-Sprache zur Implementierung der Prozessüberwachung verwenden, hauptsächlich durch Aufrufen der im psutil-Paket bereitgestellten API und Verwendung von Goroutine für die regelmäßige Erkennung. Durch die Prozessüberwachung können wir den Ausführungsstatus der Anwendung besser kontrollieren und Ausnahmen beim Auftreten des Programms umgehend behandeln, was uns dabei hilft, die Systementwicklung sowie den Betrieb und die Wartung besser umzusetzen.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie die Prozessüberwachung in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn