Linux中國

使用 Apex 和 Compose MongoDB 開發 serverless

Apex 是一個將開發和部署 AWS Lambda 函數的過程打包了的工具。它提供了一個本地命令行工具來創建安全上下文、部署函數,甚至追蹤雲端日誌。由於 AWS Lambda 服務將函數看成獨立的單元,Apex 提供了一個框架層將一系列函數作為一個項目。另外,它將服務拓展到不僅僅是 Java,Javascript 和 Ptyhon 語言,甚至包括 Go 語言。

兩年前 Express (基本上是 NodeJS 事實標準上的網路框架層)的作者,離開了 Node 社區,而將其注意力轉向 Go (谷歌創造的後端服務語言),以及 Lambda(由 AWS 提供的函數即服務)。儘管一個開發者的行為無法引領一股潮流,但是來看看他正在做的名叫 Apex 項目會很有趣,因為它可能預示著未來很大一部分網路開發的改變。

什麼是 Lambda?

如今,人們如果不能使用自己的硬體,他們會選擇付費使用一些雲端的虛擬伺服器。在雲上,他們會部署一個完整的協議棧如 Node、Express,和一個自定義應用。或者如果他們更進一步使用了諸如 Heroku 或者 Bluemix 之類的新玩意,也可能在某些已經預配置好 Node 的容器中僅僅通過部署應用代碼來部署他們完整的應用。

在這個抽象的階梯上的下一步是單獨部署函數到雲端而不是一個完整的應用。這些函數之後可以被一大堆外部事件觸發。例如,AWS 的 API 網關服務可以將代理 HTTP 請求作為觸發函數的事件,而函數即服務(FaaS)的供應方根據要求執行匹配的函數。

Apex 起步

Apex 是一個將 AWS 命令行介面封裝起來的命令行工具。因此,開始使用 Apex 的第一步就是確保你已經安裝和配置了從 AWS 獲取的命令行工具(詳情請查看 AWS CLI Getting Started 或者 Apex documentation)。

接下來,安裝 Apex:

curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh

然後為你的新項目創建一個目錄並運行:

apex init

apexInit

這步會配置好一些必須的安全策略,並且將項目名字附在函數名後,因為 Lambda 使用扁平化的命名空間。同時它也會創建一些配置文件和默認的 「Hello World" 風格的 Javascript 函數的 functions 目錄。

tree

Apex/Lambda 一個非常友好的特性是創建函數非常直觀。創建一個以你函數名為名的新目錄,然後在其中創建項目。如果想要使用 Go 語言,你可以創建一個叫 simpleGo 的目錄然後在其中創建一個小型的 main 函數:

//  serverless/functions/simpleGo/main.go
package main

import (  
    "encoding/json"
    "github.com/apex/go-apex"
    "log"
)

type helloEvent struct {  
    Hello string `json:"hello"`
}

func main() {  
    apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) {
        var h helloEvent
        if err := json.Unmarshal(event, &h); err != nil {
            return nil, err
        }
        log.Print("event.hello:", h.Hello)
        return h, nil
    })
}

Node 是 Lambda 所支持的運行環境,Apex 使用 NodeJS shim 來調用由上述程序產生的二進位文件。它將 event 傳入二進位文件的 STDIN,將從二進位返回的 STDOUT 作為 value。通過 STDERR 來顯示日誌。apex.HandleFunc 用來為你管理所有的管道。事實上在 Unix 慣例里這是一個非常簡單的解決方案。你甚至可以通過在本地命令行執行 go run main.go 來測試它。

goRun

通過 Apex 向雲端部署稍顯瑣碎:

apexDeploy

注意,這將會對你的函數指定命名空間,控制版本,甚至為其他多開發環境如 stagingproduction配置env

通過 apex invoke 在雲端執行也比較瑣碎:

apexInvoke

當然我們也可以追蹤一些日誌:

apexLog

這些是從 AWS CloudWatch 返回的結果。它們都在 AWS 的 UI 中可見,但是當在另一個終端參照此結果來署它會更快。

窺探內部的秘密

來看看它內部到底部署了什麼很具有指導性。Apex 將 shim 和所有需要用來運行函數的東西打包起來。另外,它會提前做好配置如入口與安全條例:

lambdaConfig

Lambda 服務實際上接受一個包含所有依賴的 zip 壓縮包,它會被部署到伺服器來執行指定的函數。我們可以使用 apex build <functionName> 在本地創建一個壓縮包用來在以後解壓以探索。

apexBuild

這裡的 _apex_index.js handle 函數是原始的入口。它會配置好一些環境變數然後進入 index.js

index.js 孕育一個 main Go 的二進位文件的子進程並且將所有關聯聯結在一起。

使用 mgo 繼續深入

mgo 是 Go 語言的 MongoDB 驅動。使用 Apex 來創建一個函數來連接到 Compose 的 MongoDB 就如同我們已經學習過的 simpleGo 函數一樣直觀。這裡我們會通過增加一個 mgoGo 目錄和另一個 main.go 來創建一個新函數。

// serverless/functions/mgoGo/main.go

package main

import (  
    "crypto/tls"
    "encoding/json"
    "github.com/apex/go-apex"
    "gopkg.in/mgo.v2"
    "log"
    "net"
)

type person struct {  
  Name  string `json:"name"`
  Email string `json:"email"`
}

func main() {  
    apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) {
        tlsConfig := &tls.Config{}
        tlsConfig.InsecureSkipVerify = true

        //connect URL:
        // "mongodb://<username>:<password>@<hostname>:<port>,<hostname>:<port>/<db-name>
        dialInfo, err := mgo.ParseURL("mongodb://apex:mountain@aws-us-west-2-portal.0.dblayer.com:15188, aws-us-west-2-portal.1.dblayer.com:15188/signups")
        dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
            conn, err := tls.Dial("tcp", addr.String(), tlsConfig)
            return conn, err
        }
        session, err := mgo.DialWithInfo(dialInfo)
        if err != nil {
            log.Fatal("uh oh. bad Dial.")
            panic(err)
        }
        defer session.Close()
        log.Print("Connected!")

    var p person
    if err := json.Unmarshal(event, &p); err != nil {
            log.Fatal(err)
    }

        c := session.DB("signups").C("people")
        err = c.Insert(&p) 
        if err != nil {
            log.Fatal(err)
        }

    log.Print("Created: ", p.Name," - ", p.Email)
        return p, nil
    })
}

發布部署,我們可以通過使用正確類型的事件來模擬調用了一個 API:

apexMgo

最終結果是 insert 到在 Compose 之上 的 MongoDB 中。

composeDeploy

還有更多……

儘管目前我們已經涉及了 Apex 的方方面面,但是仍然有很多值得我們去探索的東西。它還和 Terraform 進行了整合。如果你真的希望,你可以發布一個多語言項目包括 Javascript、Java、Python 以及 Go。你也可以為開發、演示以及產品環境配置多種環境。你可以調整運行資源如調整存儲大小和運行時間來調整成本。而且你可以把函數勾連到 API 網關上來傳輸一個 HTTP API 或者使用一些類似 SNS (簡單通知服務)來為雲端的函數創建管道。

和大多數事物一樣,Apex 和 Lambda 並不是在所有場景下都完美。 但是,在你的工具箱中增加一個完全不需要你來管理底層建設的工具完全沒有壞處。

作者簡介:

Hays Hutton 喜歡寫代碼並寫一些與其相關的東西。喜歡這篇文章?請前往Hays Hutton』s author page 繼續閱讀其他文章。

via: https://www.compose.com/articles/go-serverless-with-apex-and-composes-mongodb/

作者:Hays Hutton 譯者:xiaow6 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國