詳解如何使用Golang擴展Envoy
一、背景
主要介紹用 Golang 擴展 Envoy 的極速開發(fā)體驗
MoE(MOSN on Envoy)是 MOSN 團隊提出的技術架構,經(jīng)過近兩年的發(fā)展,在螞蟻內(nèi)部已經(jīng)得到了很好的驗證;并且去年我們也將底層的 Envoy Go 七層擴展貢獻了 Envoy 官方,MOSN 也初步支持了使用 Envoy 作為網(wǎng)絡底座的能力。
借此準備寫一系列的文章,逐一介紹這里面的技術。本文作為開篇,將重點介紹 MoE 中的基礎技術,Envoy Go 擴展。
二、FAQ
開始前,先給大家解答下幾個基本的問題:
1、MoE 與 Envoy Go 擴展有什么區(qū)別?
A:MoE 是技術架構,Envoy Go 擴展是連接 MOSN 和 Envoy 的基礎技術。
2、Envoy Go 擴展,與用 Go 來編譯 Wasm 有什么區(qū)別?
A:Envoy Go 支持 Go 語言的所有特性,包括 Goroutine;Go Wasm 則只能使用少量的 Go 語言特性,尤其是沒有 Goroutine 的支持。
3、Go 是靜態(tài)鏈接到 Envoy 么?
A:不是的,Go 擴展編譯成為 so,Envoy 動態(tài)加載 so,不需要重新編譯 Envoy
4、Envoy Go 支持流式處理么?
A:支持的。
由于 Go 擴展提供的是底層的 API,非常的靈活,使用上相對會稍微復雜一些;如果只想簡單的使用,可以使用 MOSN 的 filter,后面我們也會介紹。
三、需求
我們先實現(xiàn)一個小需求,來實際體會一下:
對請求需要進行驗簽,大致是從 URI 上的某些參數(shù),以及私鑰計算一個 token,然后和 header 中的 token 進行對比,對不上就返回 403。
很簡單的需求,僅僅作為示例,主要是體驗一下過程。??
四、代碼實現(xiàn)
完整的代碼可以看 envoy-go-filter-example[1] 這個倉庫,這里摘錄最核心的兩個函數(shù):
const secretKey = "secret" func verify(header api.RequestHeaderMap) (bool, string) { token, ok := header.Get("token") if ok { return false, "missing token" } path, _ := header.Get(":path") hash := md5.Sum([]byte(path + secretKey)) if hex.EncodeToString(hash[:]) != token { return false, "invalid token" } return true, "" } func (f *filter) DecodeHeaders(header api.RequestHeaderMap, endStream bool) api.StatusType { if ok, msg := verify(header); !ok { f.callbacks.SendLocalReply(403, msg, map[string]string{}, 0, "bad-request") return api.LocalReply } return api.Continue }
DecodeHeaders
是擴展 filter
必須實現(xiàn)的方法,我們就是在這個階段對請求 header
進行校驗。
verify
是校驗函數(shù),這里的 RequestHeaderMap
是 Go 擴展提供的 interface
,我們可以通過它來讀寫 header,其他都是常見的 Go 代碼寫法。
五、編譯
編譯很簡單,與常見的 Go 編譯一樣,這里我們使用 Golang 官方的 docker 鏡像來編譯:
docker run --rm -v `pwd`:/go/src/go-filter -w /go/src/go-filter \ -e GOPROXY=https://goproxy.cn \ golang:1.19 \ go build -v -o libgolang.so -buildmode=c-shared .
Go 編譯還是很快的,只需要幾秒鐘,當前目錄下,就會產(chǎn)生一個 libgolang.so 的文件。反觀 Envoy 的編譯速度,一次全量編譯動輒幾十分鐘,或者上小時的,這幸福感提升了不止一個檔次。??
六、運行
我們可以使用 Envoy 官方提供的鏡像來運行,如下示例:
docker run --rm -v `pwd`/envoy.yaml:/etc/envoy/envoy.yaml \ -v `pwd`/libgolang.so:/etc/envoy/libgolang.so \ -p 10000:10000 \ envoyproxy/envoy:contrib-dev \ envoy -c /etc/envoy/envoy.yaml
只需要把上一步編譯的 libgolang.so
和 envoy.yaml
掛載進去就可以了。
值得一提的是,我們需要在 envoy.yaml 配置中啟用 Go 擴展,具體是這段配置:
http_filters: - name: envoy.filters.http.golang typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.golang.v3alpha.Config library_id: example library_path: /etc/envoy/libgolang.so plugin_name: example-1
跑起來之后,我們測試一下:
$ curl 'http://localhost:10000/' missing token $ curl -s 'http://localhost:10000/' -H 'token: c64319d06364528120a9f96af62ea83d' -I HTTP/1.1 200 OK
符合期望,是不是很簡單呢???
七、后續(xù)
什么?這個示例太簡單?
是的,這里主要是體驗下開發(fā)流程,下篇我們將再介紹更高級的玩法:
Go 接受來自 Envoy 側的配置、異步 Goroutine,以及與 Istio 配合的用法。
|相關鏈接|
[1]envoy-go-filter-example 倉庫:https://github.com/doujiang24/envoy-go-filter-example/tree/master/example-1
以上就是詳解如何使用Golang擴展Envoy的詳細內(nèi)容,更多關于Golang擴展Envoy的資料請關注腳本之家其它相關文章!
相關文章
intelliJ?idea安裝go開發(fā)環(huán)境并搭建go項目(打包)全過程
最近在配置idea開發(fā)go語言時碰到很多問題,所以這里給大家總結下,這篇文章主要給大家介紹了關于intelliJ?idea安裝go開發(fā)環(huán)境并搭建go項目(打包)的相關資料,需要的朋友可以參考下2023-10-10go+redis實現(xiàn)消息隊列發(fā)布與訂閱的詳細過程
這篇文章主要介紹了go+redis實現(xiàn)消息隊列發(fā)布與訂閱,redis做消息隊列的缺點:沒有持久化,一旦消息沒有人消費,積累到一定程度后就會丟失,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09