天天看點

go web架構_Golang架構探索(一)

go web架構_Golang架構探索(一)

這篇文章是搬運自我的個人blog:

MashiroC的奇思妙想

最近閑來無事,搗鼓了一下Golang的Web架構。這一篇文章主要是梳理一下Web架構的執行邏輯,真正開始上手撸代碼和踩坑要到下一篇。

因為是Java選手,剛開始學Go不久,代碼風格可能比較Java。

另外有一些題外話,我最初開始學習Web架構是一本Java的講解Web架構的書籍,名字叫《架構探險》。

但是Java的Web架構和Go的Web架構還是有不少的差別,學習Go的話不是很建議使用這本書。

Web架構基本設計

現代的Web後端架構中,所有架構的設計都會提供一部分共同的功能。這部分功能是Web架構的最基礎功能:建立url對函數的映射,對 Request / Response 進行解析和封裝。這些架構減輕了工作時的重複勞動與複雜繁瑣的api調用,提升了應用的開發速度和可維護性。

架構不管是使用過濾器這樣的設計(比如struts),還是直接使用一個函數處理所有的請求(比如spring、gin等等),都是使用了單一入口,即所有請求通過原生的api進入到一個統一的處理子產品。

請求進來時,在這個單一子產品中查找請求的路由(uri)和方法(method)所對應的處理這個路由的函數。若查找不到,則傳回404(NOT FOUND)或405(MOTHOD NOW ALLOW)。

找到對應的處理函數後取出這個函數,根據解析請求中的參數,如get請求中url的參數、post請求中body裡的參數,解析并封裝後執行該函數,得到傳回對象再進行解析通過設定好的格式(json/xml/html等)序列化,最後原生的方法傳回。

下面是原生api和使用架構的對比:

go web架構_Golang架構探索(一)

我們希望使用架構能夠寫出如下的代碼:

package main

import "begonia"

func main(){
    app := application.Init()

  app.Get("/hello", func(ctx *begonia.Context) {
      ctx.String("hello world")
    })

  app.Post("/welcome", func(ctx *begonia.Context) {
      name := ctx.Param("name")
      ctx.String("hello " + name)
    })

    app.Start(1234)
}
           

對于一個架構來說,最基礎的子產品就是路由子產品了,即uri對執行函數的映射。下面一個部分我們來聊聊這個路由。

路由子產品

在閱讀了多個語言多個架構的路由解析部分源碼後,一般路由的實作大體分為兩個思路:哈希表和Trie樹(字首樹)。

使用哈希表的為:

  • Java Spring

而我所看過的golang的架構,全部使用了Trie樹來實作路由的解析分發

  • beego
  • gin
  • echo

我們這篇文章裡簡單來說一下兩種實作的思路。

路由的哈希表實作

由于各大語言都擁有了原生的哈希表實作,這裡我們就不贅述如何實作一個哈希表了,感興趣可以自行 百度/谷歌 一下。

Go的map、Java的HashMap、pthon的dict采用的是哈希表實作,而c++的map使用的是紅黑樹,哈希表是unordered_map,這裡提醒一下。

我們可以針對每個方法建立一個哈希表,每添加一個路由,在對應方法的哈希表下建立一個鍵值對即可。

當請求進來時,根據uri查找路由,若查找得到則封裝請求參數并執行。若查找不到,則去其他方法的哈希表裡再查詢一下,這一步查到的到傳回

405 method not allow

,查找不到傳回

404 not found

go web架構_Golang架構探索(一)

路由的Trie樹實作

這裡我聊一聊使用

壓縮Trie樹

來添加和查找路由,代碼實作我們下一篇文章來專門分析。

Trie樹

又稱

字首樹

字典樹

,思路是将字元串按每個字元存儲在樹的節點上,具有公共字首的單詞共享一個或幾個父節點。例如:"wechat"、"weibo"、"ware"、"hi"、"te"存儲在

Trie樹

上的情況如圖所示

go web架構_Golang架構探索(一)

但是對于url來說,會有很多的uri具有公共字首,但是具有較長的非公共的字尾,這個時候我們就需要使用到

壓縮Trie樹

了。

壓縮Trie樹

其實是上面的普通Trie樹的更新版,比

普通Trie樹

占用更少的記憶體空間。大題思路是在

普通Trie樹

上将長鍊壓縮為一個節點。上圖所示的資料結構壓縮後如下圖所示:

go web架構_Golang架構探索(一)

對比上面的普通Trie樹,不難發現每個節點不存在單獨的子節點,沒有單獨的長鍊存在了。

寫在最後

在Web架構中除了路由,還擁有其他非常重要的子產品。這一篇文章隻是一個簡單的Web架構針對路由的一些分析。在下一篇我會詳細分析并使用代碼實作壓縮Trie樹路由

繼續閱讀