1. 程式人生 > >Golang-web基礎

Golang-web基礎

conn face .net ace href 處理 exp block 高性能

1. Golang-web工作機制

1.web工作方式:

瀏覽器URL –> 請求DNS服務器 ->解析域名到對應的IP –> 建立TCP協議 –>發送Http Request –>Web服務器處理請求 –>Http Response返回客戶端 –>渲染響應體 –>呈現給用戶UI界面

2.Http請求

GET請求: http://xx.xx.com?name=test1&id=123 //用?分隔URL和傳輸數據,參數之間用&連接 URL有長度限制、明文傳輸,參數在URL中。

3.http響應

狀態碼:1XX:請求被接收,繼續處理 2XX:成功,請求已經被成功處理 3XX:重定向 4XX:客戶端錯誤 5XX:服務器端錯誤

4.http包運行的流程:

(1.)創建Listen Socket 監聽指定端口,等待客戶端的請求到來。

(2.)ListenSocket 接收客戶端的請求,得到Client Socket,通過Client Socket與客戶端通信。

(3.)處理客戶端的請求,首先從Client Socket讀取Http請求的協議頭,如果是post請求,還需要讀取客戶端提交的數據,然後交給相應的handler處理請求,handler處理完後,將數據返回給客戶端。

(4.)具體實現:

初始化一個server, 調用 net.Listen(“tcp”,addr) 監控端口 ,srv.Serve(net.Listener)接收客戶端的請求信息。創建連接,執行gorouting

(5.) Go http的兩個核心功能,conn和ServMux,實現高並發和高性能。

srv.netConn(rw) //每次請求都會創建一個連接,這個鏈接中保存了這次請求的信息,並將該信息傳遞給對應的handler,handler讀取響應的header信息。這樣就保持了每個請求的獨立性。

go c.serve()

type ServeMux struct {

mu sync.RWMutex //鎖,由於請求設計到並發處理,因此需要加鎖

m map[string]muxEnty //路由規則,一個string(路由表達式)對應一個Mux實體{ explicit bool //是否精確匹配 h Handler //這個路由表達式對應哪個handler pattern string //匹配字符串}

hosts bool //是否在任意的規則中帶有host信息

}

type Handler interface {

ServeHTTP(RespnseWriter,*Request) //路由實現器

}

type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}


func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
w.Header().Set("Connection", "close")
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
if r.Method != "CONNECT" {
if p := cleanPath(r.URL.Path); p != r.URL.Path {
_, pattern = mux.handler(r.Host, p)
return RedirectHandler(p, StatusMovedPermanently), pattern
}
}
return mux.handler(r.Host, r.URL.Path)
}

func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
mux.mu.RLock()
defer mux.mu.RUnlock()

// Host-specific pattern takes precedence over generic ones
if mux.hosts {
h, pattern = mux.match(host + path)
}
if h == nil {
h, pattern = mux.match(path)
}
if h == nil {
h, pattern = NotFoundHandler(), ""
}
return
}

5.執行流程:

首先調用Http.HandleFunc

按順序做了幾件事:

1 調用了DefaultServeMux的HandleFunc

2 調用了DefaultServeMux的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 在這個例子中,下面就進入到DefaultServeMux.ServeHttp

10 根據request選擇handler,並且進入到這個handler的ServeHTTP

mux.handler(r).ServeHTTP(w, r)
11 選擇handler:

A 判斷是否有路由能滿足這個request(循環遍歷ServerMux的muxEntry)

B 如果有路由滿足,調用這個路由handler的ServeHttp

C 如果沒有路由滿足,調用NotFoundHandler的ServeHttp

Golang-web基礎