iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 10
1
Software Development

啥物碗Golang? 30天就Go系列 第 10

靜態檔案分享伺服器 File System Server

今天是第十天,今天完成整個鐵人賽就完成三分之一!告訴自己要繼續堅持努力下去。

今天會介紹的go伺服器應用範例是靜態檔案分享伺服器(File System Server),可能有人會想這種東西有什麼好獨立成一台Web Server,其實這關係到近來一個逐漸流行的網路框架設計概念,我們先來聊聊什麼是「微服務」:

微服務 Microservices

我第一次聽到這個名詞其實是在今年初的某次面試時,幸好我當時就字面上理解的並沒有什麼差異。過去的網站不管有多少功能,都會視為一個專案,部署時自然也會整包部署。就算有自動擴展或附載平衡,也都是以整個專案為一個單位考量,但這樣其實喪失了一些靈活性。

想像一個情境:一個線上商城的專案,把會員的部分獨立一個伺服器、結帳獨立一個伺服器、商品管理獨立一個伺服器、前端頁面UI獨立一個伺服器。把原本全都綑綁在同一個專案中的各個功能解耦合,降低相依性,彼此之間用API互相溝通,這樣可以有什麼好處?

靈活控制附載

原本是一個巨大的專案,如果有週年慶等大型活動,動態加到兩百台虛擬主機,其中所有功能都等比例提升,但實際上並不是所有部分都有相同需求;拆散之後,商品管理在大型活動之前壓力不變、會員系統微微提升,最終可以把所有資源投注在頁面與結帳,資源使用更有效率!

降低各功能組合的相依性

拆為獨立的伺服器之後,各功能之間勢必要將原本錯綜複雜的邏輯解除開,彼此只處理自己的部分,清爽乾淨更不容易產生架構問題。如果要導入新技術,各伺服器分別升級的風險,也比一次動整包來得更安全。

業務多角化後重複使用

當商城越做越大,可能書店的部分獨立為一個事業群,另外又開始活動報名等新的業務,如果沒有將功能切開,與商城綑綁在一起的會員與結帳難以支援其他服務;如果是分別的伺服器,只要符合API規格,擴展性更高。書店、活動報名等可以使用相同的會員、結帳API,更換前端、商品管理即可。

事實上這樣的概念在python的網路框架Django中就有設計出來,雖然還是包在同一個專案內,但各功能之間保持高度的獨立性,有關這部分可以參考我去年鐵人賽的文章Django與Rails比較


前面說了這麼多,我們馬上來看看code範例:

package main

import (
  "net/http"
)
func ping(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("pong"))
}
func main() {
  http.Handle("/", http.FileServer(http.Dir("./src")))
  http.HandleFunc("/ping", ping)
  if err := http.ListenAndServe(":8000", nil); err != nil {
    panic(err)
  }
}

然後在根目錄下建一個src的資料夾,在裡面放靜態檔案。接著將伺服器啟動,訪問同名的路徑,就可以找到我們剛剛放的檔案囉!我們可以觀察一下今天的範例與前幾天有一些不同之處:

  1. 多了一種路由方法。由http所支援的http.HandleFunc對應到別的方法(在這個例子中對應到ping());新的http.Handle後面則直接將http.FileServer作為參數,連結到靜態檔案。
  2. http.ListenAndServe監聽路由依然是必備的句子,但今天他不是獨立存在,而是寫在條件判斷內,給值的同時做錯誤處理。這樣的句型結構是前面幾天講到的,在go之中最接近三元運算子(ternary conditional operator)的寫法,可以當作比較進階的go句型使用。
  3. 就算是靜態伺服器,也不可能所有連結都會連結到靜態資源,這個時候可以使用別條路由(在這邊使用ping pong作為例子。假如說彼此衝突的時候,像是將程式改寫為下面這樣:
  http.Handle("/", http.FileServer(http.Dir("./src")))
  http.HandleFunc("/apple.jpg", ping)  // 與靜態資源同名

則會以HandleFunc為優先,也就是說會導引導ping而不是顯示靜態資源,這個部分需要特別注意!

Reference


上一篇
Html & Template
下一篇
API Server 範例
系列文
啥物碗Golang? 30天就Go30

1 則留言

我要留言

立即登入留言