go http模塊源碼分析-server端

前言

近期使用go開發(fā)api后臺服務(wù)宜鸯,對http模塊源碼有初步了解适滓,所以整理總結(jié)一下皂甘。

server端核心模型包括

  • Server 類型結(jié)構(gòu)斧散,代表了一個(gè)指定端口下的服務(wù)供常。

同時(shí)也保存了tls,超時(shí)等配置鸡捐。最重要的是一個(gè)handler處理器栈暇。

type Server struct {
    Addr    string  // TCP address to listen on, ":http" if empty
    Handler Handler // handler to invoke, http.DefaultServeMux if nil
    TLSConfig *tls.Config
    ReadTimeout time.Duration
        //...
}

ListenAndServe方法開啟監(jiān)聽,等待連接箍镜。
server 監(jiān)聽客戶端請求源祈,啟動(dòng)goroutine處理。

func (srv *Server) Serve(l net.Listener) error {
    //...
    for {
        rw, e := l.Accept()
        // ...
        c := srv.newConn(rw)
        go c.serve(ctx)
    }
}
  • Handler 接口色迂,響應(yīng)一個(gè)http請求
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
  • ServeMux : http請求多路復(fù)用器香缺,實(shí)現(xiàn)了 Handler接口,它的實(shí)現(xiàn)為: 轉(zhuǎn)發(fā)請求到匹配的handler處理歇僧。
type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    es    []muxEntry // slice of entries sorted from longest to shortest.
    hosts bool       // whether any patterns contain hostnames
}

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    if r.RequestURI == "*" {
        if r.ProtoAtLeast(1, 1) {
            w.Header().Set("Connection", "close")
        }
        w.WriteHeader(StatusBadRequest)
        return
    }
    h, _ := mux.Handler(r)
    h.ServeHTTP(w, r)
}
  • DefaultServeMux: 是ServeMux類型一個(gè)實(shí)力图张, 作為一個(gè)全局對象導(dǎo)出。當(dāng)新建的server對象诈悍,handler為空時(shí)祸轮,使用DefaultServeMux。
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

可以通過HandleFunc方法侥钳,向全局多路復(fù)用器中加入路由模式及其handler适袜。
處理請求時(shí)根據(jù)所有加入的路由模式中匹配。

// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

注冊pattern, 如果以/結(jié)尾舷夺,會加入到排序的切片中苦酱,在map中匹配不到路由時(shí),使用它冕房,做最長匹配躏啰。

if pattern[len(pattern)-1] == '/' {
        mux.es = appendSorted(mux.es, e)
    }

路由匹配規(guī)則趁矾,先在map中精確匹配耙册。
匹配失敗則 用到排序的slice 進(jìn)行最長匹配。

func (mux *ServeMux) match(path string) (h Handler, pattern string) {
    // Check for exact match first.
    v, ok := mux.m[path]
    if ok {
        return v.h, v.pattern
    }

    // Check for longest valid match.  mux.es contains all patterns
    // that end in / sorted from longest to shortest.
    for _, e := range mux.es {
        if strings.HasPrefix(path, e.pattern) {
            return e.h, e.pattern
        }
    }
    return nil, ""
}

總結(jié):

    1. go的http server模塊同時(shí)也包含了處理socker 連接的代碼毫捣,所以不需要像java需要額外的應(yīng)用服務(wù)器详拙,例如tomcat。 go更易于部署蔓同,開發(fā)迭代饶辙。
      我認(rèn)為一部分原因 是得益于go對并發(fā)的原生支持,go的并發(fā)模型斑粱。go開發(fā)時(shí)弃揽,可以使用goroute簡單 并且低代價(jià)的方式,即可獲得高并發(fā)的支持。
    1. go server中路由匹配 力度太大矿微,一個(gè)url匹配一個(gè)handler痕慢,不區(qū)分http方法,也無法在url中加入?yún)?shù)匹配涌矢。
      所以 路由部分 還是建議使用開源模塊
      https://github.com/gorilla/mux
      https://github.com/julienschmidt/httprouter
      mux源碼分析參考 : 這里

參考:
https://www.godoc.org/net/http

原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掖举,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子娜庇,更是在濱河造成了極大的恐慌塔次,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件名秀,死亡現(xiàn)場離奇詭異励负,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匕得,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門熄守,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耗跛,你說我怎么就攤上這事裕照。” “怎么了调塌?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵晋南,是天一觀的道長。 經(jīng)常有香客問我羔砾,道長负间,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任姜凄,我火速辦了婚禮政溃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘态秧。我一直安慰自己董虱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布申鱼。 她就那樣靜靜地躺著愤诱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捐友。 梳的紋絲不亂的頭發(fā)上淫半,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音匣砖,去河邊找鬼科吭。 笑死昏滴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的对人。 我是一名探鬼主播影涉,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼规伐!你這毒婦竟也來了蟹倾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤猖闪,失蹤者是張志新(化名)和其女友劉穎鲜棠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體培慌,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豁陆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吵护。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盒音。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖馅而,靈堂內(nèi)的尸體忽然破棺而出祥诽,到底是詐尸還是另有隱情,我是刑警寧澤瓮恭,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布雄坪,位于F島的核電站,受9級特大地震影響屯蹦,放射性物質(zhì)發(fā)生泄漏维哈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一登澜、第九天 我趴在偏房一處隱蔽的房頂上張望阔挠。 院中可真熱鬧,春花似錦脑蠕、人聲如沸购撼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽份招。三九已至切揭,卻和暖如春狞甚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廓旬。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工哼审, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谐腰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓涩盾,卻偏偏與公主長得像十气,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子春霍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前面有介紹beego web框架砸西, 其實(shí)很多框架都是在 最簡單的http服務(wù)上做擴(kuò)展的的,基本上都是遵循h(huán)ttp協(xié)...
    若與閱讀 35,459評論 4 31
  • 譯注: 這篇文章的內(nèi)容非持啡澹基礎(chǔ)芹枷,也非常容易理解。原文地址莲趣,感覺是最能清晰的講述了net/http包的用法的一篇鸳慈,故...
    li3p閱讀 1,961評論 0 3
  • 《Go語言四十二章經(jīng)》第三十六章 net/http包 作者:李驍 在Go中,搭建一個(gè)http server簡單到令...
    ffhelicopter閱讀 2,211評論 0 8
  • Go語言中HTTP Server: HTTP server喧伞,顧名思義走芋,支持http協(xié)議的服務(wù)器,HTTP是一個(gè)簡單...
    WuXiao_閱讀 9,326評論 2 24
  • 小憶在許多人眼里是一個(gè)乖巧懂事潘鲫,性格內(nèi)向話很少的小姑娘翁逞,可是這樣的性格讓她在生活和工作中不夠自信,存在感太低溉仑,常常...
    萬妮妮閱讀 201評論 0 1