迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Go >

Golang httptrace 的示例

作者:迹忆客 最近更新:2023/01/16 浏览次数:

httptrace 包是从 Go1.7 开始包含在 Go (Golang) 标准库中的新包。 如果我们想要监控 http 请求的性能,或者如果我们想要收集和监控有关我们的 http 客户端的统计信息,该包将非常有用。 主要思想是能够跟踪在 http 请求的生命周期内发生的一组事件。 比如dns解析、tcp连接创建、写入tcp连接的数据、从tcp连接接收到的数据等等。

在这篇文章中,我们将了解如何使用 httptrace 包来监控我们的 Go (Golang) http 请求的性能。


1. 初始化 httptrace.ClientTrace

httptrace 包的主要导出类型是 ClientTrace 结构类型。 它用于定义我们要监听的事件。 这些事件被定义为函数,也称为“钩子”。 让我们来看看其中的一些。

这是 httptrace.ClientTrace 结构的精简版

ClientTrace 是一组钩子,可在传出 HTTP 请求的各个阶段运行。 任何特定的钩子都可以是 nil

type ClientTrace struct {
    // GetConn is called before a connection is created or
    // retrieved from an idle pool. The hostPort is the
    // "host:port" of the target or proxy. GetConn is called even
    // if there's already an idle cached connection available.
    GetConn func(hostPort string)

    // GotConn is called after a successful connection is
    // obtained. There is no hook for failure to obtain a
    // connection; instead, use the error from
    // Transport.RoundTrip.
    GotConn func(GotConnInfo)

    [...]

    // DNSStart is called when a DNS lookup begins.
    DNSStart func(DNSStartInfo)

    // DNSDone is called when a DNS lookup ends.
    DNSDone func(DNSDoneInfo)

    // ConnectStart is called when a new connection's Dial begins.
    // If net.Dialer.DualStack (IPv6 "Happy Eyeballs") support is
    // enabled, this may be called multiple times.
    ConnectStart func(network, addr string)

    // ConnectDone is called when a new connection's Dial
    // completes. The provided err indicates whether the
    // connection completedly successfully.
    // If net.Dialer.DualStack ("Happy Eyeballs") support is
    // enabled, this may be called multiple times.
    ConnectDone func(network, addr string, err error)

    [...]
}

我们在 ClientTrace 中看到的每个定义的函数都是我们在 Go 中创建和发送 http 请求时想要监听的事件。 让我们使用其中一些来跟踪我们的 http 请求示例中的事件。

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    req, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
    clientTrace := &httptrace.ClientTrace{
        GetConn:      func(hostPort string) { fmt.Println("starting to create conn ", hostPort) },
        DNSStart:     func(info httptrace.DNSStartInfo) { fmt.Println("starting to look up dns", info) },
        DNSDone:      func(info httptrace.DNSDoneInfo) { fmt.Println("done looking up dns", info) },
        ConnectStart: func(network, addr string) { fmt.Println("starting tcp connection", network, addr) },
        ConnectDone:  func(network, addr string, err error) { fmt.Println("tcp connection created", network, addr, err) },
        GotConn:      func(info httptrace.GotConnInfo) { fmt.Println("connection established", info) },
    }
}

2. 使用 httptrace.WithClientTrace 创建上下文

为了使用我们的客户端跟踪指令(函数钩子),我们需要将结构附加到上下文中,该上下文稍后传递到请求上下文中并由 http 客户端使用。 我们可以使用 httptrace.WithClientTrace 函数来做到这一点

func WithClientTrace(ctx context.Context, trace *ClientTrace) context.Context

WithClientTrace 根据提供的父 ctx 返回一个新的上下文。 使用返回的上下文发出的 HTTP 客户端请求将使用提供的跟踪挂钩,以及之前使用 ctx 注册的任何挂钩。 将首先调用提供的跟踪中定义的任何挂钩。

这是我们需要添加到示例中的内容

clientTraceCtx := httptrace.WithClientTrace(req.Context(), clientTrace)

3. 将 httptrace.ClientTrace 与我们的 HTTP 客户端一起使用

我们的最终结果如下。 定义客户端跟踪钩子,使用客户端跟踪创建上下文并将其传递到我们的请求对象中。

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    req, _ := http.NewRequest(http.MethodGet, "http://example.com", nil)
    clientTrace := &httptrace.ClientTrace{
        GetConn:      func(hostPort string) { fmt.Println("starting to create conn ", hostPort) },
        DNSStart:     func(info httptrace.DNSStartInfo) { fmt.Println("starting to look up dns", info) },
        DNSDone:      func(info httptrace.DNSDoneInfo) { fmt.Println("done looking up dns", info) },
        ConnectStart: func(network, addr string) { fmt.Println("starting tcp connection", network, addr) },
        ConnectDone:  func(network, addr string, err error) { fmt.Println("tcp connection created", network, addr, err) },
        GotConn:      func(info httptrace.GotConnInfo) { fmt.Println("connection established", info) },
    }
    clientTraceCtx := httptrace.WithClientTrace(req.Context(), clientTrace)
    req = req.WithContext(clientTraceCtx)
    _, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
}

运行示例

预期结果如下

starting to create conn  example.com:80
starting to look up dns {example.com}
done looking up dns {[{93.184.216.34 } {2606:2800:220:1:248:1893:25c8:1946 }]  false}
starting tcp connection tcp 93.184.216.34:80
tcp connection created tcp 93.184.216.34:80 
connection established {0xc000010090 false false 0s}

这些只是我们可以用来在 Go 中跟踪传出 HTTP 请求的可能事件的一个子集。 但是正如我们从这个示例中看到的那样,这对于跟踪正在发生的事情和对我们的 http 客户端进行故障排除已经非常有用

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Golang 中的零值 Nil

发布时间:2023/04/27 浏览次数:166 分类:Go

本篇文章介绍 nil 在 Golang 中的含义,nil 是 Go 编程语言中的零值,是众所周知且重要的预定义标识符。

Golang 中的 Lambda 表达式

发布时间:2023/04/27 浏览次数:93 分类:Go

本篇文章介绍如何在 Golang 中创建 lambda 表达式。Lambda 表达式似乎不存在于 Golang 中。 函数文字、lambda 函数或闭包是匿名函数的另一个名称。

在 Go 中使用断言

发布时间:2023/04/27 浏览次数:181 分类:Go

本篇文章介绍了 assert 在 GoLang 中的使用。在 Go 语言中使用断言:GoLang 不提供对断言的任何内置支持,但我们可以使用来自 Testify API 的广泛使用的第三方包断言。

Go 中的随机数生成

发布时间:2023/04/27 浏览次数:114 分类:Go

本篇文章介绍如何在 Go 语言中使用随机数生成功能。Go 中的随机数生成 Go 语言为随机数生成功能提供内置支持。 内置包 math 有方法 rand(),用于随机数生成。

GoLang 电子邮件验证器

发布时间:2023/04/27 浏览次数:195 分类:Go

本篇文章介绍如何在 Go 语言中验证电子邮件。电子邮件需要特定格式; 否则,它们将无法工作。

卸载 GoLang

发布时间:2023/04/27 浏览次数:183 分类:Go

本篇文章介绍如何在不同的操作系统上卸载 GoLang。卸载 Go 语言 只需几个简单的步骤即可卸载 GoLang。 这些步骤对于不同的操作系统是不同的。

在 Go 中使用 Electron API 创建 GUI

发布时间:2023/04/27 浏览次数:124 分类:Go

本篇文章介绍如何在 Go 语言中使用 Electron API 创建 GUI。Electron API 或 Astilectron 用于为 GoLang 创建 GUI。

在 GoLang 中安装包

发布时间:2023/04/27 浏览次数:122 分类:Go

使用 Go 语言的 get 命令安装所需的包非常容易。 Go 语言提供了多种命令来执行某些任务,get 就是其中之一。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便