Golang HTTP客户端Server-Timing头部处理插件库client-timing使用指南
Server-Timing头部允许服务器在响应中传递性能指标数据,client-timing是一个用于处理这些数据的Golang库。
安装client-timing
go get github.com/posener/client-timing
基本使用方法
1. 创建带Timing的HTTP客户端
package main
import (
"fmt"
"net/http"
"time"
"github.com/posener/client-timing"
)
func main() {
// 创建基础HTTP客户端
client := &http.Client{
Timeout: 10 * time.Second,
}
// 包装客户端以支持Timing
timingClient := clienttiming.NewClient(client)
// 创建请求
req, err := http.NewRequest("GET", "https://example.com", nil)
if err != nil {
panic(err)
}
// 发送请求并获取响应
resp, err := timingClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 获取Timing信息
timing := clienttiming.Timing(resp)
fmt.Printf("Timing metrics: %v\n", timing.Metrics())
}
2. 解析Server-Timing头部
Server-Timing头部格式示例:
Server-Timing: miss, db;dur=53, app;dur=47.2
解析代码:
// 获取并解析Server-Timing头部
if timing := clienttiming.Timing(resp); timing != nil {
metrics := timing.Metrics()
for _, metric := range metrics {
fmt.Printf("Metric: %s, Duration: %v, Description: %s\n",
metric.Name,
metric.Duration,
metric.Description)
}
}
3. 自定义处理Timing数据
// 自定义处理函数
func processTiming(resp *http.Response) {
timing := clienttiming.Timing(resp)
if timing == nil {
return
}
// 获取所有指标
metrics := timing.Metrics()
// 计算总服务器处理时间
var total time.Duration
for _, m := range metrics {
total += m.Duration
}
fmt.Printf("Total server processing time: %v\n", total)
// 查找特定指标
for _, m := range metrics {
if m.Name == "db" {
fmt.Printf("Database query took: %v\n", m.Duration)
}
}
}
高级用法
1. 自定义HTTP Transport
transport := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
}
client := &http.Client{
Transport: transport,
Timeout: 10 * time.Second,
}
// 包装自定义Transport
timingClient := clienttiming.NewClient(client)
2. 与context集成
func fetchWithTiming(ctx context.Context, url string) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := timingClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// 处理Timing数据
processTiming(resp)
return nil
}
3. 记录客户端请求时间
// 在请求前记录开始时间
start := time.Now()
resp, err := timingClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// 计算总请求时间
totalTime := time.Since(start)
// 获取服务器端时间
serverTiming := clienttiming.Timing(resp)
if serverTiming != nil {
fmt.Printf("Total request time: %v (client) + %v (server)\n",
totalTime - serverTiming.Total(),
serverTiming.Total())
}
实际应用示例
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/posener/client-timing"
)
func main() {
// 创建带Timing的客户端
client := clienttiming.NewClient(http.DefaultClient)
// 测试URL - 可以使用任何返回Server-Timing头部的服务
url := "https://httpbin.org/response-headers?Server-Timing=miss%2C+db%3Bdur%3D53%2C+app%3Bdur%3D47.2"
// 发送请求
resp, err := client.Get(url)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 解析Timing数据
timing := clienttiming.Timing(resp)
if timing == nil {
log.Fatal("No Server-Timing header found")
}
// 打印所有指标
fmt.Println("Server Timing Metrics:")
for _, metric := range timing.Metrics() {
fmt.Printf("- %s: %v", metric.Name, metric.Duration)
if metric.Description != "" {
fmt.Printf(" (%s)", metric.Description)
}
fmt.Println()
}
// 计算总服务器处理时间
fmt.Printf("\nTotal server processing time: %v\n", timing.Total())
}
注意事项
- 不是所有服务器都支持Server-Timing头部
- 生产环境中应考虑添加错误处理和日志记录
- 对于性能敏感的应用程序,注意Timing处理的开销
- 某些代理服务器可能会移除或修改Server-Timing头部
通过client-timing库,你可以方便地在Golang应用中收集和分析服务器性能指标,这对于性能监控和优化非常有价值。