编辑
2024-11-27
后端
00
请注意,本文编写于 164 天前,最后修改于 164 天前,其中某些信息可能已经过时。
go
package health import ( "fmt" "html/template" "net/http" _ "net/http/pprof" "runtime" "sync" "time" "github.com/gorilla/websocket" ) type MemUsage struct { Alloc uint64 TotalAlloc uint64 Sys uint64 NumGC uint32 Timestamp time.Time } var memUsageHistory []MemUsage var mu sync.Mutex var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } func Run(addr string) { // 启动 pprof HTTP 服务器 go func() { fmt.Println(http.ListenAndServe(addr, nil)) }() // 启动内存监控 HTTP 服务器 http.HandleFunc("/", memUsageHandler) http.HandleFunc("/ws", wsHandler) go func() { fmt.Println(http.ListenAndServe("localhost:8080", nil)) }() // 定期记录内存使用情况 go func() { for { mu.Lock() memUsageHistory = append(memUsageHistory, getMemUsage()) mu.Unlock() time.Sleep(10 * time.Second) } }() } func memUsageHandler(w http.ResponseWriter, r *http.Request) { const htmlTemplate = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Memory Usage</title> <style> body { margin: 0; font-family: Arial, Helvetica, sans-serif; background-color: #f8f9fa; } .header { position: fixed; top: 0; width: 100%; background-color: #007bff; color: white; padding: 10px 0; text-align: center; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } .container { margin-top: 70px; padding: 20px; } .table { width: 100%; border-collapse: collapse; } .table th, .table td { padding: 8px; border: 1px solid #dee2e6; } .table th { background-color: #007bff; color: white; } .table tr:nth-child(even) { background-color: #f2f2f2; } </style> </head> <body> <div class="header"> <h1>Memory Usage</h1> </div> <div class="container"> <table class="table"> <thead> <tr> <th>Timestamp</th> <th>Alloc (MiB)</th> <th>TotalAlloc (MiB)</th> <th>Sys (MiB)</th> <th>NumGC</th> </tr> </thead> <tbody id="memUsageTable"> {{range .}} <tr> <td>{{.Timestamp.Format "2006-01-02 15:04:05"}}</td> <td>{{.Alloc}}</td> <td>{{.TotalAlloc}}</td> <td>{{.Sys}}</td> <td>{{.NumGC}}</td> </tr> {{end}} </tbody> </table> </div> <script> var ws = new WebSocket("ws://localhost:8080/ws"); ws.onmessage = function(event) { var data = JSON.parse(event.data); var row = "<tr>"; row += "<td>" + new Date(data.Timestamp).toLocaleString() + "</td>"; row += "<td>" + data.Alloc + "</td>"; row += "<td>" + data.TotalAlloc + "</td>"; row += "<td>" + data.Sys + "</td>"; row += "<td>" + data.NumGC + "</td>"; row += "</tr>"; document.getElementById("memUsageTable").innerHTML += row; }; </script> </body> </html> ` tmpl := template.Must(template.New("memUsage").Parse(htmlTemplate)) mu.Lock() defer mu.Unlock() tmpl.Execute(w, memUsageHistory) } func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { fmt.Println("Upgrade error:", err) return } defer conn.Close() for { mu.Lock() if len(memUsageHistory) > 0 { lastUsage := memUsageHistory[len(memUsageHistory)-1] err := conn.WriteJSON(lastUsage) if err != nil { fmt.Println("Write error:", err) break } } mu.Unlock() time.Sleep(1 * time.Second) } } func getMemUsage() MemUsage { var m runtime.MemStats runtime.ReadMemStats(&m) return MemUsage{ Alloc: bToMb(m.Alloc), TotalAlloc: bToMb(m.TotalAlloc), Sys: bToMb(m.Sys), NumGC: m.NumGC, Timestamp: time.Now(), } } func bToMb(b uint64) uint64 { return b / 1024 / 1024 }

go内存监控,主要使用runtime获取参数

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!