无为做网站,ui设计已经不火了,微信小程序h5,网站开发大概需要多少钱介绍与使用 expvar 是 exposed variable的简写 expvar包[1]是 Golang 官方为暴露Go应用内部指标数据所提供的标准对外接口#xff0c;可以辅助获取和调试全局变量。 其通过init函数将内置的expvarHandler(一个标准http HandlerFunc)注册到http包ListenAndServe创建的默认Serve… 介绍与使用 expvar 是 exposed variable的简写 expvar包[1]是 Golang 官方为暴露Go应用内部指标数据所提供的标准对外接口可以辅助获取和调试全局变量。 其通过init函数将内置的expvarHandler(一个标准http HandlerFunc)注册到http包ListenAndServe创建的默认Server上 如以下案例: package mainimport ( encoding/json expvar fmt github.com/gin-gonic/gin net/http runtime time)func main() { router : gin.Default() //初始化一个gin实例 router.GET(/debug/vars, GetCurrentRunningStats) //接口路由如果url不是/debug/vars则用metricBeat去获取会出问题 s : http.Server{ Addr: : 6666, Handler: router, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, MaxHeaderBytes: 1 20, } s.ListenAndServe() //开始监听}var CuMemoryPtr *map[string]stringvar BTCMemoryPtr *map[string]interface{}// 开始时间var start time.Now()// calculateUptime 计算运行时间func calculateUptime() interface{} { return time.Since(start).String()}// currentGoVersion 当前 Golang 版本func currentGoVersion() interface{} { return runtime.Version()}// getNumCPUs 获取 CPU 核心数量func getNumCPUs() interface{} { return runtime.NumCPU()}// getGoOS 当前系统类型func getGoOS() interface{} { return runtime.GOOS}// getNumGoroutins 当前 goroutine 数量func getNumGoroutins() interface{} { return runtime.NumGoroutine()}// getNumCgoCall CGo 调用次数func getNumCgoCall() interface{} { return runtime.NumCgoCall()}// 业务特定的内存数据func getCuMemoryMap() interface{} { if CuMemoryPtr nil { return 0 } else { return len(*CuMemoryPtr) }}// 业务特定的内存数据func getBTCMemoryMap() interface{} { if BTCMemoryPtr nil { return 0 } else { return len(*BTCMemoryPtr) }}var lastPause uint32// getLastGCPauseTime 获取上次 GC 的暂停时间func getLastGCPauseTime() interface{} { var gcPause uint64 ms : new(runtime.MemStats) statString : expvar.Get(memstats).String() if statString ! { json.Unmarshal([]byte(statString), ms) if lastPause 0 || lastPause ! ms.NumGC { gcPause ms.PauseNs[(ms.NumGC255)%256] lastPause ms.NumGC } } return gcPause}// GetCurrentRunningStats 返回当前运行信息func GetCurrentRunningStats(c *gin.Context) { c.Writer.Header().Set(Content-Type, application/json; charsetutf-8) first : true report : func(key string, value interface{}) { if !first { fmt.Fprintf(c.Writer, ,\n) } first false if str, ok : value.(string); ok { fmt.Fprintf(c.Writer, %q: %q, key, str) } else { fmt.Fprintf(c.Writer, %q: %v, key, value) } } fmt.Fprintf(c.Writer, {\n) expvar.Do(func(kv expvar.KeyValue) { report(kv.Key, kv.Value) }) fmt.Fprintf(c.Writer, \n}\n) c.String(http.StatusOK, )}func init() { //这些都是自定义变量发布到expvar中每次请求接口expvar会自动去获取这些变量并返回 expvar.Publish(运行时间, expvar.Func(calculateUptime)) expvar.Publish(version, expvar.Func(currentGoVersion)) expvar.Publish(cores, expvar.Func(getNumCPUs)) expvar.Publish(os, expvar.Func(getGoOS)) expvar.Publish(cgo, expvar.Func(getNumCgoCall)) expvar.Publish(goroutine, expvar.Func(getNumGoroutins)) expvar.Publish(gcpause, expvar.Func(getLastGCPauseTime)) expvar.Publish(CuMemory, expvar.Func(getCuMemoryMap)) expvar.Publish(BTCMemory, expvar.Func(getBTCMemoryMap))} 运行程序并请求127.0.0.1:6666/debug/vars 结果如下 { BTCMemory: 0, CuMemory: 0, cgo: 1, cmdline: [ /var/folders/9t/839s3jmj73bcgyp5x_xh3gw00000gn/T/go-build1753052226/b001/exe/1 ], cores: 8, gcpause: 0, goroutine: 3, memstats: { Alloc: 1516104, TotalAlloc: 1516104, Sys: 71961616, Lookups: 0, Mallocs: 12075, Frees: 1237, HeapAlloc: 1516104, HeapSys: 66650112, HeapIdle: 63930368, HeapInuse: 2719744, HeapReleased: 63930368, HeapObjects: 10838, StackInuse: 458752, StackSys: 458752, MSpanInuse: 46376, MSpanSys: 49152, MCacheInuse: 9600, MCacheSys: 16384, BuckHashSys: 4156, GCSys: 4227128, OtherSys: 555932, NextGC: 4473924, LastGC: 0, PauseTotalNs: 0, PauseNs: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], PauseEnd: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], NumGC: 0, NumForcedGC: 0, GCCPUFraction: 0, EnableGC: true, DebugGC: false, BySize: [ { Size: 0, Mallocs: 0, Frees: 0 }, { Size: 8, Mallocs: 251, Frees: 0 }, { Size: 16, Mallocs: 4258, Frees: 0 }, { Size: 24, Mallocs: 490, Frees: 0 }, { Size: 32, Mallocs: 1194, Frees: 0 }, { Size: 48, Mallocs: 745, Frees: 0 }, { Size: 64, Mallocs: 572, Frees: 0 }, { Size: 80, Mallocs: 72, Frees: 0 }, { Size: 96, Mallocs: 84, Frees: 0 }, { Size: 112, Mallocs: 2268, Frees: 0 }, { Size: 128, Mallocs: 79, Frees: 0 }, { Size: 144, Mallocs: 19, Frees: 0 }, { Size: 160, Mallocs: 164, Frees: 0 }, { Size: 176, Mallocs: 11, Frees: 0 }, { Size: 192, Mallocs: 16, Frees: 0 }, { Size: 208, Mallocs: 73, Frees: 0 }, { Size: 224, Mallocs: 5, Frees: 0 }, { Size: 240, Mallocs: 4, Frees: 0 }, { Size: 256, Mallocs: 30, Frees: 0 }, { Size: 288, Mallocs: 28, Frees: 0 }, { Size: 320, Mallocs: 50, Frees: 0 }, { Size: 352, Mallocs: 11, Frees: 0 }, { Size: 384, Mallocs: 30, Frees: 0 }, { Size: 416, Mallocs: 25, Frees: 0 }, { Size: 448, Mallocs: 3, Frees: 0 }, { Size: 480, Mallocs: 0, Frees: 0 }, { Size: 512, Mallocs: 9, Frees: 0 }, { Size: 576, Mallocs: 18, Frees: 0 }, { Size: 640, Mallocs: 57, Frees: 0 }, { Size: 704, Mallocs: 8, Frees: 0 }, { Size: 768, Mallocs: 1, Frees: 0 }, { Size: 896, Mallocs: 19, Frees: 0 }, { Size: 1024, Mallocs: 26, Frees: 0 }, { Size: 1152, Mallocs: 23, Frees: 0 }, { Size: 1280, Mallocs: 36, Frees: 0 }, { Size: 1408, Mallocs: 1, Frees: 0 }, { Size: 1536, Mallocs: 3, Frees: 0 }, { Size: 1792, Mallocs: 22, Frees: 0 }, { Size: 2048, Mallocs: 7, Frees: 0 }, { Size: 2304, Mallocs: 3, Frees: 0 }, { Size: 2688, Mallocs: 38, Frees: 0 }, { Size: 3072, Mallocs: 6, Frees: 0 }, { Size: 3200, Mallocs: 2, Frees: 0 }, { Size: 3456, Mallocs: 3, Frees: 0 }, { Size: 4096, Mallocs: 20, Frees: 0 }, { Size: 4864, Mallocs: 2, Frees: 0 }, { Size: 5376, Mallocs: 15, Frees: 0 }, { Size: 6144, Mallocs: 6, Frees: 0 }, { Size: 6528, Mallocs: 1, Frees: 0 }, { Size: 6784, Mallocs: 2, Frees: 0 }, { Size: 6912, Mallocs: 0, Frees: 0 }, { Size: 8192, Mallocs: 3, Frees: 0 }, { Size: 9472, Mallocs: 2, Frees: 0 }, { Size: 9728, Mallocs: 3, Frees: 0 }, { Size: 10240, Mallocs: 8, Frees: 0 }, { Size: 10880, Mallocs: 8, Frees: 0 }, { Size: 12288, Mallocs: 0, Frees: 0 }, { Size: 13568, Mallocs: 0, Frees: 0 }, { Size: 14336, Mallocs: 0, Frees: 0 }, { Size: 16384, Mallocs: 0, Frees: 0 }, { Size: 18432, Mallocs: 1, Frees: 0 } ] }, os: darwin, version: go1.16.7, 运行时间: 30.037286084s} 其中expvar包会默认携带memstats该字段内含 各种内存堆栈以及GC的一些信息具体可见源码注释 src/runtime/mstats.go src/runtime/mstats.go[2] // A MemStats records statistics about the memory allocator.type MemStats struct { // General statistics. // Alloc is bytes of allocated heap objects. // // This is the same as HeapAlloc (see below). Alloc uint64 // TotalAlloc is cumulative bytes allocated for heap objects. // // TotalAlloc increases as heap objects are allocated, but // unlike Alloc and HeapAlloc, it does not decrease when // objects are freed. TotalAlloc uint64 // Sys is the total bytes of memory obtained from the OS. // // Sys is the sum of the XSys fields below. Sys measures the // virtual address space reserved by the Go runtime for the // heap, stacks, and other internal data structures. Its // likely that not all of the virtual address space is backed // by physical memory at any given moment, though in general // it all was at some point. Sys uint64 // Lookups is the number of pointer lookups performed by the // runtime. // // This is primarily useful for debugging runtime internals. Lookups uint64 // Mallocs is the cumulative count of heap objects allocated. // The number of live objects is Mallocs - Frees. Mallocs uint64 // Frees is the cumulative count of heap objects freed. Frees uint64 // Heap memory statistics. // // Interpreting the heap statistics requires some knowledge of // how Go organizes memory. Go divides the virtual address // space of the heap into spans, which are contiguous // regions of memory 8K or larger. A span may be in one of // three states: // // An idle span contains no objects or other data. The // physical memory backing an idle span can be released back // to the OS (but the virtual address space never is), or it // can be converted into an in use or stack span. // // An in use span contains at least one heap object and may // have free space available to allocate more heap objects. // // A stack span is used for goroutine stacks. Stack spans // are not considered part of the heap. A span can change // between heap and stack memory; it is never used for both // simultaneously. // HeapAlloc is bytes of allocated heap objects. // // Allocated heap objects include all reachable objects, as // well as unreachable objects that the garbage collector has // not yet freed. Specifically, HeapAlloc increases as heap // objects are allocated and decreases as the heap is swept // and unreachable objects are freed. Sweeping occurs // incrementally between GC cycles, so these two processes // occur simultaneously, and as a result HeapAlloc tends to // change smoothly (in contrast with the sawtooth that is // typical of stop-the-world garbage collectors). HeapAlloc uint64 // HeapSys is bytes of heap memory obtained from the OS. // // HeapSys measures the amount of virtual address space // reserved for the heap. This includes virtual address space // that has been reserved but not yet used, which consumes no // physical memory, but tends to be small, as well as virtual // address space for which the physical memory has been // returned to the OS after it became unused (see HeapReleased // for a measure of the latter). // // HeapSys estimates the largest size the heap has had. HeapSys uint64 // HeapIdle is bytes in idle (unused) spans. // // Idle spans have no objects in them. These spans could be // (and may already have been) returned to the OS, or they can // be reused for heap allocations, or they can be reused as // stack memory. // // HeapIdle minus HeapReleased estimates the amount of memory // that could be returned to the OS, but is being retained by // the runtime so it can grow the heap without requesting more // memory from the OS. If this difference is significantly // larger than the heap size, it indicates there was a recent // transient spike in live heap size. HeapIdle uint64 // HeapInuse is bytes in in-use spans. // // In-use spans have at least one object in them. These spans // can only be used for other objects of roughly the same // size. // // HeapInuse minus HeapAlloc estimates the amount of memory // that has been dedicated to particular size classes, but is // not currently being used. This is an upper bound on // fragmentation, but in general this memory can be reused // efficiently. HeapInuse uint64 // HeapReleased is bytes of physical memory returned to the OS. // // This counts heap memory from idle spans that was returned // to the OS and has not yet been reacquired for the heap. HeapReleased uint64 // HeapObjects is the number of allocated heap objects. // // Like HeapAlloc, this increases as objects are allocated and // decreases as the heap is swept and unreachable objects are // freed. HeapObjects uint64 // Stack memory statistics. // // Stacks are not considered part of the heap, but the runtime // can reuse a span of heap memory for stack memory, and // vice-versa. // StackInuse is bytes in stack spans. // // In-use stack spans have at least one stack in them. These // spans can only be used for other stacks of the same size. // // There is no StackIdle because unused stack spans are // returned to the heap (and hence counted toward HeapIdle). StackInuse uint64 // StackSys is bytes of stack memory obtained from the OS. // // StackSys is StackInuse, plus any memory obtained directly // from the OS for OS thread stacks (which should be minimal). StackSys uint64 // Off-heap memory statistics. // // The following statistics measure runtime-internal // structures that are not allocated from heap memory (usually // because they are part of implementing the heap). Unlike // heap or stack memory, any memory allocated to these // structures is dedicated to these structures. // // These are primarily useful for debugging runtime memory // overheads. // MSpanInuse is bytes of allocated mspan structures. MSpanInuse uint64 // MSpanSys is bytes of memory obtained from the OS for mspan // structures. MSpanSys uint64 // MCacheInuse is bytes of allocated mcache structures. MCacheInuse uint64 // MCacheSys is bytes of memory obtained from the OS for // mcache structures. MCacheSys uint64 // BuckHashSys is bytes of memory in profiling bucket hash tables. BuckHashSys uint64 // GCSys is bytes of memory in garbage collection metadata. GCSys uint64 // OtherSys is bytes of memory in miscellaneous off-heap // runtime allocations. OtherSys uint64 // Garbage collector statistics. // NextGC is the target heap size of the next GC cycle. // // The garbage collectors goal is to keep HeapAlloc ≤ NextGC. // At the end of each GC cycle, the target for the next cycle // is computed based on the amount of reachable data and the // value of GOGC. NextGC uint64 // LastGC is the time the last garbage collection finished, as // nanoseconds since 1970 (the UNIX epoch). LastGC uint64 // PauseTotalNs is the cumulative nanoseconds in GC // stop-the-world pauses since the program started. // // During a stop-the-world pause, all goroutines are paused // and only the garbage collector can run. PauseTotalNs uint64 // PauseNs is a circular buffer of recent GC stop-the-world // pause times in nanoseconds. // // The most recent pause is at PauseNs[(NumGC255)%256]. In // general, PauseNs[N%256] records the time paused in the most // recent N%256th GC cycle. There may be multiple pauses per // GC cycle; this is the sum of all pauses during a cycle. PauseNs [256]uint64 // PauseEnd is a circular buffer of recent GC pause end times, // as nanoseconds since 1970 (the UNIX epoch). // // This buffer is filled the same way as PauseNs. There may be // multiple pauses per GC cycle; this records the end of the // last pause in a cycle. PauseEnd [256]uint64 // NumGC is the number of completed GC cycles. NumGC uint32 // NumForcedGC is the number of GC cycles that were forced by // the application calling the GC function. NumForcedGC uint32 // GCCPUFraction is the fraction of this programs available // CPU time used by the GC since the program started. // // GCCPUFraction is expressed as a number between 0 and 1, // where 0 means GC has consumed none of this programs CPU. A // programs available CPU time is defined as the integral of // GOMAXPROCS since the program started. That is, if // GOMAXPROCS is 2 and a program has been running for 10 // seconds, its available CPU is 20 seconds. GCCPUFraction // does not include CPU time used for write barrier activity. // // This is the same as the fraction of CPU reported by // GODEBUGgctrace1. GCCPUFraction float64 // EnableGC indicates that GC is enabled. It is always true, // even if GOGCoff. EnableGC bool // DebugGC is currently unused. DebugGC bool // BySize reports per-size class allocation statistics. // // BySize[N] gives statistics for allocations of size S where // BySize[N-1].Size S ≤ BySize[N].Size. // // This does not report allocations larger than BySize[60].Size. BySize [61]struct { // Size is the maximum byte size of an object in this // size class. Size uint32 // Mallocs is the cumulative count of heap objects // allocated in this size class. The cumulative bytes // of allocation is Size*Mallocs. The number of live // objects in this size class is Mallocs - Frees. Mallocs uint64 // Frees is the cumulative count of heap objects freed // in this size class. Frees uint64 }} 对于各个字段的意义 可参考 1、Alloc uint64 //Go语言框架 堆空间分配的字节数2、TotalAlloc uint64 //从服务开始运行至今分配器为分配的堆空间总和只增加释放时不减少3、Sys uint64 //服务现在使用的系统内存4、Lookups uint64 //被runtime监视的指针数5、Mallocs uint64 //服务malloc的次数6、Frees uint64 //服务回收的heap objects的字节数7、HeapAlloc uint64 //服务分配的堆内存字节数8、HeapSys uint64 //系统分配的作为运行栈的内存9、HeapIdle uint64 //申请但未分配的堆内存或者回收了的堆内存空闲字节数10、HeapInuse uint64 //正在使用的堆内存字节数10、HeapReleased uint64 //返回给OS的堆内存类似C/C中的free11、HeapObjects uint64 //堆内存块申请的量12、StackInuse uint64 //正在使用的栈字节数13、StackSys uint64 //系统分配的作为运行栈的内存14、MSpanInuse uint64 //用于测试用的结构体使用的字节数15、MSpanSys uint64 //系统为测试用的结构体分配的字节数16、MCacheInuse uint64 //mcache结构体申请的字节数(不会被视为垃圾回收)17、MCacheSys uint64 //操作系统申请的堆空间用于mcache的字节数18、BuckHashSys uint64 //用于剖析桶散列表的堆空间19、GCSys uint64 //垃圾回收标记元信息使用的内存20、OtherSys uint64 //golang系统架构占用的额外空间21、NextGC uint64 //垃圾回收器检视的内存大小22、LastGC uint64 // 垃圾回收器最后一次执行时间。23、PauseTotalNs uint64 // 垃圾回收或者其他信息收集导致服务暂停的次数。24、PauseNs [256]uint64 //一个循环队列记录最近垃圾回收系统中断的时间25、PauseEnd [256]uint64 //一个循环队列记录最近垃圾回收系统中断的时间开始点。26、NumForcedGC uint32 //服务调用runtime.GC()强制使用垃圾回收的次数。27、GCCPUFraction float64 //垃圾回收占用服务CPU工作的时间总和。如果有100个goroutine垃圾回收的时间为1S,那么就占用了100S。28、BySize //内存分配器使用情况 以上参考golang程序的监控神器----expvar[3] 社区同行开发的expvarmon[4]工具可以在命令行终端以图形化的方式实时展示特定的指标数据的变化expvarmon 即expvar monitor go get github.com/divan/expvarmon 启动刚才的程序然后执行如下命令可实时查看应用指标变化 期间可以进行不同qps的请求 expvarmon -portshttp://localhost:6666/debug/vars -i 1s 参考 给expvarmon插上数据持久化的“翅膀”[5] 官方库或知名项目中的使用 src/net/http/triv.go[6] 中使用了这个包 另外 golang.org/x/toolsv0.1.6/cmd/godoc/main.go golang.org/x/toolsv0.1.6/go/internal/gccgoimporter/gccgoinstallation_test.go go/test/bench/garbage/parser.go 也有使用 以及前面提到的expvarmon[7] 参考资料 [1] expvar包: https://gitee.com/cuishuang/go1.16/tree/master/src/expvar [2] src/runtime/mstats.go: https://gitee.com/cuishuang/go1.16/blob/master/src/runtime/mstats.go#L107 [3] golang程序的监控神器----expvar: https://blog.csdn.net/jeffrey11223/article/details/78886923/ [4] expvarmon: https://github.com/divan/expvarmon [5] 给expvarmon插上数据持久化的“翅膀”: https://tonybai.com/2021/04/14/expvarmon-save-and-convert-to-xlsx/ [6] src/net/http/triv.go: https://gitee.com/cuishuang/go1.16/blob/master/src/net/http/triv.go [7] expvarmon: https://github.com/divan/expvarmon 本文由 mdnice 多平台发布