私は Go、HTMX、Tailwwindcss を使用する楽しいプロジェクトを見つけて、最終的に Web ソケットの力を使ったシンプルなリアルタイム Web ベースのシステム モニターを構築しました。結果は次のとおりです。
システム情報、メモリ、ディスク、CPU、実行中のプロセスが表示され、5 秒ごとに自動的に更新されます。
この投稿ではコードを少し詳しく説明します。
type HttpServer struct { subscriberMessageBuffer int Mux http.ServeMux subscribersMutex sync.Mutex subscribers map[*subscriber]struct{} } type subscriber struct { msgs chan []byte }
それは非常に簡単です。 HttpServer には、http ハンドラーとして http.ServeMux が含まれており、後で Web ソケット ブロードキャストを行うためのサブスクライバーも含まれています。加入者はデータ更新用のメッセージ チャネルを持っているだけです。
単一の HTML ファイルを提供するだけでよいため、ページを表示するための URL と、Web ソケット接続用の URL が 1 つ必要です。
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 }
エンドポイント /ws は Web ソケット接続を処理し、サブスクライバーを管理します。まず、新しいサブスクライバを開始し、それを http サーバー構造のマップに追加します。後で go ルーチンを使用するため、ロックは競合状態を防ぐために使用されます。
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 ソケットは接続の受け入れを開始しており、ループを介してサブスクライバーからの受信チャネル メッセージを検出し、それを Web ソケットに書き込みます。
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() } } }
システム情報データの自動更新は go ルーチンによって処理されます。 Web ソケット経由で送信される HTML 応答を構築し、htmx が HTML 側の更新を処理します。
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) // ... }
htmx の構文 hx-swap-oob="innerHTML:#data-timestamp" は、HTML の data-timestamp ID 内のコンポーネントを交換することを示します。すべてのスワッピング メカニズムは、他のシステム情報コンポーネントでも同じです。
すべてのスワップ可能な HTML コンポーネントは、Broadcast(msg) メソッドを介して送信され、その後は 5 秒ごとにチャネルを介して送信されます。
func (s *HttpServer) Broadcast(msg []byte) { s.subscribersMutex.Lock() for subscriber := range s.subscribers { subscriber.msgs <- msg } s.subscribersMutex.Unlock() }
これはプレーンな HTML ファイルであり、Tailwindcss の場合は単純に CDN を使用しました
<script src="https://cdn.tailwindcss.com"></script>
CDN を使用するための HTMX と Web ソケット拡張についても同じ考えです。
<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>
システム モニター ページは Web ソケットですべてのデータを受信することが想定されているため、メインの div コンテナーから設定できます。 Web ソケット拡張機能を使用するように HTMX に指示するには hx-ext=”ws” を指定し、Web ソケットに /ws URL 経由で接続するように指示するには ws-connect=”/ws” を指定します。
<h2> 完全なコード </h2> <p>コードの完全版は https://github.com/didikz/gosysmon-web です。独自のバージョンを試してみることもできます。</p> <p>コーディングを楽しんでください!</p>
以上がGo、HTMX、Web Socket を使用したシンプルなリアルタイム システム モニターの構築の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。