基本特性
Engine
server.Hertz 是 Hertz 的核心类型,它由 route.Engine 以及 signalWaiter 组成,Hertz 服务器的启动、路由注册、中间件注册以及退出等重要方法均包含在 server.Hertz 中。以下是 server.Hertz 的定义:
type Hertz struct { *route.Engine // 用于接收信号以实现优雅退出 signalWaiter func (err chan error) error }
配置信息
配置项 | 默认值 | 说明 |
WithTransport | network.NewTransporter | 更换底层 transport |
WithHostPorts | :8888 | 指定监听的地址和端口 |
WithKeepAliveTimeout | 1min | tcp 长连接保活时间,一般情况下不用修改,更应该关注 idleTimeout |
WithReadTimeout | 3min | 底层读取数据超时时间 |
WithIdleTimeout | 3min | 长连接请求链接空闲超时时间 |
WithMaxRequestBodySize | 4 * 1024 * 1024 | 配置最大的请求体大小 |
WithRedirectTrailingSlash | true | 自动根据末尾的 / 转发,例如:如果 router 只有 /foo/,那么 /foo 会重定向到 /foo/ ;如果只有 /foo,那么 /foo/ 会重定向到 /foo |
WithRemoveExtraSlash | false | RemoveExtraSlash 当有额外的 / 时也可以当作参数。如:user/:name,如果开启该选项 user//xiaoming 也可匹配上参数 |
WithUnescapePathValues | true | 如果开启,请求路径会被自动转义(eg. ‘%2F’ -> ‘/')。如果 UseRawPath 为 false(默认情况),则 UnescapePathValues 实际上为 true,因为 .URI().Path() 将被使用,它已经是转义后的。设置该参数为 false,需要配合 WithUseRawPath(true) |
WithUseRawPath | false | 如果开启,会使用原始 path 进行路由匹配 |
WithHandleMethodNotAllowed | false | 如果开启,当当前路径不能被匹配上时,server 会去检查其他方法是否注册了当前路径的路由,如果存在则会响应"Method Not Allowed",并返回状态码 405; 如果没有,则会用 NotFound 的 handler 进行处理 |
WithDisablePreParseMultipartForm | false | 如果开启,则不会预处理 multipart form。可以通过 ctx.Request.Body() 获取到 body 后由用户处理 |
WithStreamBody | false | 如果开启,则会使用流式处理 body |
WithNetwork | “tcp” | 设置网络协议,可选:tcp,udp,unix(unix domain socket),默认为 tcp |
WithExitWaitTime | 5s | 设置优雅退出时间。Server 会停止建立新的连接,并对关闭后的每一个请求设置 Connection: Close 的 header,当到达设定的时间关闭 Server。当所有连接已经关闭时,Server 可以提前关闭 |
WithTLS | nil | 配置 server tls 能力,详情可见 TLS |
WithListenConfig | nil | 设置监听器配置,可用于设置是否允许 reuse port 等 |
WithALPN | false | 是否开启 ALPN |
WithTracer | []interface{}{} | 注入 tracer 实现,如不注入 Tracer 实现,默认关闭 |
WithTraceLevel | LevelDetailed | 设置 trace level |
WithWriteTimeout | 无限长 | 写入数据超时时间 |
WithRedirectFixedPath | false | 如果开启,当当前请求路径不能匹配上时,server 会尝试修复请求路径并重新进行匹配,如果成功匹配并且为 GET 请求则会返回状态码 301 进行重定向,其他请求方式返回 308 进行重定向 |
WithBasePath | / | 设置基本路径,前缀和后缀必须为 / |
WithMaxKeepBodySize | 4 * 1024 * 1024 | 设置回收时保留的请求体和响应体的最大大小。单位:字节 |
WithGetOnly | false | 如果开启则只接受 GET 请求 |
WithKeepAlive | true | 如果开启则使用 HTTP 长连接 |
WithAltTransport | network.NewTransporter | 设置备用 transport |
WithH2C | false | |
WithReadBufferSize | 4 * 1024 | 设置读缓冲区大小,同时限制 HTTP header 大小 |
WithRegistry | registry.NoopRegistry, nil | 设置注册中心配置,服务注册信息 |
WithAutoReloadRender | false, 0 | 设置自动重载渲染配置 |
WithDisablePrintRoute | false | 设置是否禁用 debugPrintRoute |
WithOnAccept | nil | 设置在 netpoll 中当一个连接被接受但不能接收数据时的回调函数,在 go net 中在转换 TLS 连接之前被调用 |
WithOnConnect | nil | 设置 onConnect 函数。它可以接收来自 netpoll 连接的数据。在 go net 中,它将在转换 TLS 连接后被调用 |
WithDisableHeaderNamesNormalizing | false | 设置是否禁用 Request 和 Response Header 名字的规范化 (首字母和破折号后第一个字母大写) |
初始化服务
// Default 用于初始化服务,默认使用了 Recovery 中间件以保证服务在运行时不会因为 panic 导致服务崩溃。 func Default(opts ...config.Option) *Hertz // New 用于初始化服务,没有使用默认的 Recovery 中间件。 func New(opts ...config.Option) *Hertz
例子:
func main() { h := server.New() h.Spin() }
成功效果:
服务运行与退出
// Spin 函数用于运行 Hertz 服务器,接收到退出信号后可退出服务。 // 在使用 服务注册发现 的功能时,Spin 会在服务启动时将服务注册进入注册中心,并使用 signalWaiter 监测服务异常。 func (h *Hertz) Spin() // Run 函数用于运行 Hertz 服务器,接收到退出信号后可退出服务。该函数不支持服务的优雅退出,除非有特殊需求,不然一般使用 Spin 函数用于运行服务。 func (engine *Engine) Run() (err error) // SetCustomSignalWaiter 函数用于自定义服务器接收信号后的处理函数,若没有设置自定义函数,Hertz 使用 waitSignal 函数作为信号处理的默认实现方式, func (h *Hertz) SetCustomSignalWaiter(f func(err chan error) error)
中间件
func (engine *Engine) Use(middleware ...app.HandlerFunc) IRoutes
Use 函数用于将中间件注册进入路由。
Hertz 支持用户自定义中间件,Hertz 已经实现了一些常用的中间件,详情见 hertz-contrib。
Hertz 支持的中间件的使用方法包括全局注册、路由组级别和单一路由级别的注册。
Use 函数中 middleware 的形参必须为 app.HandlerFunc 的 http 处理函数:
type HandlerFunc func (ctx context.Context, c *app.RequestContext)
函数签名:
func (engine *Engine) Use(middleware ...app.HandlerFunc) IRoutes
示例代码:
func main() { h := server.New() // 将内置的 Recovery 中间件注册进入路由 h.Use(recovery.Recovery()) // 使用自定义的中间件 h.Use(exampleMiddleware()) h.Spin() } func exampleMiddleware() app.HandlerFunc { return func(ctx context.Context, c *app.RequestContext) { // 在 Next 中的函数执行之前打印日志 hlog.Info("print before...") // 使用 Next 使得路由匹配的函数执行 c.Next(ctx) } }
流式处理
Hertz 支持 Server 的流式处理,包括流式读和流式写。
注意:由于 netpoll 和 go net 触发模式不同,netpoll 流式为 “伪” 流式(由于 LT 触发,会由网络库将数据读取到网络库的 buffer 中),在大包的场景下(如:上传文件等)可能会有内存问题,推荐使用 go net
流式读
代码实例
func main() { h := server.Default(server.WithHostPorts("127.0.0.1:8080"), server.WithStreamBody(true), server.WithTransport(standard.NewTransporter)) h.POST("/bodyStream", handler) h.Spin() } func handler(ctx context.Context, c *app.RequestContext) { // Acquire body streaming bodyStream := c.RequestBodyStream() // Read half of body bytes p := make([]byte, c.Request.Header.ContentLength()/2) r, err := bodyStream.Read(p) if err != nil { panic(err) } left, _ := ioutil.ReadAll(bodyStream) c.String(consts.StatusOK, "bytes streaming_read: %d\nbytes left: %d\n", r, len(left)) }
底层网络库
func (engine *Engine) GetTransporterName() (tName string) func SetTransporter(transporter func (options *config.Options) network.Transporter)
GetTransporterName
获取当前使用的网络库名称,现在有原生的 go net 和 netpoll 两种。
linux 默认使用 netpoll, windows 只能使用 go net。
如果对如何使用对应的网络库有疑惑,请查看 此处。
函数签名:
func (engine *Engine) GetTransporterName() (tName string)
示例代码:
h := server.New() tName := h.GetTransporterName()
SetTransporter
SetTransporter 用于设置网络库。
注意:SetTransporter 只设置 Engine 的全局默认值,所以在初始化 Engine 时使用 WithTransporter 来设置网络库会覆盖掉 SetTransporter 的设置。
函数签名:
func SetTransporter(transporter func (options *config.Options) network.Transporter)
示例代码:
route.SetTransporter(standard.NewTransporter)