Ich habe ein lustiges Projekt für die Arbeit mit Go, HTMX und Tailwwindcss gefunden und am Ende einen einfachen webbasierten Echtzeit-Systemmonitor mit der Leistung von Web Socket erstellt. Hier ist das Ergebnis.
Es zeigt Systeminformationen, Speicher, Festplatte, CPU und laufende Prozesse an, die alle 5 Sekunden automatisch aktualisiert werden.
Ich werde den Code in diesem Beitrag etwas aufschlüsseln.
type HttpServer struct { subscriberMessageBuffer int Mux http.ServeMux subscribersMutex sync.Mutex subscribers map[*subscriber]struct{} } type subscriber struct { msgs chan []byte }
Es ist ganz einfach. HttpServer enthält einen http.ServeMux als http-Handler und Abonnenten für späteres Web-Socket-Broadcasting. Der Abonnent hat einfach einen Nachrichtenkanal für die Datenaktualisierung.
Da nur eine einzige HTML-Datei bereitgestellt werden muss, benötigt es eine URL zum Anzeigen der Seite und eine URL für die Web-Socket-Verbindung.
func NewHttpServer() *HttpServer { s := &HttpServer{ subscriberMessageBuffer: 10, subscribers: make(map[*subscriber]struct{}), } s.Mux.Handle("/", http.FileServer(http.Dir("./views"))) s.Mux.HandleFunc("/ws", s.subscribeHandler) return s }
Endpunkt /ws kümmert sich um die Web-Socket-Verbindung und verwaltet einen Abonnenten. Zunächst wird ein neuer Abonnent initiiert und zu einer Karte in der http-Serverstruktur hinzugefügt. Die Sperre wird verwendet, um eine Rennbedingung zu verhindern, da wir später die Go-Routine verwenden werden.
func (s *HttpServer) subscribeHandler(w http.ResponseWriter, r *http.Request) { err := s.subscribe(r.Context(), w, r) if err != nil { fmt.Println(err) return } } func (s *HttpServer) addSubscriber(subscriber *subscriber) { s.subscribersMutex.Lock() s.subscribers[subscriber] = struct{}{} s.subscribersMutex.Unlock() fmt.Println("subscriber added", subscriber) }
Web Socket beginnt, eine Verbindung zu akzeptieren und über eine Schleife erkennen wir eingehende Kanalnachrichten vom Abonnenten und schreiben sie an Web Socket.
func (s *HttpServer) subscribe(ctx context.Context, w http.ResponseWriter, r *http.Request) error { var c *websocket.Conn subscriber := &subscriber{ msgs: make(chan []byte, s.subscriberMessageBuffer), } s.addSubscriber(subscriber) c, err := websocket.Accept(w, r, nil) if err != nil { return err } defer c.CloseNow() ctx = c.CloseRead(ctx) for { select { case msg := <-subscriber.msgs: ctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() err := c.Write(ctx, websocket.MessageText, msg) if err != nil { return err } case <-ctx.Done(): return ctx.Err() } } }
Die automatische Aktualisierung der Systeminformationsdaten erfolgt durch die Go-Routine. Wir erstellen eine HTML-Antwort, die über einen Web-Socket gesendet wird, und htmx übernimmt die Aktualisierung auf der HTML-Seite.
func main() { fmt.Println("Starting system monitor") s := server.NewHttpServer() go func(s *server.HttpServer) { for { hostStat, _ := host.Info() timestamp := time.Now().Format("2006-01-02 15:04:05") html := ` <span hx-swap-oob="innerHTML:#data-timestamp">` + timestamp + `</span> <span hx-swap-oob="innerHTML:#system-hostname">` + hostStat.Hostname + `</span> <span hx-swap-oob="innerHTML:#system-os">` + hostStat.OS + `</span> ` s.Broadcast([]byte(html)) time.Sleep(time.Second * 5) } }(s) // ... }
Die Syntax hx-swap-oob="innerHTML:#data-timestamp" in HTML besagt, dass wir eine Komponente innerhalb der Daten-Zeitstempel-ID in unserem HTML austauschen sollen. Alle Austauschmechanismen sind für andere Systeminformationskomponenten gleich.
Alle austauschbaren HTML-Komponenten werden über die Broadcast-Methode (msg) und später alle 5 Sekunden über den Kanal gesendet.
func (s *HttpServer) Broadcast(msg []byte) { s.subscribersMutex.Lock() for subscriber := range s.subscribers { subscriber.msgs <- msg } s.subscribersMutex.Unlock() }
Es ist eine einfache HTML-Datei und für Tailwindcss habe ich dafür einfach CDN verwendet
<script src="https://cdn.tailwindcss.com"></script>
Gleiche Idee für HTMX und Web-Socket-Erweiterung für die Verwendung von CDN.
<script src="https://unpkg.com/htmx.org@2.0.3" integrity="sha384-0895/pl2MU10Hqc6jd4RvrthNlDiE9U1tWmX7WRESftEDRosgxNsQG/Ze9YMRzHq" crossorigin="anonymous"></script> <script src="https://unpkg.com/htmx-ext-ws@2.0.1/ws.js"></script>
Es wird erwartet, dass die Systemüberwachungsseite alle Daten per Web-Socket empfängt, sodass ich sie vom Haupt-Div-Container aus festlegen kann. Geben Sie hx-ext=“ws“ an, um HTMX anzuweisen, die Web-Socket-Erweiterung zu verwenden, und ws-connect=“/ws“, um Web-Socket anzuweisen, eine Verbindung über die /ws-URL herzustellen.
<body> <h2> Vollständiger Code </h2> <p>Hier ist die Vollversion des Codes https://github.com/didikz/gosysmon-web und vielleicht möchten Sie mit Ihrer eigenen Version herumspielen.</p> <p>Viel Spaß beim Codieren!</p>
Das obige ist der detaillierte Inhalt vonErstellen eines einfachen Echtzeit-Systemmonitors mit Go, HTMX und Web Socket. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!