Fn 函式佈署流程涉及 Docker 映像構建和推播至倉函式庫。首先,使用 fn build 命令構建映像,再以 fn deploy 佈署至指定應用程式,同時 Fn 會自動更新版本號。佈署後,fn routes list 命令可驗證佈署結果,並透過 curl 命令與函式互動,觀察 HTTP 回應中的 Fn_call_id 等資訊。除了 Java,Fn 也支援 Go 等 runtime。利用 fn init --runtime go 初始化 Go 函式,目錄中包含 func.go、func.yaml 和 test.json 等檔案。func.go 撰寫函式程式碼,需注意錯誤處理和日誌記錄,錯誤訊息應寫入 STDERR 並以非零碼離開。佈署 Go 函式流程與 Java 類別似,使用 fn deploy 佈署,fn call 進行呼叫。
Fn 函式佈署與測試詳解
在前面的章節中,我們已經瞭解瞭如何使用 Fn 專案建立和佈署函式。本章節將探討如何佈署函式並與之互動,同時介紹如何使用不同的 runtime(如 Go)來建立函式。
佈署函式
當我們完成了函式的開發後,下一步就是將其佈署到 Fn 伺服器上。佈署的過程涉及構建 Docker 映像並將其推播到指定的 Docker 倉函式庫。
佈署流程
-
構建函式:首先,我們使用
fn build命令來構建函式的 Docker 映像。$ fn build Building image hello:0.0.1 Function hello:0.0.1 built successfully. -
佈署函式:接著,使用
fn deploy命令將構建好的映像佈署到指定的應用程式中。$ fn deploy --app demo --registry chanwit Deploying hello to app: demo at path: /hello Bumped to version 0.0.2 Building image chanwit/hello:0.0.2 Pushing chanwit/hello:0.0.2 to docker registry...在佈署過程中,Fn 會自動增加映像的版本號,構建新的 Docker 映像,並將其推播到指定的 Docker 倉函式庫。
-
驗證佈署結果:佈署完成後,可以使用
fn routes list命令來列出應用程式中的所有路由,以驗證函式是否成功佈署。$ fn routes list demo path image endpoint /hello chanwit/hello:0.0.2 localhost:8080/r/demo/hello
與函式互動
佈署完成後,我們可以使用 curl 命令來與函式互動。Fn 會將函式暴露為 HTTP 端點,因此我們可以像存取普通的 HTTP 端點一樣與之互動。
$ curl -v localhost:8080/r/demo/hello
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /r/demo/hello HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Length: 13
< Content-Type: text/plain
< Fn_call_id: 01C8SPGSEK47WGG00000000000
< Xxx-Fxlb-Wait: 78.21μs
< Date: Sat, 17 Mar 2018 10:01:43 GMT
<
* Connection #0 to host localhost left intact
Hello, world!
在回應的 HTTP 頭中,我們可以看到一些額外的資訊,如 Fn_call_id 和 Xxx-Fxlb-Wait。這些資訊對於呼叫跟蹤和效能監控非常有用。
使用 Go Runtime 建立函式
除了 Java 之外,Fn 還支援其他多種 runtime,包括 Go。讓我們來看看如何使用 Go 建立函式。
初始化 Go 函式
使用 fn init 命令並指定 --runtime go 來建立一個新的 Go 函式。
$ fn init --runtime go hello_go
Creating function at: /hello_go
Runtime: go
Function boilerplate generated.
func.yaml created.
建立完成後,我們可以看到函式目錄下的檔案結構:
$ cd hello_go
$ tree .
.
├── func.go
├── func.yaml
└── test.json
其中,func.go 是函式的主程式,func.yaml 是 Fn 的函式描述檔案,而 test.json 則包含了用於功能測試的測試韌體。
函式程式碼
在 func.go 中,我們可以看到函式的實際程式碼。以下是一個簡單的例子,展示瞭如何使用 Go 來處理輸入的 JSON 資料。
package main
import (
"encoding/json"
"fmt"
"os"
)
type Message struct {
Name string
}
func main() {
m := &Message{Name: "world"}
err := json.NewDecoder(os.Stdin).Decode(m)
if err != nil {
fmt.Fprintf(os.Stderr, "err JSON Decode: %s\n", err.Error())
os.Exit(250)
}
fmt.Printf(`{"success": "Hello %s"}`, m.Name)
os.Exit(0)
}
錯誤處理和日誌記錄
在函式程式碼中,我們需要注意錯誤處理和日誌記錄。Fn 會將寫入 STDERR 的訊息儲存到日誌中,因此我們應該將錯誤訊息寫入 STDERR。同時,函式應該以非零的離開碼離開,以指示錯誤。
佈署和測試 Go 函式
佈署 Go 函式的過程與佈署 Java 函式類別似。我們可以使用 fn deploy 命令來佈署函式,並使用 fn call 命令來呼叫函式。
$ fn deploy --app demo --registry chanwit
Deploying hello_go to app: demo at path: /hello_go
...
$ echo '{"Name": "chanwit"}' | fn call demo /hello_go
{"success": "Hello chanwit"}
如果我們在呼叫函式時沒有提供正確的輸入,函式將會傳回錯誤。
$ fn call demo /hello_go
{"error":{"message":"container exit code 250"}}
ERROR: error calling function: status 502
這個例子展示瞭如何在 Fn 中使用 Go runtime 建立和佈署函式,以及如何處理錯誤和記錄日誌。
內容解密:
- 佈署流程:詳細介紹瞭如何使用
fn build和fn deploy命令來構建和佈署函式。 - 與函式互動:展示瞭如何使用
curl命令來與佈署好的函式互動,並解析了回應中的 HTTP 頭資訊。 - Go Runtime:介紹瞭如何使用 Go runtime 建立函式,包括初始化函式、編寫函式程式碼、錯誤處理和日誌記錄。
- 佈署和測試 Go 函式:演示瞭如何佈署和測試使用 Go runtime 建立的函式。
透過本章節的學習,讀者應該能夠掌握如何在 Fn 中佈署和管理函式,以及如何使用不同的 runtime(如 Go)來建立函式。這些技能對於開發高效、可靠的 serverless 應用程式非常重要。
Fn 函式管理與佈署詳解:從日誌檢查到 Docker Swarm 佈署
檢查呼叫日誌與錯誤處理
要檢視所有的呼叫日誌,可以使用 fn calls 命令。需要注意的是,這裡的命令是 calls,而不是其他拼寫。fn calls list 命令可以接受應用程式的名稱作為引數,主要關注的屬性包括 ID 和 狀態。
呼叫日誌範例
以下範例展示了兩個呼叫日誌,第一個是錯誤的,第二個是成功的,按照逆時間順序排列:
$ fn calls list demo
ID: 01C8VRGN9R47WGJ00000000000
App: demo
Route: /hello_go
Created At: 2018-03-18T05:15:04.376Z
Started At: 2018-03-18T05:15:04.738Z
Completed At: 2018-03-18T05:15:07.519Z
Status: success
ID: 01C8VRFE3647WGE00000000000
App: demo
Route: /hello_go
Created At: 2018-03-18T05:14:24.230Z
Started At: 2018-03-18T05:14:24.566Z
Completed At: 2018-03-18T05:14:27.375Z
Status: error
擷取特定呼叫ID的日誌
現在,我們選取第二個呼叫ID來取得日誌訊息。檢索日誌的命令是 fn logs get,它需要應用程式名稱和呼叫ID:
$ fn logs get demo 01C8VRFE3647WGE00000000000
err JSON Decode: EOF
上述日誌訊息是Go程式印出到 os.Stderr 的內容。
日誌檢查重點
- 使用
fn calls list檢視所有呼叫日誌 - 重點關注
ID和狀態屬性 - 使用
fn logs get檢索特定呼叫ID的日誌
在 Docker Swarm 上佈署 Fn
建立網路與資料儲存
首先,我們需要在 Swarm 範圍的網路上建立一個 Fn 叢集。為了穩定性,我們使用 weaveworks/net-plugin 作為基礎網路。請注意,網路必須是可連線的,且子網路必須在 10.32.0.0/16 的範圍內。例如,10.32.3.0/24 是合適的:
$ docker network create \
--driver weaveworks/net-plugin:2.1.3 \
--attachable \
--subnet 10.32.3.0/24 \
fn_net
建立資料函式庫儲存卷
接下來,我們為資料儲存建立一個卷。為了展示一個生產級的設定,我們使用 MySQL 作為儲存,而不是預設的 SQLite3。這樣可以讓我們水平擴充套件 Fn 伺服器的數量。
$ docker volume create mysql_vol
啟動 MySQL 例項
以下是啟動 MySQL 例項的 docker run 命令。我們將例項連線到之前建立的 fn_net 網路,並指定網路別名以確保服務可以透過 mysql 名稱存取。所有的環境變數都用於設定使用者名稱、密碼和預設資料函式庫 fn_db。不要忘記將 mysql_vol 卷繫結到容器內的 /var/lib/mysql,以確保資料在容器移除後仍然存在:
$ docker run \
--detach \
--name mysql \
--network fn_net \
--network-alias mysql \
-e MYSQL_DATABASE=fn_db \
-e MYSQL_USER=func \
-e MYSQL_PASSWORD=funcpass \
-e MYSQL_RANDOM_ROOT_PASSWORD=yes \
-v mysql_vol:/var/lib/mysql \
mysql
啟動 Fn 伺服器
接下來的步驟是啟動 Fn 伺服器。本文示範如何啟動兩個 Fn 伺服器,它們指向同一個日誌儲存(MySQL)。每個 Fn 伺服器都連線到 fn_net。第一個例項被命名為 fn_0。Fn 伺服器需要 FN_DB_URL 環境變數指向外部的日誌儲存,這可以是 PostgreSQL 或 MySQL。只需按照以下命令提供完整的 URL:
$ docker run --privileged \
--detach \
--network fn_net \
--network-alias fn_0 \
--name fn_0 \
-e "FN_DB_URL=mysql://func:funcpass@tcp(mysql:3306)/fn_db" \
fnproject/fnserver
啟動多個 Fn 伺服器例項
讓我們啟動另一個 Fn 伺服器例項 fn_1。基本上,這應該在不同的節點(實體或虛擬)上完成:
$ docker run --privileged \
--detach \
--network fn_net \
--network-alias fn_1 \
--name fn_1 \
-e "FN_DB_URL=mysql://func:funcpass@tcp(mysql:3306)/fn_db" \
fnproject/fnserver
設定 Fn LB 負載平衡器
在設定所有 Fn 伺服器例項後,現在是時候將它們聚合起來。我們使用 Fn LB 作為所有 Fn 伺服器前面的負載平衡器。與其他容器一樣,我們只需建立它並將其連線到 fn_net。由於它是 FaaS 閘道器,我們還將其內部埠 8081 對應到主機的 8080 埠,以便 Fn CLI 可以連線到 Fn 叢集而無需任何特殊設定。網路別名僅在其他服務需要連線到此閘道器時使用。
接下來,將 Fn 伺服器節點列表作為命令列引數傳遞。目前,節點列表組態只允許直接傳遞給容器。只需將它們放在 <name>:<port> 格式中,以逗號分隔:
$ docker run --detach \
--network fn_net \
--network-alias fnlb \
--name fnlb \
-p 8080:8081 \
fnproject/fnlb:latest --nodes fn_0:8080,fn_1:8080
驗證佈署
現在是時候驗證一切是否正常執行。我們使用 docker ps 命令檢查所有容器:
$ docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Command}}\t{{.Ports}}"
CONTAINER ID NAMES COMMAND PORTS
ce4f8e9bc300 fnlb "./fnlb --nodes fn_0..." 0.0.0.0:8080->8081/tcp
dae4fb892b4d fn_1 "preentry.sh ./fnser..." 2375/tcp
8aefeb9e19ef fn_0 "preentry.sh ./fnser..." 2375/tcp
67bd136c331a mysql "docker-entrypoint.s..." 3306/tcp
使用 Fn UI 進行監控
Fn UI 是為 Fn 建立的使用者介面專案。它提供了一個簡單的儀錶板,包含易於使用的時間序列圖,可以近乎實時地監控函式的執行情況。要啟動 Fn UI,我們建立並將容器連線到 fn_net,同時將埠釋出到 4000。Fn UI 需要 Fn 伺服器的 URL。但由於它們都在 Fn LB 後面,所以我們只需將 FN_API_URL 設定為 Fn LB 的位置。
請注意,它們都在 fn_net 網路內相互連線,因此 URL 顯示為 http://fnlb:8081,使用的是 fnlb 在網路內的真實名稱和埠:
$ docker run --detach \
--network fn_net \
--network-alias fnui \
-p 4000:4000 \
-e "FN_API_URL=http://fnlb:8081" \
fnproject/ui
存取 Fn UI 儀錶板
設定 Fn UI 例項後,瀏覽到 localhost:4000 以開啟儀錶板。我們將看到所有應用程式列在那裡,如下圖所示。應用程式可以在那裡進行管理,例如建立或刪除。如果您不希望螢幕始終自動重新整理,請取消選中 Auto refresh。
執行函式
選擇應用程式後,您可以透過點選 Run Function 按鈕在儀錶板中執行函式,如下圖所示。如果執行函式時發生錯誤並失敗,例如,會彈出通知。要執行函式,請以 JSON 格式輸入 Payload 並按下 Run 按鈕。
重點整理
- 日誌檢查:使用
fn calls list和fn logs get命令檢查呼叫日誌和錯誤。 - Docker Swarm 佈署:建立網路和資料函式庫卷,啟動 MySQL 和 Fn 伺服器例項,使用 Fn LB 進行負載平衡。
- Fn UI 監控:使用 Fn UI 進行函式監控和執行。
佈署架構圖
graph LR
A[使用者端] -->|HTTP/HTTPS|> B[Fn LB]
B -->|負載平衡|> C[Fn Server 1]
B -->|負載平衡|> D[Fn Server 2]
C -->|存取資料函式庫|> E[MySQL 資料函式庫]
D -->|存取資料函式庫|> E
F[Fn UI] -->|監控|> C
F -->|監控|> D
圖表翻譯: 此圖示展示了 Fn 的佈署架構。使用者端透過 Fn LB 存取 Fn Server,Fn Server 進一步存取 MySQL 資料函式庫。同時,Fn UI 用於監控 Fn Server 的狀態。