kong go 插件開發


介紹

在Kong 2.0之前,Lua是唯一支持編寫Kong插件的語言,並且仍然是開發和擴展Kong的主要方法。Go插件支持的新增功能使Kong用戶可以進入Go生態系統。例如,有些數據庫(例如MS SQL Server)沒有很好的Lua客戶端庫,但Go很好地支持了這些數據庫。Go插件可以直接訪問此類服務器,而無需傳遞Kong的Lua代碼。

結構

Go PDK完全基於用Go編寫的單獨過程。您可以命名一個go-pluginserver作為Kong的啟動進程,並打開一個通訊通道以在它們之間傳遞事件和函數調用。這意味着Go插件可以在真實的Go環境中運行,並且可以使用Go功能,例如goroutine,I / O,IPC等。

注意:這也意味着對PDK函數的任何調用都必須轉移到Kong流程中,然后再返回。

Go插件是使用-buildmode=plugin標志編譯的,該標志允許插件服務器動態加載它們。為了遵守Go嚴格的鏈接兼容性檢查,必須使用kong/go-plugin-toolDocker鏡像對其進行編譯,如下所述。

前置條件

使用Go插件:

  • 您需要可執行文件如go-pluginserver將其安裝在中/usr/local/bin/如果要在其他任何地方使用,請將go_pluginserver_exe變量名設置在Kong配置文件中並且值是他的完整路徑
  • go_plugins_dirKong配置文件中變量設置為有效目錄。默認"off"值禁用Go支持。
  • 將已編譯的Go插件添加到上一步中指定的目錄中。
  • 通過管理API,數據庫或聲明性文件以通常方式添加插件設置。通過其文件名(不帶.so后綴)引用插件

編寫自己的Go插件:

  • 具有Kong開發環境。
  • 擁有kong/go-plugin-tool:<version> docker鏡像<version>應該是與kong相同的版本。

發展歷程

環境一致性約束

Golang開發以較低的入門障礙和易於部署而聞名。即使用Go編寫的復雜程序也可以作為單個可執行文件分發,您可以將其復制到任何地方並直接運行。

為了實現這一點,編譯器默認情況下會生成靜態鏈接的可執行文件。這種選擇的一個重大缺點是,這使得擴展“完成的” Go程序非常困難。有幾種方法可以解決此限制,但是大多數方法都涉及某種形式的進程間通信。由於語言和基本庫都對此提供了很好的支持,因此通常這是一個很好的解決方案,但並非總是如此。

在其他語言中,為Kong選擇的擴展策略很常見:插件是動態加載的模塊。為此,可執行文件和插件依賴於系統庫,而不是生成完全靜態的程序。

這是Golang中相對較新的功能,在工具和可部署性方面有一些粗略的優勢。特別是,加載的可執行文件(go-pluginserver在我們的例子中)和插件必須具有完全相同的鏈接行為,這一點至關重要這至少涉及:

  • 任何常用庫的相同版本,包括:
    • Kong/go-pdk
    • 所有的標准庫(比如fmtrpcreflect,等)
    • OS的庫,例如libpthreadlibcld-xxxx等。
  • 與Go編譯器完全相同的版本。
  • 相同的Go環境變量,例如$GOROOT$GOPATH

公共庫版本兼容性由go.mod依賴項管理部分處理,但這會在環境變量要求方面引入更復雜的問題。

例如,evironment變量$GOPATH是一個現實問題,不僅因為推薦的模式之一是$HOME/go,其中包括開發人員在其自己系統中的用戶名,而且還因為生產構建(Dockerfile,構建腳本,CI / CD系統)很常見。使用非常不同的模式。

為了保證一致性,kong/go-plugin-tool用作Go編譯器的包裝。Kong發行軟件包和映像使用它來編譯包含的軟件包go-pluginserver

開發過程

要在Go中編寫Kong插件,您需要:

  • 定義結構類型以保存配置。
  • 編寫一個New()函數來創建您的結構實例。
  • 在該結構上添加方法以處理事件。
  • 使用編譯docker run --rm -v $(pwd):/plugins kong/go-plugin-tool:<version> build <source>
  • 將生成的庫(.so文件)放入go_plugins_dir目錄中。

注意:這里是個demo,請查看https://github.com/Kong/go-plugins 。

配置結構

用Lua編寫的插件定義了一個架構,用來指定如何讀取和驗證來自數據存儲區或Admin API的配置數據。由於Go是一種靜態類型語言,因此所有規范都是通過定義結構體來處理的。

type MyConfig struct {
    Path   string
    Reopen bool
}

公共字段(即以大寫字母開頭的字段)將填充配置數據。如果希望它們在數據存儲區中使用其他名稱,請添加在encoding/json包裝上定義的字段標簽

type MyConfig struct {
    Path   string `json:my_file_path`
    Reopen bool   `json:reopen`
}

New() 初始化

您的插件必須定義一個名為New的函數,該函數創建此類型的實例並以形式返回interface{}在大多數情況下,就是這樣:

func New() interface{} {
    return &MyConfig{}
}

您可以向結構中添加更多字段,這些字段將被傳遞,但是不能保證配置實例的壽命或數量。

處理事件

要處理Kong事件,請在您的配置結構中定義相關方法。例如,要處理“訪問”事件,請定義如下函數:

func (conf *MyConfig) Access (kong *pdk.PDK) {
    …
}

你可以定義事件的方法是CertificateRewriteAccessPreread和 Log它們的簽名都是相同的。

go-pdk 包

添加"github.com/Kong/go-pdk"到導入的程序包。kong事件處理程序方法上收到指針是Go PDK函數的入口點。這些功能大多數都與Lua PDK中的相應功能相同。

有關Go PDK的參考文檔,請參見go-pdk godoc頁面。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM