Je trouvais un projet amusant pour travailler avec Go, HTMX et Tailwwindcss et j'ai fini par créer un simple moniteur système basé sur le Web en temps réel avec la puissance d'un socket Web. Voici le résultat.
Il affiche les informations système, les mémoires, le disque, le processeur et les processus en cours, mis à jour automatiquement toutes les 5 secondes.
Je vais détailler un peu le code dans cet article.
type HttpServer struct { subscriberMessageBuffer int Mux http.ServeMux subscribersMutex sync.Mutex subscribers map[*subscriber]struct{} } type subscriber struct { msgs chan []byte }
C’est assez simple. HttpServer contient un http.ServeMux comme gestionnaire http et des abonnés pour la diffusion ultérieure de sockets Web. l'abonné dispose simplement d'un canal de messages pour la mise à jour des données.
Comme il n'a besoin de servir qu'un seul fichier HTML, il a alors besoin d'une URL pour afficher la page et d'une URL pour la connexion au socket Web.
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 }
Endpoint /ws gérera la connexion au socket Web et gérera un abonné. Tout d'abord, il lancera un nouvel abonné et l'ajoutera à une carte dans la structure du serveur http. Le verrouillage sera utilisé pour éviter les conditions de concurrence puisque nous utiliserons la routine go plus tard.
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) }
Le socket Web commence à accepter une connexion et via une boucle, nous détecterons un message de canal entrant de l'abonné et l'écrirons sur le socket 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() } } }
La mise à jour automatique des données d'informations système est gérée par la routine go. Nous allons construire une réponse html qui sera envoyée via socket web et htmx gérera la mise à jour côté 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) // ... }
La syntaxe hx-swap-oob="innerHTML:#data-timestamp" en htmx nous indique qu'il faut échanger un composant à l'intérieur de l'identifiant d'horodatage des données dans notre code HTML. Tous les mécanismes d'échange seront les mêmes pour les autres composants d'informations du système.
Tous les composants HTML échangeables seront envoyés via la méthode Broadcast (msg) et plus tard seront envoyés via le canal toutes les 5 secondes.
func (s *HttpServer) Broadcast(msg []byte) { s.subscribersMutex.Lock() for subscriber := range s.subscribers { subscriber.msgs <- msg } s.subscribersMutex.Unlock() }
C'est un simple fichier HTML et pour Tailwindcss, j'ai simplement utilisé CDN pour ça
<script src="https://cdn.tailwindcss.com"></script>
Même idée pour HTMX et extension de socket Web pour utiliser 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>
La page de surveillance du système devrait recevoir toutes les données par socket Web afin que je puisse les définir à partir du conteneur div principal. Spécifiez hx-ext="ws" pour indiquer à HTMX d'utiliser l'extension de socket Web et ws-connect = "/ws" pour indiquer à la socket Web de se connecter via l'URL /ws.
<corps> <h2> Code complet </h2> <p>Voici la version complète du code https://github.com/didikz/gosysmon-web et vous voudrez peut-être jouer avec votre propre version.</p> <p>Bon codage !</p>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!