Hertz
Hertz is an ultra-large-scale enterprise-level microservice HTTP framework, featuring high ease of use, easy expansion, and low latency etc.
Hertz uses the self-developed high-performance network library Netpoll by default. In some special scenarios, Hertz has certain advantages in QPS and latency compared to go net. For performance data, please refer to the echo data below.
In internal practice, for some typical services, such as services with a high proportion of frameworks, gateways and other services, after migrating Hertz, compared to the Gin framework, the resource usage is significantly reduced. For more information, see hertz-benchmark.
Hz
Hertz provides an easy-to-use command line tool Hz. Users only need to provide an IDL. According to the defined interface information, Hz can generate project scaffolding with one click, and use Hertz out of the box; Hz also provides update capabilities. The IDL of Hz can update the scaffolding if it changes. Currently Hz supports both Thrift and Protobuf IDL definitions. The command line tool has built-in rich options that can be used according to your needs. At the same time, it relies on the official Protobuf compiler and the self-developed Thriftgo compiler at the bottom, both of which support custom generated code plugins. If you feel that the default template cannot meet the needs, you can customize the generated template.
For more information, see.
Implementation of the core structure
Hertz
To learn a framework, you must first learn its core structure, and the core structure and entry of the Hertz framework is the file hertz.go
with the same name as itself. The document is not lengthy, it can be said to be short and concise.
The core structure is at the beginning of the file with a prominent line of comments.
// Hertz is the core struct of hertz.
type Hertz struct {
*route.Engine
}
The comment means that the Hertz structure here is the core structure of the entire framework. The structure encapsulates the Engine
under route
, and the engine contains all the methods. If you want to use this framework, you must rely on this engine.
New
// New creates a hertz instance without any default config.
func New(opts ...config.Option) *Hertz {
options := config.NewOptions(opts)
h := &Hertz{
Engine: route.NewEngine(options),
}
return h
}
New is the constructor of the engine. You can create a new Engine
instance and it will not contain the default configuration, but you can customize the relevant configuration yourself, and the instance will be returned after construction.
Default
Usually we use Default
instead of New
directly in our development, because Default
will use the default middleware Recovery
, and the Gin framework will also have log middleware.
// Default creates a hertz instance with default middlewares.
func Default(opts ...config.Option) *Hertz {
h := New(opts...)
h.Use(recovery.Recovery())
return h
}
When calling the Default
function, an instance of Engine
will be created first, and the Recovery
middleware will be used. The implementation of Recovery
is very simple. Use defer
to mount the error recovery function, and call recover
in this function (), catch panic, and print the stack information in the log, returning Internal Server Error to the user. It is possible to avoid the entire program terminating due to panic.
In addition, Default
also supports custom configuration information.
In the code implementation, we will first make a channel and run a goroutine to wait for receiving information. When receiving the closing signal, we will gracefully close the program. And about the waitSignal among them, we will continue to interpret it below.
SetCustomSignalWaiter
SetCustomSignalWaiter
sets the signal waiter function. If Default one is not met the requirement, set this function to customize. Hertz will exit immediately if f returns an error, otherwise it will exit gracefully.
func (h *Hertz) SetCustomSignalWaiter(f func(err chan error) error) {
h.signalWaiter = f
}
waitSignal
In this function, we will wait for the signal and have a select to correspond to the next operation, including forced exit and graceful exit, and err will be returned if there is an error.
func waitSignal(errCh chan error) error {
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGHUP, syscall.SIGTERM)
select {
case sig := <-signals:
switch sig {
case syscall.SIGTERM:
// force exit
return errors.New(sig.String()) // nolint
case syscall.SIGHUP, syscall.SIGINT:
// graceful shutdown
return nil
}
case err := <-errCh:
return err
}
return nil
}
Summary
After that, we have already read the source code of hertz.go
, but there may still be some things that you don't understand if you only see the source code. Next, we will use the example of CloudWeGo to further see how it is used.
Example
Let's look directly at hertz-examples/hello/main.go
.
package main
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
func main() {
// server.Default() creates a Hertz with recovery middleware.
// If you need a pure hertz, you can use server.New()
h := server.Default()
h.GET("/hello", func(ctx context.Context, c *app.RequestContext) {
c.String(consts.StatusOK, "Hello hertz!")
})
h.Spin()
}
Entering the first line of the main function tells that using Default
will have its own error recovery middleware. If you want a pure instance, please use New
. Next he calls server.Default()
, which is followed by a route for a GET request, which prints "Hello hertz!". Finally called Spin()
, waiting for the signal.
Summary
You can check out the cloudwego/hertz for more information. I'm sure the documentation has answers to all your questions.
Top comments (0)