go工具库:hertz api框架 hertz client的使用

发布于:2025-06-08 ⋅ 阅读:(15) ⋅ 点赞:(0)

介绍

Hertz 是 字节跳动(ByteDance)开源的高性能 Golang 微服务框架,用于构建 Web 服务,特别适合对性能要求极高的场景。

基于字节内部自研的网络库 netpoll,具备极低的延迟和高并发能力。

对比标准库 net/http,在 QPS、RT、内存占用等指标上表现更优秀。

灵活易用
支持中间件机制,兼容 Gin 风格。

可插拔的组件设计,便于自定义协议栈、序列化方式、拦截器等。

支持自动路由注册(借助 IDL 工具)。

全面功能
路由、请求解析、响应封装

自动生成 HTTP 服务代码(结合 Kitex 使用)

内建 metrics、pprof、tracing、限流、熔断、超时等能力

多种序列化支持:JSON、Protobuf、Thrift、MsgPack 等

微服务友好
适配 CloudWeGo 微服务生态,和 Kitex 天然集成。

支持服务注册、发现、链路追踪等。

一个示例:

package main

import (
    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/app/server"
)

func main() {
    h := server.Default()

    h.GET("/ping", func(c context.Context, ctx *app.RequestContext) {
        ctx.JSON(200, map[string]string{
            "message": "pong",
        })
    })

    h.Spin()
}

创建client

创建一个标准的client
纯净的golang http client,sdk 一般用这个

package main


func main() {
   c, err := client.NewClient()
   // your code after this
}

使用配置创建标准的client

package main

import (
   "time"

)

func main() {
   c, err := client.NewClient(client.WithDialTimeout(1 * time.Second))
   //your code after this
}

支持的配置项

Hertz Client 配置表

配置名称 类型 说明
WithDialTimeout time.Duration 建立连接超时时间,默认值:1000ms
WithMaxConnsPerHost int 单个 ip:port 的最大连接数,默认 512
WithMaxIdleConnDuration time.Duration 长连接的最大空闲时间,默认 10s
WithMaxConnDuration time.Duration 长连接的最大存在时间,默认无限
WithMaxConnWaitTimeout time.Duration 最大等待连接时长,默认不等待
WithKeepAlive bool 设置是否使用长连接,默认为 true
WithMaxIdemponentCallAttempts int 幂等调用的最大尝试次数,默认为 5
(内部版本 < 1.7.0,外部版本 < 0.4.0)
WithClientReadTimeout time.Duration 读取 response 的最长时间,默认无限
WithWriteTimeout time.Duration 写超时,默认无限(外部版本 > v1.7.0)
WithDialer(standard.NewDialer()) network.Dialer 底层网络库 dialer,默认 netpoll.NewDialer()。设置为 standard.NewDialer() 会使用 Golang 原生 dialer。
⚠️ Netpoll 不支持 TLS,因此使用 TLS 时需切换到标准库
WithTLSConfig *tls.Config 用于发送 HTTPS 请求,设置该配置会自动将 dialer 切换为标准库
WithResponseBodyStream bool 是否使用流式读取 response body
WithRetryConfig ...retry.Option 设置 Client 的 retry 配置
(内部版本 >= 1.7.0,外部版本 >= 0.4.0)
WithRequestTimeout time.Duration 设置请求超时。注意Do 方法搭配此选项不会与 mesh 联动,mesh 默认超时为 4s,最终取较短者。如需联动应使用 DoTimeout / DoDeadline
WithDisablePathNormalizing bool 是否禁用 URL 归一化,默认开启归一化。设置为 true 可使用原始 URL 发送请求

使用配置创建byted client

package main

import (
   "time"

)

func main() {
   c, err := byted.NewClient(byted.WithAppClientOptions(client.WithDialTimeout(1 * time.Second)))
}

支持的配置项

配置名称 类型 说明
WithAppClientOptions ...config.ClientOption 设置标准的 client 配置,详情见「Client API 示例」
WithEnableTracing bool 是否开启 trace,默认为 true
WithEnableSpanLog bool 是否为每次请求打印日志,默认为 true
WithEnableSpanMetrics bool 是否为每次请求打印 metrics,默认为 true
WithDumpRequest bool 是否在 trace span 上记录请求体和 URL 参数,默认为 false
WithSlowRequestThreshold time.Duration 如果请求时间超过该值,trace 将强制采样
WithLoadBalancer loadbalance.Loadbalancer 使用自定义负载均衡,详情见「服务发现 & 负载均衡」
WithDisableDefaultDiscovery bool 禁用默认服务发现中间件,详情见「服务发现 & 负载均衡」
WithHostPorts ...discovery.Instance 指定 client 访问的下游实例,详情见「服务发现 & 负载均衡」
WithToMethodTagDecider (类型未指定) 指定 client 上报 method tag 的方法

发起请求

  1. Do
    func (c *Client) Do(ctx context.Context,req *Request, resp Response) error
    Do会发送请求并将响应内容写入resp中,该函数不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    package main
import (
   "context"
   "fmt"

  
)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.Do(context.Background(), req, res)
   if err != nil {
      return
   }
   fmt.Printf("%v", string(res.Body())) //读取响应body
}
  1. DoDeadline
    func (c *Client) DoDeadline(ctx context.Context,req *Request, resp Response, deadline time.Time) error
    DoDeadline会发送请求并将响应内容写入resp中,如果在给定截止日期(deadline)后没有响应则会返回github.com/cloudwego/hertz/pkg/common/errors 下的 error.ErrTimeout 错误。该方法不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    该方法会和 Mesh 的超时联动

package main

import (
   "context"
   "fmt"
   "time"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)         //设置请求方法
   req.SetRequestURI("http://example.com") //设置请求url
   c.DoDeadline(context.Background(), req, res, time.Now().Add(1*time.Second))
   fmt.Printf("%v\n", string(res.Body()))
}
  1. DoRedirects
    func (c *Client) DoRedirects(ctx context.Context,req *Request, resp *Response, maxRedirectsCount int) error
    Hertz Client DoRedirects 接口预期外 404
    DoRedirects与Do的区别是它支持重定向跳转,当重定向次数超过maxRedirectsCount时会返回error
package main

import (
   "context"
   "fmt"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.DoRedirects(context.Background(), req, res, 1)
   if err != nil {
      return
   }
   fmt.Printf("%v\n", string(res.Body())) //读取响应body
}
  1. DoTimeout
    func (c *Client) DoTimeout(ctx context.Context,req *Request, resp Response, timeout time.Duration) error
    DoTimeout发送给定的请求并将响应内容写入resp中,如果在给定超时时间(timeout)后没有响应则会返回timeout错误。该方法不支持重定向跳转,如要使用,请使用DoRedirects或者Get
    方法
    该方法会和 Mesh 的超时联动,这个超时会传递给 mesh,以代码超时为准
package main

import (
   "context"
   "fmt"
   "time"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.SetMethod(consts.MethodGet)                            //设置请求方法
   req.Header.SetContentTypeBytes([]byte("application/json")) //设置请求header
   req.SetRequestURI("http://example.com")                    //设置请求url
   err = c.DoTimeout(context.Background(), req, res, 1*time.Second)
   if err != nil {
      return
   }
   fmt.Printf("%v\n", string(res.Body())) //读取响应body
}
  1. Get
    func (c *Client) Get(ctx context.Context,dst []byte, url string) (statusCode int, body []byte, err error)
    Get会根据url返回相应的状态码和响应body;dst会被替换成响应body(响应的body会赋值给dst),如果dst太小会分配一个新的slice;该方法支持重定向跳转
package main

import (
   "context"
   "fmt"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.Get(context.Background(), nil, "http://google.com")
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. GetDeadline
    func (c *Client) GetDeadline(ctx context.Context,dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error)
    GetDeadline会根据url返回相应的状态码和响应body;如果在给定截止日期(deadline)后没有响应则会返回timeout错误,dst会被替换成响应请求body,如果dst太小会分配一个新的slice;该方法支持重定向跳转
package main

import (
   "context"
   "fmt"
   "time"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.GetDeadline(context.Background(), nil, "http://google.com", time.Now().Add(1*time.Second))
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. GetTimeout
    func (c *Client) GetTimeout(ctx context.Context,dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error)
    GetTimeout会根据url返回相应的状态码和响应body;如果在给定超时时间(timeout)后没有响应则会返回hertz.ErrTimeout错误,dst会被替换成响应请求body,如果dst太小会分配一个新的slice;该方法支持重定向跳转
package main

import (
   "context"
   "fmt"
   "time"

)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }
   status, body, _ := c.GetTimeout(context.Background(), nil, "http://google.com", 1*time.Second)
   fmt.Printf("status=%v body=%v\n", status, string(body))
}
  1. Post
    func (c *Client) Post(ctx context.Context,dst []byte, url string, postArgs *Args) (statusCode int, body []byte, err error)
    Post会根据url和post参数发送post请求,dst会被替换成响应请求body(响应的body会赋值给dst),如果dst太小会分配一个新的slice;该方法支持重定向跳转;使用的content-type是application/x-www-url-form
package main

import (
   "context"
   "fmt"


)

func main() {
   c, err := byted.NewClient()
   if err != nil {
      return
   }

   var postArgs protocol.Args
   postArgs.Set("arg", "a") //设置post请求参数
   status, body, _ := c.Post(context.Background(), nil, "http://google.com", &postArgs)
   fmt.Printf("status=%v body=%v\n", status, string(body))
}

发起multipart/form-data请求

package main

import (
   "context"

  
)

func main() {
   client, err := byted.NewClient()
   if err != nil {
      return
   }
   req := &protocol.Request{}
   res := &protocol.Response{}
   req.Header.SetMethod(consts.MethodPost) //设置请求方法
   req.SetRequestURI("http://example.com") //设置请求url
   req.SetMultipartFormData(map[string]string{
      "msg": "test message",
   })
   err = client.Do(context.Background(), req, res)
   return
}

网站公告

今日签到

点亮在社区的每一天
去签到