<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 expvar 暴露 Go 程序運(yùn)行指標(biāo)

          共 13621字,需瀏覽 28分鐘

           ·

          2022-08-02 02:24

          點(diǎn)擊上方“Go語(yǔ)言進(jìn)階學(xué)習(xí)”,進(jìn)行關(guān)注

          回復(fù)“Go語(yǔ)言”即可獲贈(zèng)從入門到進(jìn)階共10本電子書

          年年越溪女,相憶采芙蓉。

          獲取應(yīng)用程序的運(yùn)行指標(biāo),可以讓我們更好地了解它的實(shí)際狀況。將這些指標(biāo)對(duì)接到 prometheus、zabbix 等監(jiān)控系統(tǒng),能夠?qū)?yīng)用程序持續(xù)檢測(cè),發(fā)現(xiàn)異??梢约皶r(shí)告警并得到處理。

          Pull 與 Push

          與監(jiān)控系統(tǒng)對(duì)接方式有兩種,一種是 Pull(拉?。硗庖环N Push(推送)。

          以 Prometheus 為例,應(yīng)用程序通過暴露出 HTTP 接口,讓 Prometheus 周期性地通過該接口抓取指標(biāo),這就是 Pull。而 Push 是應(yīng)用程序主動(dòng)將指標(biāo)推送給 PushGateway, Prometheus 則去 PushGateway 抓取數(shù)據(jù)。

          Go 標(biāo)準(zhǔn)庫(kù)中有一個(gè)名為 expvar 的包,它的名字由 exp 和 var 兩部分組合而成,意味著導(dǎo)出變量。

          expvar 為公共變量提供了標(biāo)準(zhǔn)化的接口,并通過 HTTP 以 Json 的格式將這些變量暴露出去,很適合采用 Pull 的方式與監(jiān)控系統(tǒng)進(jìn)行對(duì)接。

          使用 expvar 庫(kù)

          expvar 是標(biāo)準(zhǔn)庫(kù),意味著我們并不要額外的依賴,并且它還提供了一些開箱即用的指標(biāo)。下面我們來學(xué)習(xí)一下該庫(kù)的使用。

          當(dāng)引用了 expvar 庫(kù)(import "expvar"),以下 init 函數(shù)將被自動(dòng)調(diào)用。

          func init() {
           http.HandleFunc("/debug/vars", expvarHandler)
           Publish("cmdline", Func(cmdline))
           Publish("memstats", Func(memstats))
          }

          該函數(shù)為我們注冊(cè)了 /debug/vars 路徑的 HTTP 服務(wù),訪問該路徑將得到 Json 格式的指標(biāo)。

          因此,我們還需要調(diào)用 ListenAndServe 綁定端口,并開始服務(wù) HTTP 請(qǐng)求。

          http.ListenAndServe(":8080"nil)

          完整代碼如下

          package main

          import (
           _ "expvar"
           "net/http"
          )

          func main() {
           http.ListenAndServe(":8080"nil)
          }

          將程序運(yùn)行起來后,通過 curl 請(qǐng)求,得到以下結(jié)果

          $ curl localhost:8080/debug/vars
          {
          "cmdline": ["/var/folders/xk/gn46n46d503dsztbc6_9qb2h0000gn/T/go-build1657217338/b001/exe/main"],
          "memstats": {"Alloc":278880,"TotalAlloc":278880,"Sys":8735760,"Lookups":0,"Mallocs":1169,"Frees":87,"HeapAlloc":278880,"HeapSys":3866624,"HeapIdle":2949120,"HeapInuse":917504,"HeapReleased":2899968,"HeapObjects":1082,"StackInuse":327680,"StackSys":327680,"MSpanInuse":28696,"MSpanSys":32640,"MCacheInuse":9600,"MCacheSys":15600,"BuckHashSys":3875,"GCSys":3826448,"OtherSys":662893,"NextGC":4194304,"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":41,"Frees":0},{"Size":16,"Mallocs":496,"Frees":0},{"Size":24,"Mallocs":63,"Frees":0},{"Size":32,"Mallocs":28,"Frees":0},{"Size":48,"Mallocs":134,"Frees":0},{"Size":64,"Mallocs":50,"Frees":0},{"Size":80,"Mallocs":17,"Frees":0},{"Size":96,"Mallocs":17,"Frees":0},{"Size":112,"Mallocs":6,"Frees":0},{"Size":128,"Mallocs":9,"Frees":0},{"Size":144,"Mallocs":9,"Frees":0},{"Size":160,"Mallocs":18,"Frees":0},{"Size":176,"Mallocs":6,"Frees":0},{"Size":192,"Mallocs":0,"Frees":0},{"Size":208,"Mallocs":37,"Frees":0},{"Size":224,"Mallocs":6,"Frees":0},{"Size":240,"Mallocs":0,"Frees":0},{"Size":256,"Mallocs":12,"Frees":0},{"Size":288,"Mallocs":7,"Frees":0},{"Size":320,"Mallocs":2,"Frees":0},{"Size":352,"Mallocs":13,"Frees":0},{"Size":384,"Mallocs":1,"Frees":0},{"Size":416,"Mallocs":30,"Frees":0},{"Size":448,"Mallocs":1,"Frees":0},{"Size":480,"Mallocs":2,"Frees":0},{"Size":512,"Mallocs":0,"Frees":0},{"Size":576,"Mallocs":5,"Frees":0},{"Size":640,"Mallocs":5,"Frees":0},{"Size":704,"Mallocs":3,"Frees":0},{"Size":768,"Mallocs":0,"Frees":0},{"Size":896,"Mallocs":6,"Frees":0},{"Size":1024,"Mallocs":8,"Frees":0},{"Size":1152,"Mallocs":10,"Frees":0},{"Size":1280,"Mallocs":3,"Frees":0},{"Size":1408,"Mallocs":1,"Frees":0},{"Size":1536,"Mallocs":0,"Frees":0},{"Size":1792,"Mallocs":7,"Frees":0},{"Size":2048,"Mallocs":2,"Frees":0},{"Size":2304,"Mallocs":3,"Frees":0},{"Size":2688,"Mallocs":2,"Frees":0},{"Size":3072,"Mallocs":0,"Frees":0},{"Size":3200,"Mallocs":0,"Frees":0},{"Size":3456,"Mallocs":0,"Frees":0},{"Size":4096,"Mallocs":8,"Frees":0},{"Size":4864,"Mallocs":1,"Frees":0},{"Size":5376,"Mallocs":1,"Frees":0},{"Size":6144,"Mallocs":2,"Frees":0},{"Size":6528,"Mallocs":0,"Frees":0},{"Size":6784,"Mallocs":0,"Frees":0},{"Size":6912,"Mallocs":0,"Frees":0},{"Size":8192,"Mallocs":2,"Frees":0},{"Size":9472,"Mallocs":8,"Frees":0},{"Size":9728,"Mallocs":0,"Frees":0},{"Size":10240,"Mallocs":0,"Frees":0},{"Size":10880,"Mallocs":0,"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":0,"Frees":0}]}
          }

          可以看到,expvar 默認(rèn)已提供了兩項(xiàng)指標(biāo),分別是程序執(zhí)行命令(os.Args)和運(yùn)行時(shí)內(nèi)存分配(runtime.Memstats)信息。

          expvar 庫(kù)重點(diǎn)內(nèi)容

          expvar 中最重要的是 Publish 函數(shù)和 Var 接口。

          func Publish(name string, v Var) {}

          Publish 函數(shù)簽名中需要兩個(gè)參數(shù),name 是我們指定的指標(biāo)名。例如在上文 expvar 的 init 函數(shù)下 Publish("cmdline", Func(cmdline))代碼行,其中cmdline就是指標(biāo)名,而Func(cmdline)則是實(shí)現(xiàn)了 Var 接口的 expvar.Func 類型變量。

          Var 接口,它只定義了一個(gè) String 方法。需要注意的是,該方法必須要返回一個(gè)有效的 Json字符串。

          // Var is an abstract type for all exported variables.
          type Var interface {
           // String returns a valid JSON value for the variable.
           // Types with String methods that do not return valid JSON
           // (such as time.Time) must not be used as a Var.
           String() string
          }

          為了方便使用,expvar 庫(kù)中提供了五種導(dǎo)出變量類型,它們均實(shí)現(xiàn)了 Var 接口。

          type Int struct {
           i int64
          }

          type Float struct {
           f uint64
          }

          type Map struct {
           m      sync.Map // map[string]Var
           keysMu sync.RWMutex
           keys   []string // sorted
          }

          type String struct {
           s atomic.Value // string
          }

          type Func func() any

          我們分別通過調(diào)用 expvar.NewXXX 函數(shù)即可完成前四種類型的變量創(chuàng)建與指標(biāo)注冊(cè)。

          intVar = expvar.NewInt(“metricName”)
          floatVar = expvar.NewFloat(“metricName”)
          mapVar = expvar.NewMap(“metricName”)
          stringVar = expvar.NewString(“metricName”)

          例如 expvar.NewInt 函數(shù),它會(huì)內(nèi)部調(diào)用 Publish 方法完成指標(biāo)名與 expvar.Int 類型變量的綁定。

          func NewInt(name string) *Int {
           v := new(Int)
           Publish(name, v)
           return v
          }

          而 expvar.Func 類型,其實(shí)是為了讓我們可以自定義導(dǎo)出類型。

          例如,假如我們想要暴露以下定義的結(jié)構(gòu)體

          type MyStruct struct {
           Field1 string
           Field2 int
           Field3 float64
          }

          首先需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)生成函數(shù)。它用于在每次調(diào)用 HTTP 服務(wù)路徑時(shí),通過該函數(shù)導(dǎo)出這里面的數(shù)據(jù)。

          func MyStructData() interface{} {
           return MyStruct{
            Field1: "Gopher",
            Field2: 22,
            Field3: 19.99,
           }
          }

          最后,通過 Publish 函數(shù)注冊(cè)指標(biāo)名即可。

          expvar.Publish("metricName", expvar.Func(MyStructData))

          完整示例

          下面,我們給出一個(gè)覆蓋五種導(dǎo)出變量類型的完整示例。

          package main

          import (
           "expvar"
           "github.com/shirou/gopsutil/v3/host"
           "github.com/shirou/gopsutil/v3/load"
           "github.com/shirou/gopsutil/v3/mem"
           "net/http"
           "time"
          )

          type Load struct {
           Load1  float64
           Load5  float64
           Load15 float64
          }

          func AllLoadAvg() interface{} {
           return Load{
            Load1:  LoadAvg(1),
            Load5:  LoadAvg(5),
            Load15: LoadAvg(15),
           }
          }

          func LoadAvg(loadNumber int) float64 {
           avg, _ := load.Avg()
           switch loadNumber {
           case 5:
            return avg.Load5
           case 15:
            return avg.Load15
           default:
            return avg.Load1
           }
          }

          func main() {
           var (
            aliveOfSeconds = expvar.NewInt("aliveOfSeconds")
            hostID         = expvar.NewString("hostID")
            lastLoad       = expvar.NewFloat("lastLoad")
            virtualMemory  = expvar.NewMap("virtualMemory")
           )
           expvar.Publish("allLoadAvg", expvar.Func(AllLoadAvg))
           h, _ := host.HostID()
           hostID.Set(h)

           go http.ListenAndServe(":8080"nil)

           for {
            aliveOfSeconds.Add(1)
            vm, _ := mem.VirtualMemory()
            lastLoad.Set(LoadAvg(1))
            virtualMemory.Add("active"int64(vm.Active))
            virtualMemory.Add("buffer"int64(vm.Buffers))
            time.Sleep(1 * time.Second)
           }
          }

          在上述示例中,我們通過 gopsutil 庫(kù)(介紹可見還在自己寫 Go 系統(tǒng)監(jiān)控函數(shù)嗎一文)獲取了一些系統(tǒng)信息,并展示了如何通過 expvar 中的各種變量類型將這些信息進(jìn)行導(dǎo)出。

          curl 訪問 localhost:8080/debug/vars 結(jié)果如下

          $ curl localhost:8080/debug/vars
          {
          "aliveOfSeconds": 1,
          "allLoadAvg": {"Load1":1.69580078125,"Load5":1.97412109375,"Load15":1.90283203125},
          "cmdline": ["/var/folders/xk/gn46n46d503dsztbc6_9qb2h0000gn/T/go-build3566019824/b001/exe/main"],
          "hostID""7a1a74f2-30fc-5bc1-b439-6b7aef22e58d",
          "lastLoad": 1.69580078125,
          "memstats": {"Alloc":256208,"TotalAlloc":256208,"Sys":8735760,"Lookups":0,"Mallocs":1089,"Frees":48,"HeapAlloc":256208,"HeapSys":3866624,"HeapIdle":2891776,"HeapInuse":974848,"HeapReleased":2859008,"HeapObjects":1041,"StackInuse":327680,"StackSys":327680,"MSpanInuse":19992,"MSpanSys":32640,"MCacheInuse":9600,"MCacheSys":15600,"BuckHashSys":3905,"GCSys":3851120,"OtherSys":638191,"NextGC":4194304,"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":35,"Frees":0},{"Size":16,"Mallocs":415,"Frees":0},{"Size":24,"Mallocs":71,"Frees":0},{"Size":32,"Mallocs":37,"Frees":0},{"Size":48,"Mallocs":141,"Frees":0},{"Size":64,"Mallocs":52,"Frees":0},{"Size":80,"Mallocs":20,"Frees":0},{"Size":96,"Mallocs":23,"Frees":0},{"Size":112,"Mallocs":14,"Frees":0},{"Size":128,"Mallocs":7,"Frees":0},{"Size":144,"Mallocs":7,"Frees":0},{"Size":160,"Mallocs":18,"Frees":0},{"Size":176,"Mallocs":6,"Frees":0},{"Size":192,"Mallocs":1,"Frees":0},{"Size":208,"Mallocs":42,"Frees":0},{"Size":224,"Mallocs":3,"Frees":0},{"Size":240,"Mallocs":0,"Frees":0},{"Size":256,"Mallocs":9,"Frees":0},{"Size":288,"Mallocs":8,"Frees":0},{"Size":320,"Mallocs":5,"Frees":0},{"Size":352,"Mallocs":13,"Frees":0},{"Size":384,"Mallocs":3,"Frees":0},{"Size":416,"Mallocs":33,"Frees":0},{"Size":448,"Mallocs":0,"Frees":0},{"Size":480,"Mallocs":2,"Frees":0},{"Size":512,"Mallocs":1,"Frees":0},{"Size":576,"Mallocs":4,"Frees":0},{"Size":640,"Mallocs":8,"Frees":0},{"Size":704,"Mallocs":3,"Frees":0},{"Size":768,"Mallocs":1,"Frees":0},{"Size":896,"Mallocs":6,"Frees":0},{"Size":1024,"Mallocs":8,"Frees":0},{"Size":1152,"Mallocs":9,"Frees":0},{"Size":1280,"Mallocs":3,"Frees":0},{"Size":1408,"Mallocs":1,"Frees":0},{"Size":1536,"Mallocs":1,"Frees":0},{"Size":1792,"Mallocs":9,"Frees":0},{"Size":2048,"Mallocs":1,"Frees":0},{"Size":2304,"Mallocs":2,"Frees":0},{"Size":2688,"Mallocs":2,"Frees":0},{"Size":3072,"Mallocs":0,"Frees":0},{"Size":3200,"Mallocs":1,"Frees":0},{"Size":3456,"Mallocs":0,"Frees":0},{"Size":4096,"Mallocs":5,"Frees":0},{"Size":4864,"Mallocs":0,"Frees":0},{"Size":5376,"Mallocs":1,"Frees":0},{"Size":6144,"Mallocs":1,"Frees":0},{"Size":6528,"Mallocs":0,"Frees":0},{"Size":6784,"Mallocs":0,"Frees":0},{"Size":6912,"Mallocs":0,"Frees":0},{"Size":8192,"Mallocs":1,"Frees":0},{"Size":9472,"Mallocs":8,"Frees":0},{"Size":9728,"Mallocs":0,"Frees":0},{"Size":10240,"Mallocs":0,"Frees":0},{"Size":10880,"Mallocs":0,"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":0,"Frees":0}]},
          "virtualMemory": {"active": 1957449728, "buffer": 0}
          }

          總結(jié)

          標(biāo)準(zhǔn)庫(kù) expvar 為需要導(dǎo)出的公共變量提供了一個(gè)標(biāo)準(zhǔn)化的接口,使用比較簡(jiǎn)單。

          expvar 包內(nèi)部定義的幾種基礎(chǔ)類型都相應(yīng)給出了并發(fā)安全的操作方法,我們不需要去重復(fù)實(shí)現(xiàn)一遍,能夠開箱即用。

          但是, 在 https://go.dev/ 上統(tǒng)計(jì)的公共項(xiàng)目,該庫(kù)的 import 數(shù)量還不足 1萬(wàn)。

          相比于其他標(biāo)準(zhǔn)庫(kù)的 import 數(shù)量而言,expvar 的存在感太低了。

          所以問題來了,你認(rèn)為是什么原因?qū)е?expvar 庫(kù)這么冷門呢?歡迎留言討論。

          ------------------ End -------------------

          往期精彩文章推薦:

          歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

          想加入Go學(xué)習(xí)群請(qǐng)?jiān)诤笈_(tái)回復(fù)【入群

          萬(wàn)水千山總是情,點(diǎn)個(gè)【在看】行不行

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文无码免费一区二区三区 | 怒操香蕉| 久久久久久无码精品大片 | 免费日屄视频 | 青青草在线视频黄色 |