詳解如何使用Golang擴(kuò)展Envoy
一、背景
主要介紹用 Golang 擴(kuò)展 Envoy 的極速開(kāi)發(fā)體驗(yàn)
MoE(MOSN on Envoy)是 MOSN 團(tuán)隊(duì)提出的技術(shù)架構(gòu),經(jīng)過(guò)近兩年的發(fā)展,在螞蟻內(nèi)部已經(jīng)得到了很好的驗(yàn)證;并且去年我們也將底層的 Envoy Go 七層擴(kuò)展貢獻(xiàn)了 Envoy 官方,MOSN 也初步支持了使用 Envoy 作為網(wǎng)絡(luò)底座的能力。
借此準(zhǔn)備寫(xiě)一系列的文章,逐一介紹這里面的技術(shù)。本文作為開(kāi)篇,將重點(diǎn)介紹 MoE 中的基礎(chǔ)技術(shù),Envoy Go 擴(kuò)展。
二、FAQ
開(kāi)始前,先給大家解答下幾個(gè)基本的問(wèn)題:
1、MoE 與 Envoy Go 擴(kuò)展有什么區(qū)別?
A:MoE 是技術(shù)架構(gòu),Envoy Go 擴(kuò)展是連接 MOSN 和 Envoy 的基礎(chǔ)技術(shù)。
2、Envoy Go 擴(kuò)展,與用 Go 來(lái)編譯 Wasm 有什么區(qū)別?
A:Envoy Go 支持 Go 語(yǔ)言的所有特性,包括 Goroutine;Go Wasm 則只能使用少量的 Go 語(yǔ)言特性,尤其是沒(méi)有 Goroutine 的支持。
3、Go 是靜態(tài)鏈接到 Envoy 么?
A:不是的,Go 擴(kuò)展編譯成為 so,Envoy 動(dòng)態(tài)加載 so,不需要重新編譯 Envoy
4、Envoy Go 支持流式處理么?
A:支持的。
由于 Go 擴(kuò)展提供的是底層的 API,非常的靈活,使用上相對(duì)會(huì)稍微復(fù)雜一些;如果只想簡(jiǎn)單的使用,可以使用 MOSN 的 filter,后面我們也會(huì)介紹。
三、需求
我們先實(shí)現(xiàn)一個(gè)小需求,來(lái)實(shí)際體會(huì)一下:
對(duì)請(qǐng)求需要進(jìn)行驗(yàn)簽,大致是從 URI 上的某些參數(shù),以及私鑰計(jì)算一個(gè) token,然后和 header 中的 token 進(jìn)行對(duì)比,對(duì)不上就返回 403。
很簡(jiǎn)單的需求,僅僅作為示例,主要是體驗(yàn)一下過(guò)程。??
四、代碼實(shí)現(xiàn)
完整的代碼可以看 envoy-go-filter-example[1] 這個(gè)倉(cāng)庫(kù),這里摘錄最核心的兩個(gè)函數(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
是擴(kuò)展 filter
必須實(shí)現(xiàn)的方法,我們就是在這個(gè)階段對(duì)請(qǐng)求 header
進(jìn)行校驗(yàn)。
verify
是校驗(yàn)函數(shù),這里的 RequestHeaderMap
是 Go 擴(kuò)展提供的 interface
,我們可以通過(guò)它來(lái)讀寫(xiě) header,其他都是常見(jiàn)的 Go 代碼寫(xiě)法。
五、編譯
編譯很簡(jiǎn)單,與常見(jiàn)的 Go 編譯一樣,這里我們使用 Golang 官方的 docker 鏡像來(lái)編譯:
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 編譯還是很快的,只需要幾秒鐘,當(dāng)前目錄下,就會(huì)產(chǎn)生一個(gè) libgolang.so 的文件。反觀 Envoy 的編譯速度,一次全量編譯動(dòng)輒幾十分鐘,或者上小時(shí)的,這幸福感提升了不止一個(gè)檔次。??
六、運(yùn)行
我們可以使用 Envoy 官方提供的鏡像來(lái)運(yùn)行,如下示例:
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
掛載進(jìn)去就可以了。
值得一提的是,我們需要在 envoy.yaml 配置中啟用 Go 擴(kuò)展,具體是這段配置:
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
跑起來(lái)之后,我們測(cè)試一下:
$ curl 'http://localhost:10000/' missing token $ curl -s 'http://localhost:10000/' -H 'token: c64319d06364528120a9f96af62ea83d' -I HTTP/1.1 200 OK
符合期望,是不是很簡(jiǎn)單呢???
七、后續(xù)
什么?這個(gè)示例太簡(jiǎn)單?
是的,這里主要是體驗(yàn)下開(kāi)發(fā)流程,下篇我們將再介紹更高級(jí)的玩法:
Go 接受來(lái)自 Envoy 側(cè)的配置、異步 Goroutine,以及與 Istio 配合的用法。
|相關(guān)鏈接|
[1]envoy-go-filter-example 倉(cāng)庫(kù):https://github.com/doujiang24/envoy-go-filter-example/tree/master/example-1
以上就是詳解如何使用Golang擴(kuò)展Envoy的詳細(xì)內(nèi)容,更多關(guān)于Golang擴(kuò)展Envoy的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang 實(shí)現(xiàn)Location跳轉(zhuǎn)方式
這篇文章主要介紹了golang 實(shí)現(xiàn)Location跳轉(zhuǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05intelliJ?idea安裝go開(kāi)發(fā)環(huán)境并搭建go項(xiàng)目(打包)全過(guò)程
最近在配置idea開(kāi)發(fā)go語(yǔ)言時(shí)碰到很多問(wèn)題,所以這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于intelliJ?idea安裝go開(kāi)發(fā)環(huán)境并搭建go項(xiàng)目(打包)的相關(guān)資料,需要的朋友可以參考下2023-10-10go+redis實(shí)現(xiàn)消息隊(duì)列發(fā)布與訂閱的詳細(xì)過(guò)程
這篇文章主要介紹了go+redis實(shí)現(xiàn)消息隊(duì)列發(fā)布與訂閱,redis做消息隊(duì)列的缺點(diǎn):沒(méi)有持久化,一旦消息沒(méi)有人消費(fèi),積累到一定程度后就會(huì)丟失,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09簡(jiǎn)單聊聊Go語(yǔ)言中空結(jié)構(gòu)體和空字符串的特殊之處
在日常的編程過(guò)程中,大家應(yīng)該經(jīng)常能遇到各種”空“吧,比如空指針、空結(jié)構(gòu)體、空字符串等,本文就以?Go?語(yǔ)言為例,一起來(lái)看看空結(jié)構(gòu)體和空字符串在?Go?語(yǔ)言中的特殊之處吧2024-03-03Go語(yǔ)言題解LeetCode455分發(fā)餅干示例詳解
這篇文章主要為大家介紹了Go語(yǔ)言題解LeetCode455分發(fā)餅干示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Go語(yǔ)言定時(shí)器Timer和Ticker的使用與區(qū)別
在Go語(yǔ)言中內(nèi)置的有兩個(gè)定時(shí)器,Timer和Ticker,本文主要介紹了Go語(yǔ)言定時(shí)器Timer和Ticker的使用與區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07