前面介紹了如果通過Go搭建一個web服務,我們可以看到簡單應用一個net/http包就方便的搭建起來了,那么Go在底層到底是怎么做的呢?
Web作業方式的幾個概念
以下均是服務器端的幾個概念
Request:用戶請求的資訊,用來決議用戶的請求資訊,包括post,get,cookie,url等資訊
Response:服務器需要反饋給客戶端的資訊
Conn:用戶的每次請求鏈接
Handler:處理請求和成成回傳資訊的處理邏輯
分析http包運行機制
如下圖所示,是Go實作Web服務的作業模式的流程圖

http包執行流程:
- 創建Listen Socket,監聽指定的埠,等待客戶端請求道來,
- Listen Socket接受客戶端的請求,得到Client Socket,接下來通過Client Socket與客戶端通信,
- 處理客戶端的請求,首先從Client Socket讀取HTTP請求的協議頭,如果是POST方法,還可能要讀取客戶端提交的資料,然后交給相應的Handler處理請求,Handler處理完畢準備好客戶端需要的資料,通過Client Socket寫給客戶端,
這整個的程序里面我們只要了解清楚下面三個問題,也就知道Go是如何讓web運行起來了
- 如何監聽埠?
- 如何接受客戶端請求?
- 如何分配Handler?
前面小結的代碼里我們可以看到,Go是通過一個函式ListenAndServe來處理這些事情的,這個底層其實是這樣處理的:初始化一個server物件,然后呼叫了net.Listen("tcp",addr),也就是底層用TCP協議單間了一個服務,然后監控我們設定的埠,
下面這段代碼來自Go的http包的原始碼,通過下面的代碼我們可以看到整個的http處理程序:

監控之后如何接收客戶端的請求呢?上面代碼執行監控埠之后,呼叫了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("/",sayhello)么,這個作用就是注冊了請求/的路由規則,當請求為"/",路由就會跳轉到函式sayhello,DefaultServeMux會呼叫ServeHTTP方法,這個方法內部其實就是呼叫sayhello本身,最后通過寫入response的資訊反饋到客戶端,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/227217.html
標籤:Go
