Golang获取外部页面的TTFP和完全加载时间等性能指标

Golang获取外部页面的TTFP和完全加载时间等性能指标 大家好,

我已经在谷歌上搜索了好几天,但没有任何进展。希望有人能告诉我如何解决这个问题。

我想获取一些关于外部页面的指标信息,例如,当我连接到 google.com 时,我希望获取:

  1. TTFB 时间
  2. 完整页面加载时间

在 Golang 中有没有办法获取这类信息?我目前正在使用 http.Client,并且可以测量响应时间,这工作正常,但我更想要的是 TTFB 和完整页面加载时间。

希望有人能帮助我。

3 回复

非常感谢您的回复,我会查看那个包,否则我会尝试使用无头浏览器。

更多关于Golang获取外部页面的TTFP和完全加载时间等性能指标的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我刚开始学习 Go 语言编程,但遇到了这个模块:httptrace package - net/http/httptrace - Go Packages

它似乎能够追踪连接过程中每个步骤所花费的时间。但当然,它没有“页面完全加载”这样的事件,因为爬虫本身无法做到这一点,真正专业地实现这一点确实需要一个(无头)浏览器。

据我所知,使用 http.Client 的 Go 语言程序只是调用这一个资源,不会获取其所有子资源,也不会渲染任何内容或运行 JavaScript。

或许可以试试:GitHub - go-rod/rod: A Devtools driver for web automation and scraping

在Golang中获取外部页面的TTFB和完全加载时间需要使用支持完整页面加载分析的库。以下是使用chromedp的解决方案:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/chromedp/chromedp"
)

func main() {
    // 创建上下文
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()

    // 设置超时
    ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
    defer cancel()

    var ttfb, loadTime float64
    
    // 监听性能指标
    chromedp.ListenTarget(ctx, func(ev interface{}) {
        switch e := ev.(type) {
        case *chromedp.EventPerformanceMetrics:
            for _, metric := range e.Metrics {
                if metric.Name == "TimeToFirstByte" {
                    ttfb = metric.Value
                }
                if metric.Name == "LoadEventEnd" {
                    loadTime = metric.Value
                }
            }
        }
    })

    // 执行页面导航并收集指标
    err := chromedp.Run(ctx,
        chromedp.Navigate("https://google.com"),
        chromedp.WaitReady("body"),
        chromedp.Sleep(2*time.Second), // 确保页面完全加载
    )
    
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("TTFB: %.2fms\n", ttfb)
    fmt.Printf("完全加载时间: %.2fms\n", loadTime)
}

如果需要更详细的性能指标,可以使用Performance API:

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "time"

    "github.com/chromedp/chromedp"
)

type PerformanceTiming struct {
    ConnectStart         float64 `json:"connectStart"`
    ConnectEnd           float64 `json:"connectEnd"`
    DomainLookupStart    float64 `json:"domainLookupStart"`
    DomainLookupEnd      float64 `json:"domainLookupEnd"`
    RequestStart         float64 `json:"requestStart"`
    ResponseStart        float64 `json:"responseStart"`
    ResponseEnd          float64 `json:"responseEnd"`
    LoadEventStart       float64 `json:"loadEventStart"`
    LoadEventEnd         float64 `json:"loadEventEnd"`
}

func main() {
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()
    
    ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
    defer cancel()

    var timingJSON string
    var timing PerformanceTiming
    
    err := chromedp.Run(ctx,
        chromedp.Navigate("https://google.com"),
        chromedp.WaitReady("body"),
        chromedp.Sleep(2*time.Second),
        chromedp.Evaluate(`
            JSON.stringify(window.performance.timing)
        `, &timingJSON),
    )
    
    if err != nil {
        log.Fatal(err)
    }

    if err := json.Unmarshal([]byte(timingJSON), &timing); err != nil {
        log.Fatal(err)
    }

    // 计算TTFB(响应开始时间 - 请求开始时间)
    ttfb := timing.ResponseStart - timing.RequestStart
    
    // 计算完全加载时间(加载事件结束时间 - 导航开始时间)
    // 注意:需要从performance.timing.navigationStart获取导航开始时间
    var navigationStart float64
    chromedp.Run(ctx,
        chromedp.Evaluate(`
            window.performance.timing.navigationStart
        `, &navigationStart),
    )
    
    fullLoadTime := timing.LoadEventEnd - navigationStart

    fmt.Printf("TTFB: %.2fms\n", ttfb)
    fmt.Printf("DNS查询时间: %.2fms\n", timing.DomainLookupEnd - timing.DomainLookupStart)
    fmt.Printf("TCP连接时间: %.2fms\n", timing.ConnectEnd - timing.ConnectStart)
    fmt.Printf("完全加载时间: %.2fms\n", fullLoadTime)
}

对于简单的HTTP请求TTFB测量,可以使用标准库:

package main

import (
    "fmt"
    "net/http"
    "time"
)

func measureTTFB(url string) (time.Duration, error) {
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return 0, err
    }

    start := time.Now()
    
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return 0, err
    }
    defer resp.Body.Close()

    // 读取第一个字节的时间
    buf := make([]byte, 1)
    _, err = resp.Body.Read(buf)
    if err != nil {
        return 0, err
    }

    return time.Since(start), nil
}

func main() {
    ttfb, err := measureTTFB("https://google.com")
    if err != nil {
        fmt.Printf("错误: %v\n", err)
        return
    }
    
    fmt.Printf("TTFB: %v\n", ttfb)
}

安装依赖:

go get -u github.com/chromedp/chromedp

chromedp方案提供了最准确的完全加载时间测量,因为它模拟了真实浏览器的完整页面加载过程。

回到顶部