page contents

Golang之Web编程执行流程

为什么Golang做Web编程比其他语言并发高: Go是通过一个函数ListenAndServe来处理这些事情的,这个底层其实这样处 理的:初始化一个server对象,然后调用了net.Listen("tcp", addr),也就是底层...

attachments-2021-07-KywZD0kI60f4e314dde96.png

为什么Golang做Web编程比其他语言并发高:

Go是通过一个函数ListenAndServe来处理这些事情的,这个底层其实这样处 理的:初始化一个server对象,然后调用了net.Listen("tcp", addr),也就是底层用TCP协议搭建了一个服 务,然后监控我们设置的端口。

下面代码来自Go的http包的源码,通过下面的代码我们可以看到整个的http处理过程:

func (srv *Server) Serve(l net.Listener) error {
    defer l.Close()
    var tempDelay time.Duration // how long to sleep on accept failure
    for {
        rw, e := l.Accept() 
        if e != nil {
            if ne, ok := e.(net.Error); ok && ne.Temporary() { 
                if tempDelay == 0 {
                tempDelay = 5 * time.Millisecond 
                } else {
                tempDelay *= 2 
                }
                if max := 1 * time.Second; tempDelay > max {
                 tempDelay = max
                }
                log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay) 
                time.Sleep(tempDelay)
                continue
            }
            return e 
        }
        tempDelay = 0
        if srv.ReadTimeout != 0 {
            rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout)) 
        }
        if srv.WriteTimeout != 0 {
            rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
        }
        c, err := srv.newConn(rw) if err != nil {
            continue 
        }
        go c.serve()
    }
    panic("not reached")
}

监控之后如何接收客户端的请求呢?上面代码执行监控端口之后,调用了srv.Serve(net.Listener)函数,这个 函数就是处理接收客户端的请求信息。这个函数里面起了一个for{},首先通过Listener接收请求,其次创建一个 Conn,最后单独开了一个goroutine,把这个请求的数据当做参数扔给这个conn去服务:go c.serve()。这个就是 高并发体现了,用户的每一次请求都是在一个新的goroutine去服务,相互不影响。

那么如何具体分配到相应的函数来处理请求呢?conn首先会解析request:c.readRequest(),然后获取相应的 handler:handler := c.server.Handler,也就是我们刚才在调用函数ListenAndServe时候的第二个参数, 我们前面例子传递的是nil,也就是为空,那么默认获取handler = DefaultServeMux,那么这个变量用来做什么 的呢?对,这个变量就是一个路由器,它用来匹配url跳转到其相应的handle函数,那么这个我们有设置过吗?有,我 们调用的代码里面第一句不是调用了http.HandleFunc("/", sayhelloName)嘛。这个作用就是注册了请求/的 路由规则,当请求uri为"/",路由就会转到函数sayhelloName,DefaultServeMux会调用ServeHTTP方法,这个方法内 部其实就是调用sayhelloName本身,最后通过写入response的信息反馈到客户端。

Go代码的执行流程 通过对http包的分析之后,现在让我们来梳理一下整个的代码执行过程。

首先调用Http.HandleFunc

按顺序做了几件事:

1 调用了DefaultServerMux的HandleFunc

2 调用了DefaultServerMux的Handle

3 往DefaultServeMux的map[string]muxEntry中增加对应的handler和路由规则 其次调用http.ListenAndServe(":9090", nil)

按顺序做了几件事情:

1 实例化Server

2 调用Server的ListenAndServe()

3 调用net.Listen("tcp", addr)监听端口

4 启动一个for循环,在循环体中Accept请求

5 对每个请求实例化一个Conn,并且开启一个goroutine为这个请求进行服务go c.serve()

6 读取每个请求的内容w, err := c.readRequest()

7 判断handler是否为空,如果没有设置handler(这个例子就没有设置handler),handler就设置为 DefaultServeMux

8 调用handler的ServeHttp

9 在这个例子中,下面就进入到DefaultServerMux.ServeHttp

10 根据request选择handler,并且进入到这个handler的ServeHTTP mux.handler(r).ServeHTTP(w, r)

11 选择handler:

    A 判断是否有路由能满足这个request(循环遍历ServerMux的muxEntry)

    B 如果有路由满足,调用这个路由handler的ServeHttp

    C 如果没有路由满足,调用NotFoundHandler的ServeHttp

attachments-2021-07-OI1HOmES60f4e27c100f2.jpg

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-BI5wTj7k62ad4233086ec.jpeg

  • 发表于 2021-07-19 10:27
  • 阅读 ( 451 )
  • 分类:Golang

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章