go-zero http 请求流程简析

开始

var c config.Config  //配置
ctx := svc.NewServiceContext(c)
server := rest.MustNewServer(c.RestConf) //生成server
handler.RegisterHandlers(server, ctx) //路由注册
server.Start() //启动http 服务

上面的代码是 go-zero 自带的 goctl 工具自动生成的代码。

初始化 Server

server := rest.MustNewServer(c.RestConf)

说明:engine 和 router 后面再介绍,先来看看整体流程

注册路由

可以看到有一个 rest.Route 的 struct:

所有的路由都通过这种方式注册,这部分由 goctl 自动生成,减轻了不少工作量。

Route 包含三个属性:

Method:http 请求方式:post/get 等;

Path:就是 url 后面的自愿路径;

Handler:是实际处理器,请求最终会根据路由而执行不同的 handler,这个是 go 官方 net/http 里面定义的,所以 go-zero 的 http 也是在 net/http 基础上实现的。

启动 http 服务:server.Start ()

Start () 的具体实现是调用了初始化时 engin 的 start,继续往下看:

// StartHttp starts a http server.
func StartHttp(host string, port int, handler http.Handler, opts ...StartOption) error {
	return start(host, port, handler, func(srv *http.Server) error {
		return srv.ListenAndServe()
	}, opts...)
}

//具体的启动方法
func start(host string, port int, handler http.Handler, run func(srv *http.Server) error,
	opts ...StartOption) (err error) {
    //net/http 包的Server
	server := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", host, port),
		Handler: handler,//go-zero 的路由系统,
	}
	for _, opt := range opts {
		opt(server)
	}

	waitForCalled := proc.AddWrapUpListener(func() {
		if e := server.Shutdown(context.Background()); err != nil {
			logx.Error(e)
		}
	})
	defer func() {
		if err == http.ErrServerClosed {
			waitForCalled()
		}
	}()

	return run(server) //实质是执行:http.Server.ListenAndServe()
}

作为对比,我们看看原始 net/http 开启 http:

http.HandleFunc("/api/v1/user", func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(501)
	w.Write([]byte("error msg."))
})
http.ListenAndServe(":8081", nil)

//http.ListenAndServe本质上也是用http.Server.ListenAndServe()
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

到这里,也就完成了 go-zero http 服务启动,最终是由 net/http 去完成启动,go-zero 加入了自己的路由系统代替默认的路由,因此需要的时候我们也可以参考实现自己的路由系统,从而撸出一个自己的 go web 框架。

go-zero 路由系统

回到上面的 NewServer,注意到有:

server := &Server{
	ngin:   newEngine(c),
	router: router.NewRouter(),
}

进 router.NewRouter 看看

// NewRouter returns a httpx.Router.
func NewRouter() httpx.Router {
	return &patRouter{
		trees: make(map[string]*search.Tree),
	}
}

// Router interface represents a http router that handles http requests.
type Router interface {
	http.Handler
	Handle(method, path string, handler http.Handler) error
	SetNotFoundHandler(handler http.Handler)
	SetNotAllowedHandler(handler http.Handler)
}

type patRouter struct {
	trees      map[string]*search.Tree  //key是http method,路由就放入search.Tree里面
	notFound   http.Handler
	notAllowed http.Handler
}

可以看到最终的路由是有一个 patRouter 的结构体,实现了 Router 接口的相关方法,而所有的路由都放在一个按不同 http method 区分的 search.Tree 里面

这个 search.Tree 是变种前缀树:

当有新的 http 请求进来后就会通过这树找到对应的 Handler,然后进行处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
go-zero是一个开源的Go语言框架,它在构建微服务和高并发应用方面具有突破性的优势。其中一个突出的特点就是它整合了masterminds/squirrel,从而实现了优雅的多数据库支持。 masterminds/squirrel是一个流行的SQL查询构建器,它以非常直观和灵活的方式提供了编写SQL查询的功能。而go-zero在此基础上做了进一步的封装和优化,使得使用者能够更加方便地编写和执行SQL查询。 首先,go-zero提供了一组简洁而强大的API,使得构建SQL查询非常容易。开发者只需要按照一定的约定来创建查询参数和条件,然后使用go-zero提供的API来构建查询语句,即可完成复杂的SQL查询。 其次,go-zero还增加了一些高级功能,进一步提升了多数据库查询的灵活性和性能。例如,它支持数据库连接池管理,可以动态调整数据库连接数以适应并发请求;还支持分表分库功能,可以按照一定的规则将数据分散存储在不同的数据库或表中,从而提高查询效率。 最重要的是,go-zero通过内置的代码生成工具,提供了自动化生成数据库访问代码的能力。开发者只需要定义数据表的结构,然后运行代码生成工具,就能够自动生成包含增删改查等一系列数据库操作的代码。这极大地提高了开发效率,减少了出错的机会。 综上所述,go-zero整合了masterminds/squirrel,通过提供简洁强大的API、高级功能和自动化代码生成工具,实现了优雅的多数据库支持。它在微服务和高并发应用场景下的表现突出,为开发者提供了极大的便利和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值