真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Dropbox是怎么將接入層從Nginx遷移到Envoy的

這篇文章主要介紹了Dropbox是怎么將接入層從Nginx遷移到Envoy的,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

舒蘭ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)建站的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

在我們大部分的 Dropbox 流量轉(zhuǎn)到 Envoy 后,我們還必須無縫地將一個已經(jīng)處理了數(shù)千萬個建立的連接,每秒數(shù)百萬個請求,并擁有數(shù)個 TB  帶寬的復(fù)雜系統(tǒng)遷移到上面。這實際上已經(jīng)讓我們成為了世界上最大的 Envoy 用戶之一。

免責聲明:盡管我們試圖保持客觀性,但是本文中有很多對比是針對 Dropbox 以及我們軟件開發(fā)的方式進行的:我們的技術(shù)棧選型是 Bazel,gRPC 和  C++/Golang。

另外請注意,下文提到的 Nginx 指的是其開源版本,而不是具有附加功能的商業(yè)版本。

舊的一套基于 Nginx 的流量基礎(chǔ)設(shè)施

我們的 Nginx 配置絕大部分都是靜態(tài)的,然后通過結(jié)合 Python2、Jinja2 以及 YAML  等渲染。任意一處變動都需要一次完整的重新部署才能生效。所有動態(tài)的部分,比如 upstream 管理以及 stats exporter,這些是用 Lua  編寫的。更復(fù)雜的邏輯放到了用 Go 編寫的,下面一層的代理層。

Nginx 在我們的環(huán)境里良好運行了近十年。但是它已經(jīng)無法再適應(yīng)我們現(xiàn)在的開發(fā)優(yōu)秀實踐:

  • 我們內(nèi)部和(私有)外部的 API 逐漸從 REST 遷移到 gRPC,這需要各種代理層面的轉(zhuǎn)碼功能支持;

  • Protocol buffer 已經(jīng)成為服務(wù)定義和配置的事實標準;

  • 所有軟件,無論使用哪種語言,均是通過 Bazel 構(gòu)建和測試;

  • 我們的工程師開始重度參與開源社區(qū)里一些重要的基礎(chǔ)設(shè)施項目。

此外,在運維方面,Nginx 的維護成本非常高:

  • 配置生成邏輯太過靈活,而且拆分到了 YAML、Jinja2 和 Python等多處;

  • 監(jiān)控是一個 Lua 腳本、日志解析以及基于系統(tǒng)的基礎(chǔ)監(jiān)控的組合;

  • 越來越依賴于第三方模塊,而這會帶來穩(wěn)定性、性能以及后續(xù)升級成本等多方面的影響;

  • Nginx 的部署及流程管理同其他服務(wù)完全不同。它完全依賴于其他一些系統(tǒng)的配置:syslog、logrotate 等,并沒有和基礎(chǔ)系統(tǒng)完全分離。

正是出于上述種種原因,10 年來我們首次開始尋找 Nginx 的潛在替代產(chǎn)品。

為什么不用 Bandaid?

正如我們上面提到的,在 Dropbox 內(nèi)部,我們嚴重依賴一個 Golang 實現(xiàn)的代理(稱為 Bandaid)。之所以它可以和 Dropbox  的整個基礎(chǔ)設(shè)施很好地集成,原因是在于它可以訪問到我們內(nèi)部 Golang 庫的廣闊生態(tài):監(jiān)控、服務(wù)發(fā)現(xiàn)、限流等。我們考慮過從 Nginx 遷移到 Bandaid  的方案,但是這里面有一些問題阻礙了我們這樣做:

  • Golang 比 C/C++ 占用更多的資源。資源的低使用率對于跑在邊緣端的我們至關(guān)重要,因為我們無法輕易地“自動擴容”那里的部署。

  • CPU 開銷主要來自 GC、HTTP 解析器和 TLS ,后者的優(yōu)化程度低于 Nginx/Envoy 使用的 BoringSSL。

  • “每個請求一個 goroutine”的模型和 GC 開銷大大增加了像我們這樣高連接服務(wù)的內(nèi)存需求。

  • Go 的 TLS 棧不支持 FIPS(譯者注:見 go #11658)。

  • 除了 Dropbox,Bandaid 沒有一個社區(qū)的支持,這意味著我們只能依靠我們自己來開發(fā)功能。

綜合上述原因,我們決定將所有流量基礎(chǔ)設(shè)施遷移到 Envoy。

全新的基于 Envoy 的流量基礎(chǔ)設(shè)施

讓我們逐一看看開發(fā)和運維幾個主要的維度,從中了解為什么我們認為 Envoy 對我們來說是一個更好的選擇,以及我們從 Nginx 遷移到 Envoy  之后獲得了哪些收益。

性能

Nginx 的架構(gòu)是一個事件驅(qū)動和多進程的模式。它支持 SO_REUSEPORT,EPOLLEXCLUSIVE 以及 Worker  綁核。盡管它是基于事件循環(huán)的,但它并不是完全非阻塞的。這意味著某些操作(例如打開一個文件或記錄 access/error  日志)可能會導(dǎo)致事件循環(huán)中止(即使啟用了 aio,aio_write 和線程池),這樣會使得尾部延遲增加,從而導(dǎo)致旋轉(zhuǎn)磁盤驅(qū)動器上出現(xiàn)幾秒鐘的延遲。

Envoy 是一個類似的事件驅(qū)動式的架構(gòu),只是它使用的是線程而不是進程。它也同樣支持 SO_REUSEPORT(自帶一個 BPF 過濾器的支持),并且依賴  libevent 實現(xiàn)事件循環(huán)(換句話說,沒有用到像 EPOLLEXCLUSIVE 這樣的 epoll(2) 功能)。Envoy 在事件循環(huán)里并沒有任何阻塞  IO 的操作。甚至日志記錄也是以非阻塞方式實現(xiàn)的,因此它不會出現(xiàn)停頓的現(xiàn)象。

從理論上講,Nginx 和 Envoy 應(yīng)該具有相似的性能特征。但是“希望”不是我們的做事風格,因此我們的第一步便是針對經(jīng)過類似調(diào)整的 Nginx 和  Envoy 設(shè)置運行各種工作負載測試。

我們的測試結(jié)果表明,在大多數(shù)測試工作負載下,Nginx 和 Envoy 擁有相近的性能表現(xiàn):單秒高請求(RPS),高帶寬以及混合的低延遲/高帶寬的  gRPC 代理。

可以說,進行一個良好的性能測試非常困難。Nginx 有提供一個用于性能測試的準則,但是這些準則尚未形成規(guī)范。Envoy 也有提供一個基準測試指南,甚至在  envoy-perf 項目下也提供了一些工具,但遺憾的是后者似乎不怎么維護了。

我們轉(zhuǎn)而使用內(nèi)部的測試工具。之所以稱其為“綠巨人(hulk)”,是因為它在粉碎我們的服務(wù)方面享有盛譽。

這么說吧,我們發(fā)現(xiàn)測試結(jié)果里有幾處顯著的差異:

  • Nginx 表現(xiàn)出更高的長尾延遲。這主要是在遭遇繁重的 I/O 時事件循環(huán)停滯所致,尤其是與 SO_REUSEPORT  一起使用的情況,因為在這種情況下,它可以代表當前被阻塞的 Worker 程序繼續(xù)接受連接請求;

  • 在沒有開啟統(tǒng)計數(shù)據(jù)收集的情況下,Nginx 的功能和 Envoy 相當,但是我們的 Lua 統(tǒng)計數(shù)據(jù)收集模塊在高 RPS 測試中拖慢了 Nginx 3  倍??紤]到我們對 lua_shared_dict 的依賴,它在 Nginx 的各個 worker  之間是以一個互斥鎖進行同步,性能方面的損失也是意料之中的情況。

我們也知道統(tǒng)計數(shù)據(jù)收集模塊效率很低下。我們有考慮過在用戶空間里實現(xiàn)一個類似于 FreeBSD 的 counter(9) 的功能:綁定 CPU 核心,為每個  worker 分配一個無鎖的計數(shù)器以及一個取值的例程,該例程會循環(huán)遍歷所有 worker  并聚合匯總他們各自的統(tǒng)計信息。但是我們最終放棄了這個想法,因為如果我們想要監(jiān)控 Nginx  內(nèi)部狀態(tài)(比如所有錯誤情況),那就意味著我們要維護一個巨大的補丁程序,這將使得后續(xù)升級變成一個真正的地獄。

由于 Envoy 不會受到這兩個問題的困擾,因此在遷移到 Envoy 之后,我們可以釋放多達 60% 的服務(wù)器資源(之前被 Nginx 獨占)。

可監(jiān)察性

可監(jiān)察性是任何產(chǎn)品的最基本的運維需求,尤其是對于像代理這樣的基礎(chǔ)設(shè)施而言。在遷移期間,這一點尤為關(guān)鍵,這樣一來任何問題都可以被監(jiān)控系統(tǒng)檢測到,而不用等到沮喪的用戶報障時才發(fā)現(xiàn)。

非商業(yè)版本的 Nginx 自帶一個“stub status”模塊,提供了 7 個統(tǒng)計信息:

Active connections: 291  server accepts handled requests 16630948 16630948 31070465  Reading: 6 Writing: 179 Waiting: 106

這當然是不夠的,因此我們添加了一個簡單的 log_by_lua 處理程序,該處理程序根據(jù) Lua 中可用的 HTTP header  和變量添加每個請求的統(tǒng)計信息:狀態(tài)代碼,大小,緩存命中率等。以下是一個簡單的吐出統(tǒng)計數(shù)據(jù)的函數(shù)的例子:

function _M.cache_hit_stats(stat) if _var.upstream_cache_status then     if _var.upstream_cache_status == "HIT" then         stat:add("upstream_cache_hit")     else         stat:add("upstream_cache_miss")     end end end

除了每個請求的 Lua 統(tǒng)計信息外,我們還有一個非常脆弱的 error.log 解析器,它負責 upstream,http,Lua 和 TLS  的錯誤分類。

在這些之上,我們有一個單獨的 exporter ,用于收集 Nginx 的內(nèi)部狀態(tài):自上次 reload 的時間,worker 數(shù)量,RSS/VMS  大小,TLS 證書使用期限等。

典型的 Envoy 配置為我們提供了數(shù)千種不同的指標(采用 Prometheus 格式),用于描述代理流量和服務(wù)器的內(nèi)部狀態(tài):

$ curl -s http://localhost:3990/stats/prometheus | wc -l  14819

這里面囊括了五花八門的來自不同地方匯總的大量統(tǒng)計信息:

  • 每個集群/每個 upstream /每個 vhost 的 HTTP 統(tǒng)計信息,包括連接池信息和各種時序直方圖;

  • 每個監(jiān)聽器的 TCP/HTTP/TLS 下游的連接統(tǒng)計信息;

  • 從基本版本信息和正常運行時間到內(nèi)存分配統(tǒng)計以及棄用功能使用情況計數(shù),各種內(nèi)部/運行時狀態(tài)的統(tǒng)計信息。

Envoy 的管理接口真心贊。它不僅通過 /certs,/clusters 和 /config_dump  端點提供額外的結(jié)構(gòu)化的統(tǒng)計信息,而且還提供了非常重要的運維功能:

  • 通過 /logging 提供即時更改錯誤日志配置的能力。這讓我們能夠在幾分鐘內(nèi)排查相當模糊的問題;

  • /cpuprofiler,/heapprofiler,/contention 在不可避免的性能排障期間肯定會有用武之地;

  • /runtime_modify 端點允許我們更改配置參數(shù)集而不用推送新的配置,而這些配置可用于功能開關(guān)等。

除了統(tǒng)計數(shù)據(jù)外,Envoy 還支持可插拔的 tracing  實現(xiàn)。這不僅對擁有多個負載均衡層的接入層團隊有用,對于希望從邊緣到應(yīng)用服務(wù)器端到端跟蹤請求延遲的應(yīng)用程序開發(fā)人員也很有用。

從技術(shù)上講,Nginx 也支持通過第三方的 OpenTracing 集成進行跟蹤,但是該功能開發(fā)尚不成熟。

最后,同等重要的是,Envoy 能夠通過 gRPC 流式傳輸 access 日志。這減輕了我們接入層團隊不得不支持打通 syslog 到 hive  的負擔。此外,在 Dropbox 生產(chǎn)中啟動通用 gRPC 服務(wù)比添加自定義的 TCP/UDP 監(jiān)聽器更容易(也更安全!)。

和其他所有操作類似,Envoy 里面 access 日志的配置是通過 gRPC 管理服務(wù),即訪問日志服務(wù)(ALS)設(shè)置。管理服務(wù)是將 Envoy  數(shù)據(jù)平面與生產(chǎn)中的各種服務(wù)集成的標準方式。這也是我們下一節(jié)要介紹的內(nèi)容。

集成

Nginx 提供的集成方案,一個最佳描述便是 “Unix-ish”。配置是非常靜態(tài)的。而且它嚴重依賴于文件(例如配置文件本身,TLS 證書和 Ticket  、白名單/黑名單等)以及一些知名的行業(yè)協(xié)議(記錄日志到 syslog 以及通過 HTTP  發(fā)送認證子請求)。對于小型部署而言,這樣做的簡單性和向后兼容性是一件好事,因為我們可以通過編寫幾個 Shell 腳本輕松實現(xiàn) Nginx  的自動化。但是隨著系統(tǒng)規(guī)模的擴大,可測試性和標準化變得更加重要。

Envoy 對于是否應(yīng)該將接入層數(shù)據(jù)平面和它的控制平面,以及因此也即是與其他基礎(chǔ)設(shè)施集成在一起,持更加堅定的態(tài)度。它通過提供一個穩(wěn)定的 API(通常稱為  xDS ),鼓勵用戶使用 protobuf 和gRPC。Envoy 通過查詢一個或多個這樣的 xDS 服務(wù)來發(fā)現(xiàn)其動態(tài)資源。

如今,xDS API 的發(fā)展已然超越 Envoy:通用數(shù)據(jù)平面 API(UDPA)的宏偉目標是“成為事實上的 L4/L7 負載均衡器標準”。

根據(jù)我們的經(jīng)驗,這一雄心壯志是靠譜的。我們已經(jīng)在內(nèi)部負載測試中使用了開放請求成本匯總(ORCA),并且正在考慮將 UDPA 用于非 Envoy  的負載均衡,例如我們基于 Katran 的 eBPF/XDP 4層負載均衡代理。

這對于 Dropbox 尤其適合,Dropbox 的所有服務(wù)都已經(jīng)實現(xiàn)了在內(nèi)部通過基于 gRPC 的 API 進行交互。我們已經(jīng)實現(xiàn)了自主版本的 xDS  控制平面,它將 Envoy 同我們的配置管理、服務(wù)發(fā)現(xiàn)、私密信息管理以及路由信息集成在一起。

以下是一些可用的 xDS 服務(wù),它們的 Nginx 替代品以及我們?nèi)绾问褂盟鼈兊囊恍┦纠?/p>

  • 如上所述,訪問日志服務(wù)(ALS)讓我們可以動態(tài)地配置訪問日志目標,編碼和格式。試想一下 Nginx 的 log_format 和 access_log  的動態(tài)版本;

  • 端點發(fā)現(xiàn)服務(wù)(EDS)提供相關(guān)集群成員的信息。這類似于 Nginx 配置中動態(tài)更新 upstream 里的 server 條目列表(例如,對于 Lua  來說便是 balancer_by_lua_block)。在這里,我們將其代理到內(nèi)部的服務(wù)發(fā)現(xiàn);

  • 私密信息發(fā)現(xiàn)服務(wù)(SDS)提供了各種與 TLS 相關(guān)的信息,這些信息將涵蓋各種 ssl_ *  指令(以及相應(yīng)的ssl_*_by_lua_block)。我們將這個接口調(diào)整為適用于我們場景的私密信息分發(fā)服務(wù);

  • 運行時發(fā)現(xiàn)服務(wù)(RTDS)提供了運行時標志。我們在 Nginx 中實現(xiàn)這一功能的方式很不可靠,它是通過在 Lua  里檢查各種文件是否存在來實現(xiàn)的。這種方法很快會在各個服務(wù)器之間變得不一致。 Envoy 的默認實現(xiàn)也是基于文件系統(tǒng)的,但是我們將 RTDS xDS API  指向了我們的分布式配置存儲。這樣一來,我們便可以一次控制整個集群(通過帶有類似 sysctl  界面的工具),并且在不同服務(wù)器之間不會出現(xiàn)意外不一致的情況;

  • 路由發(fā)現(xiàn)服務(wù)(RDS)將路由映射到虛擬主機,并允許對 HTTP 頭部和過濾器進行額外的配置。用 Nginx 術(shù)語來說,它們類似于帶有  set_header/proxy_set_header 和 proxy_pass 的動態(tài) location  配置。在更底下的代理層,我們直接在我們的服務(wù)定義配置中自動生成這些配置;

關(guān)于 Envoy 如何與現(xiàn)有生產(chǎn)系統(tǒng)集成的示例,這里有一個將 Envoy 與自定義服務(wù)發(fā)現(xiàn)集成的一個經(jīng)典例子。還有一些開源的 Envoy  控制面板實現(xiàn),例如 Istio 和更少復(fù)雜度的 go-control-plane。

我們自己的 Envoy 控制平面實現(xiàn)了越來越多的 xDS API。它在生產(chǎn)中以普通的 gRPC  服務(wù)的形式部署,并充當我們基礎(chǔ)設(shè)施構(gòu)建塊的一個適配器。它通過一組通用的 Golang 庫來實現(xiàn)與內(nèi)部服務(wù)進行對話,并通過穩(wěn)定的 xDS API 向 Envoy  公開它們。整個過程不涉及任何文件系統(tǒng)調(diào)用,信號量,cron,logrotate,syslog,日志解析器等。

配置

Nginx 在配置方面具有簡單易讀這樣一項不可否認的優(yōu)勢。但是,隨著配置變得越來越復(fù)雜,并且配置開始變成是代碼生成式的,這項優(yōu)勢就沒了。

正如上面所提到的,我們的 Nginx 配置是通過 Python2,Jinja2 和 YAML 的混合生成的。 你們中的一些人可能已經(jīng)在  erb,pug,Text::Template 甚至 m4 里面看到或甚至編寫了這樣類似的變體:

{% for server in servers %} server { {% for error_page in server.error_pages %} error_page {{ error_page.statuses|join(' ') }} {{ error_page.file }}; {% endfor %} ... {% for route in service.routes %} {% if route.regex or route.prefix or route.exact_path %} location {% if route.regex %}~ {{route.regex}}{%         elif route.exact_path %}= {{ route.exact_path }}{%         else %}{{ route.prefix }}{% endif %} {     {% if route.brotli_level %}     brotli on;     brotli_comp_level {{ route.brotli_level }};     {% endif %}     ...

我們的 Nginx 配置的生成方式有一個大問題:配置生成中涉及的所有語言都允許代入 和/或 邏輯。YAML 有 anchor,Jinja2 有  loop/ifs/macroses,然后,Python 當然是圖靈完備的。如果沒有一個干凈的數(shù)據(jù)模型,復(fù)雜性會迅速擴散到這三者。

這個問題自然是可以解決的,但是有兩個基本問題:

  • 這里沒有關(guān)于配置格式的聲明性描述。如果我們想通過編程的方式生成和驗證配置,那么需要自己重新造輪子;

  • 語法上有效的配置,從 C  代碼的角度來看仍然可能是無效的。例如,某些與緩沖區(qū)相關(guān)的變量具有值限制,對齊限制以及與其他變量的相互依賴性。為了從語義上驗證配置,我們需要運行 nginx -t  來校驗。

另一方面,Envoy 自帶一套用于配置的統(tǒng)一數(shù)據(jù)模型:它的所有配置都放到 protobuffer  中定義。這不僅解決了數(shù)據(jù)建模問題,而且還將輸入的信息添加到了配置值里。鑒于 protobuf 是Dropbox  生產(chǎn)環(huán)境里的頭等公民,并且是描述/配置服務(wù)的通用方式,因此,集成就變得更加簡單了。

我們針對 Envoy 設(shè)計的新的配置生成器是基于 protobuf 和 Python3 實現(xiàn)的。所有數(shù)據(jù)建模均在原始文件中完成,而所有邏輯均在  Python 中執(zhí)行。下面是一個例子:

from dropbox.proto.envoy.extensions.filters.http.gzip.v3.gzip_pb2 import Gzip from dropbox.proto.envoy.extensions.filters.http.compressor.v3.compressor_pb2 import Compressor  def default_gzip_config( compression_level: Gzip.CompressionLevel.Enum = Gzip.CompressionLevel.DEFAULT, ) -> Gzip:     return Gzip(         # Envoy's default is 6 (Z_DEFAULT_COMPRESSION).         compression_level=compression_level,         # Envoy's default is 4k (12 bits). Nginx uses 32k (MAX_WBITS, 15 bits).         window_bits=UInt32Value(value=12),         # Envoy's default is 5. Nginx uses 8 (MAX_MEM_LEVEL - 1).         memory_level=UInt32Value(value=5),         compressor=Compressor(             content_length=UInt32Value(value=1024),             remove_accept_encoding_header=True,             content_type=default_compressible_mime_types(),         ),     )

注意上述代碼里的 Python3 類型注解!結(jié)合 mypy-protobuf protoc 插件,它們可以在 config  生成器里提供端到端的輸入。如果你用的 IDE 支持自動檢查的話,它將會立即高亮顯示輸入信息不匹配。

在某些情況下,經(jīng)過類型檢查的 protobuf 在邏輯上仍然可能是無效的。在上面的示例中,gzip window_bits 只能取 9 到 15  之間的值。這類限制可以在 protoc-gen-validate protoc 插件的幫助下輕松完成定義:

google.protobuf.UInt32Value window_bits = 9 [(validate.rules).uint32 = {lte: 15 gte: 9}];

最后,使用官方定義的配置模型的一個潛在好處是,它有機地引領(lǐng)了文檔與配置定義并排配置。 以下是一個 gzip.proto 的示例:

// Value from 1 to 9 that controls the amount of internal memory used by zlib. Higher values.            // use more memory, but are faster and produce better compression results. The default value is 5.             google.protobuf.UInt32Value memory_level = 1 [(validate.rules).uint32 = {lte: 9 gte: 1

可擴展性

要想讓 Nginx 提供超出標準配置所提供的功能范疇之外的特性的話,通常需要編寫一個 C 模塊。 Nginx  的開發(fā)指南對于可用的構(gòu)建塊提供了詳盡的介紹。這也就是說,這種方式是相對重量級的。實際上,要想安全地編寫一個 Nginx  模塊的話,需要一位相當資深的軟件工程師。

關(guān)于可供模塊開發(fā)人員選用的基礎(chǔ)設(shè)施的話,他們可以期待一些像哈希表、隊列、rb樹這樣的基礎(chǔ)容器,(非RAII)內(nèi)存管理、以及可用于所有請求處理階段的鉤子。另外,還有一些外部庫,比如  pcre、zlib、openssl,當然,還有l(wèi)ibc。

為了提供更輕量級的功能擴展,Nginx 提供了 Perl 和 JavaScript  的接口??杀氖?,它們所提供的功能都相當有限,絕大部分都局限于請求處理的內(nèi)容階段。

社區(qū)采納的最常用的擴展方式是基于第三方的 lua-nginx 模塊和各種 Openresty 類庫。這一方案幾乎可以外掛到請求處理的任意階段。我們使用  log_by_lua 進行統(tǒng)計信息的收集,然后使用 balancer_by_lua 進行動態(tài)地后端再配置。

從理論上講,Nginx 提供了使用 C++ 開發(fā)模塊的能力。然而實際上,對于所有原語,它都缺少適當?shù)?C++  接口/包裝器,這樣就顯得不太值得了。盡管如此,仍有一些社區(qū)對此進行嘗試。這些還遠遠沒有達到生產(chǎn)就緒。

Envoy 的主要擴展機制是通過 C++ 插件。這個流程在文檔方面不如 Nginx,但是它更為簡單。部分原因是:

  • 整潔且擁有良好注釋的界面。C++ 類充當自然的擴展和文檔點。比如,看看 HTTP 過濾接口。

  • C++14 語言和標準庫。從 template 和 lambda 函數(shù)等這些基本的語言功能,到類型安全的容器和算法。通常,編寫現(xiàn)代 C++14 與使用  Golang 并沒有多大區(qū)別,或者有些人甚至會說 Python。

  • C++14 及其標準庫以外的功能。由 abseil 庫提供的,其中包括來自較新版本的 C++ 標準的直接替換,內(nèi)置了靜態(tài)的死鎖檢測和 debug  支持的互斥鎖,以及額外的/更有效的容器,等等。

具體地,這里有一份 HTTP 過濾模塊的經(jīng)典例子。

通過簡單地實現(xiàn) Envoy stats 接口,我們僅用200行代碼就可以將 Envoy 與 Vortex2(我們的監(jiān)視框架)集成在一起。

Envoy 還通過 moonjit 添加了對 Lua 的支持,moonjit 是一個對 Lua 5.2 做了諸多改進支持的 LuaJIT fork。與  Nginx 的第三方 Lua 集成相比,它所提供的功能和開放的鉤子要少得多。由于在開發(fā)、測試和解釋后代碼的排障等諸多方面存在的額外復(fù)雜性成本,這使得 Lua 對  Envoy 的吸引力大大降低。專門從事 Lua 開發(fā)的公司可能會不同意這一觀點,但是在我們的案例中,我們決定避免使用它,而只是將 C++ 用于 Envoy  的可擴展性。

Envoy 與其他 Web 服務(wù)器的區(qū)別就在于它提供了對 WebAssembly(WASM)的新興支持 —— 一種快速的,可移植且安全的擴展機制。WASM  不能直接使用,但是可以作為任何通用編程語言的編譯目標。Envoy 實現(xiàn)了一個適用于代理的 WebAssembly 規(guī)范(還包括相關(guān)的 Rust 和 C++  SDK),該規(guī)范描述了 WASM 代碼和通用的 L4/L7 代理之間的邊界。代理和擴展之間代碼的分隔提供了一個安全的沙箱,而 WASM  低級凝練的二進制格式又為之提供了接近原生的效率。在此之上,在 Envoy 里,proxy-wasm 擴展是和 xDS  集成在一起的。這樣便可以進行動態(tài)地更新,甚至可以進行潛在的 A/B 測試。

在 KubeCon’s 19 上,《通過 WebAssembly 擴展 Envoy》這個演講很好地概述了 Envoy 里集成的 WASM  及其潛在用途。它還暗示已經(jīng)達到了原生 C++ 代碼性能水平的 60-70%。

使用 WASM,服務(wù)提供方可以安全有效地在其邊緣環(huán)境運行客戶的代碼??蛻臬@益的則是可移植性:他們的擴展可以在實現(xiàn) proxy-wasm ABI  的任何云上運行。此外,它允許用戶使用任意一種語言,只要它可以編譯為 WebAssembly。這使得他們能夠安全有效地使用更廣泛的非 C++ 類庫。

Istio 正在向 WebAssembly 的開發(fā)傾注大量資源:他們已經(jīng)有了基于 WASM 的遙測擴展的實驗版本以及用于共享擴展的  WebAssemblyHub 社區(qū)。

當前,Dropbox 并未用到 WebAssembly。但是,等到 proxy-wasm 的 GO SDK 可用時,這一情況也許會發(fā)生變化。

構(gòu)建和測試

默認情況下,Nginx 使用的是一套自定義的基于 shell 的配置系統(tǒng)和基于 make 的構(gòu)建系統(tǒng)構(gòu)建的。這是簡單而優(yōu)雅的,但是將其集成到 Bazel  構(gòu)建的 monorepo 的話需要花費大量的精力才能獲得增量、分布式、封閉和可重現(xiàn)構(gòu)建這些所有優(yōu)點。

Google 開源了他們用 Bazel 構(gòu)建的 Nginx 版本,該版本由 Nginx,BoringSSL,PCRE,ZLIB 和 Brotli  庫/模塊組成。

在測試方面,Nginx 在一個單獨的倉庫里有一組 Perl 驅(qū)動的集成測試,沒有任何單元測試。

鑒于我們對 Lua 的大量使用以及缺乏內(nèi)置的單元測試框架,我們求助于使用模擬配置和基于 Python 的簡單測試驅(qū)動程序進行測試:

class ProtocolCountersTest(NginxTestCase): @classmethod def setUpClass(cls):     super(ProtocolCountersTest, cls).setUpClass()     cls.nginx_a = cls.add_nginx(         nginx_CONFIG_PATH, endpoint=["in"], upstream=["out"],     )     cls.start_nginxes()  @assert_delta(lambda d: d == 0, get_stat("request_protocol_http2")) @assert_delta(lambda d: d == 1, get_stat("request_protocol_http1")) def test_http(self):     r = requests.get(self.nginx_a.endpoint["in"].url("/"))     assert r.status_code == requests.codes.ok

最重要的是,我們通過預(yù)處理所有生成的配置(例如用 127/8 替換所有 IP 地址,切換到自簽名 TLS 證書等)并在結(jié)果上運行 nginx -c  來驗證所有語法的語法正確性。

在 Envoy 方面,其主流的構(gòu)建系統(tǒng)已經(jīng)是 Bazel。因此,將它和我們的 monorepo 集成起來并不繁瑣:Bazel  支持輕松添加外部依賴項。

我們還使用 copybara 腳本來同步 Envoy 和 udpa 的  protobuf。當你需要進行簡單的轉(zhuǎn)換而無需永遠維護大型補丁集時,Copybara 十分方便。

通過 Envoy,我們可以靈活地選擇使用一組預(yù)先編寫好的 mock 來進行單元測試(基于 gtest/gmock ),也可以選擇使用 Envoy  的集成測試框架,或者同時使用兩者。至此,針對每一項細小的改動,我們不再需要依靠緩慢的端到端集成測試了。

gtest 是 Chromium 和 LLVM 等項目所采用的一套相當有名的單元測試框架。如果你想進一步了解  googletest,這里有兩份不錯的介紹資料:googletest 和 googlemock。

開源的 Envoy 開發(fā)要求每次更改達到 100% 的單元測試覆蓋率。它會通過 Azure CI 流水線針對每個 PR 自動觸發(fā)測試。

使用 google/becnhmark 對性能敏感的代碼進行微基準測試也是一種常見做法:

$ bazel run --compilation_mode=opt test/common/upstream:load_balancer_benchmark -- --benchmark_filter=".*LeastRequestLoadBalancerChooseHost.*" BM_LeastRequestLoadBalancerChooseHost/100/1/1000000          848 ms          449 ms            2 mean_hits=10k relative_stddev_hits=0.0102051 stddev_hits=102.051 ...

改用 Envoy 之后,我們開始完全依賴單元測試來進行內(nèi)部模塊開發(fā):

TEST_F(CourierClientIdFilterTest, IdentityParsing) { struct TestCase { std::vector uris; Identity expected; }; std::vector tests = { {{"spiffe://prod.dropbox.com/service/foo"}, {"spiffe://prod.dropbox.com/service/foo", "foo"}}, {{"spiffe://prod.dropbox.com/user/boo"}, {"spiffe://prod.dropbox.com/user/boo", "user.boo"}}, {{"spiffe://prod.dropbox.com/host/strange"}, {"spiffe://prod.dropbox.com/host/strange", "host.strange"}}, {{"spiffe://corp.dropbox.com/user/bad-prefix"}, {"", ""}}, }; for (auto& test : tests) { EXPECT_CALL(*ssl_, uriSanPeerCertificate()).WillOnce(testing::Return(test.uris)); EXPECT_EQ(GetIdentity(ssl_), test.expected); } }

實施亞秒級的往返測試在生產(chǎn)力方面會帶來復(fù)合效果。它讓我們能夠把更多精力放在增加測試覆蓋范圍。由于可以在單元測試和集成測試之間進行自由選擇,這使得我們能夠在  Envoy 測試的覆蓋范圍、速度和成本之間獲得一個平衡。

學習上手 Bazel  對我們開發(fā)人員來說是一次絕佳的經(jīng)歷。它的學習曲線非常陡峭,而且前期需要付出大量的投資,但是它卻有很高的回報:增量式構(gòu)建,遠程緩存,分布式構(gòu)建/測試等。

Bazel  很少討論的好處之一是,它讓我們能夠查詢甚至擴展依賴圖譜。依賴關(guān)系圖的編程接口,以及跨語言的通用構(gòu)建系統(tǒng),這是一項非常強大的功能。它可以用作代碼提示器,代碼生成,漏洞跟蹤以及部署系統(tǒng)等這類服務(wù)的基礎(chǔ)構(gòu)建塊。

安全性

Nginx 的代碼面非常小,它的外部依賴很少。通常,對生成的二進制文件來說只能看到 3 個外部依賴項:zlib(或者更快的變體之一),一個 TLS 庫以及  PCRE。Nginx 自研實現(xiàn)了所有相關(guān)的協(xié)議解析器、事件庫,甚至還重新實現(xiàn)了某些 libc 函數(shù)。

在某些情況下,Nginx 被認為非常安全,以至于它被用作 OpenBSD 里默認的 Web 服務(wù)器。后來,兩個開發(fā)社區(qū)發(fā)生了沖突,也因此有了  httpd。您可以在 BSDCon《介紹OpenBSD的新 httpd 》中了解此舉背后的動機。

這種極簡主義在實踐中得到了回報。Nginx 在11年多的時間里僅報告了30個安全漏洞。

另一方面,Envoy 的代碼量更大,尤其是考慮到 C++ 代碼比用于 Nginx 的基本 C  代碼更加密集時,這一點更為明顯。它還包含來自外部依賴項的數(shù)百萬行代碼。從事件通知到協(xié)議解析器的所有內(nèi)容都推給了第三方庫。這會增加攻擊面并造成最終產(chǎn)出的可執(zhí)行文件愈加膨脹。

為了解決這個問題,Envoy 高度依賴現(xiàn)代安全實踐。它使用 AddressSanitizer,ThreadSanitizer 和  MemorySanitizer。它的開發(fā)人員甚至超綱地采用了模糊測試。

任何對于全球IT基礎(chǔ)架構(gòu)至關(guān)重要的開源項目都可以接入到  OSS-Fuzz,這是一個用于自動化模糊測試的免費平臺。要了解更多信息,請參閱“OSS-Fuzz/架構(gòu)”。

實際上,盡管如此,所有這些預(yù)防措施都不能完全抵消增加的代碼所留下的痕跡。結(jié)果便是,在過去的兩年里,Envoy 已經(jīng)發(fā)布了 22 條安全公告。

Envoy 的《安全發(fā)布策略》一文對此進行了詳細描述,針對某些指定的漏洞還有詳細的檢查報告。Envoy 還是 Google  漏洞獎勵計劃(VRP)的成員之一。VRP 向所有安全研究人員開放,根據(jù)它們設(shè)計的規(guī)則,對發(fā)現(xiàn)和報告的漏洞提供獎勵。

為了應(yīng)對不斷增長的漏洞風險,我們使用了來自上游發(fā)行版供應(yīng)商 Ubuntu 和 Debian  的最佳可執(zhí)行文件來強化安全措施。我們?yōu)樗羞吘壄h(huán)境曝光的可執(zhí)行文件定義了特殊加固后的構(gòu)建配置文件。它包括 ASLR,堆棧保護器以及符號表的加固:

build:hardened --force_pic build:hardened --copt=-fstack-clash-protection build:hardened --copt=-fstack-protector-strong build:hardened --linkopt=-Wl,-z,relro,-z,now

在絕大多數(shù)環(huán)境里,fork 的 Web 服務(wù)器(如  Nginx)在堆棧保護器方面會存在問題。由于主進程和工作進程共享同一套堆棧來進行灰度,而在灰度驗證失敗時,工作進程會被殺死,因此,我們可以通過大約 1000  次嘗試逐位對灰度的實例進行暴力破解。使用線程作為并發(fā)原語的 Envoy 不受此攻擊的影響。

我們還希望盡可能的給第三方依賴的安全性加固。我們在 FIPS 模式下使用  BoringSSL,該模式包括啟動自檢和可執(zhí)行文件的完整性檢查。我們還考慮在某些邊緣環(huán)境的灰度服務(wù)器上運行啟用 ASAN 的可執(zhí)行文件。

功能性

這是帖子中最主觀的部分,請做好準備。

Nginx 最初是設(shè)計成一個 Web 服務(wù)器,致力于以最少的資源消耗來提供靜態(tài)文件服務(wù)。它的功能性在這里是最重要的:靜態(tài)文件服務(wù),緩存(包括驚群保護)以及  range 緩存。

但是,作為代理的話,Nginx 缺乏現(xiàn)代基礎(chǔ)架構(gòu)所需的功能。它的后端沒有 HTTP/2。盡管可以代理 gRPC 服務(wù),但是它不支持連接多路復(fù)用。而且不支持  gRPC  轉(zhuǎn)碼。最重要的是,Nginx的“核心開放(open-core)”模型限制了可以納入開源版本代理服務(wù)的功能集。結(jié)果便是,某些重要功能(如統(tǒng)計信息)在它的“社區(qū)”版本里是不可用的。

相比之下,Envoy 已經(jīng)演變?yōu)橐粋€ ingress/egress 代理,經(jīng)常用于以 gRPC 為主要負載的環(huán)境。盡管它的 Web  服務(wù)功能還是相當初級的:沒有文件服務(wù),而且緩存功能仍然在開發(fā)中,brotli或者預(yù)壓縮這些功能也都不支持。針對這些場景,我們?nèi)匀惶峁┝艘粋€小的 fallback  Nginx 實例,Envoy 會把它當成上游集群。

等到 Envoy 的 HTTP 緩存功能生產(chǎn)就緒時,我們便可以將大多數(shù)靜態(tài)服務(wù)用例遷移過去,使用 S3 取代文件系統(tǒng)作為長期存儲。

Envoy 還提供了許多 gRPC 相關(guān)能力的原生支持:

  • gRPC 代理。這是一項基本功能,允許我們在應(yīng)用程序里端到端地使用 gRPC(比如 Dropbox 桌面客戶端)

  • HTTP/2 到后端。這項功能使得我們可以大大減少流量層之間的 TCP 連接數(shù),從而減少內(nèi)存消耗和 keepalive 的流量。

  • gRPC -> HTTP 的橋接(+反向代理)這些讓我們能夠使用現(xiàn)代的 gRPC 棧對外暴露舊版的 HTTP/1 應(yīng)用程序服務(wù)。

  • gRPC-WEB。這項功能讓我們即使在中間層(防火墻,IDS等)尚不支持 HTTP/2 的環(huán)境里也可以端對端地使用gRPC。

  • gRPC JSON 轉(zhuǎn)碼器。這讓我們能夠?qū)⑺腥胝玖髁?包括 Dropbox 公共 API )從 REST 轉(zhuǎn)到 gRPC。

此外,Envoy 還可以用作一個出站代理。我們通過它統(tǒng)一了另外幾個用例場景:

  • Egress 代理:自從 Envoy 添加了對 HTTP CONNECT 方法的支持以后,它便可以用作 Squid 代理的替代產(chǎn)品。我們已經(jīng)開始用  Envoy 替換出站的 Squid  實例。這樣做不僅極大地提高了可見性,而且還通過統(tǒng)一使用通用的數(shù)據(jù)平面和可觀察性技術(shù)棧省掉了一攬子運維方面的糟心事(不再需要為了統(tǒng)計信息而去解析日志)

  • 第三方軟件服務(wù)發(fā)現(xiàn):我們并沒有使用 Envoy 來構(gòu)建服務(wù)網(wǎng)格,取而代之的是,我們依靠的是軟件里的 Courier gRPC  庫。但是,當遇到需要一次性花費最小的精力將開源服務(wù)與我們的服務(wù)發(fā)現(xiàn)連接的場景時,我們實際還是選擇了 Envoy。比如,Envoy  在我們的分析棧里用作服務(wù)發(fā)現(xiàn)的輔助工具。Hadoop 可以動態(tài)地發(fā)現(xiàn)它的 name 及 journal 節(jié)點。 Superset  可以發(fā)現(xiàn)airflow,presto 以及 hive 的后端。Grafana 可以發(fā)現(xiàn)它的 MySQL 數(shù)據(jù)庫。

社區(qū)

Nginx 的開發(fā)是相當中心化的。它的絕大部分開發(fā)活動都是核心團隊內(nèi)部進行的。nginx-devel 郵件列表上有一些外部活動,然后官方 Bug  跟蹤上偶爾有一些與開發(fā)相關(guān)的討論。

FreeNode 上有一個 #nginx 頻道。我們可以隨時加入到里面進行更多互動性質(zhì)的社區(qū)對話。

Envoy 的開發(fā)則是開放和去中心化的:通過 GitHub issue/pull request,郵件列表和社區(qū)會議進行協(xié)同。

Slack 上的社區(qū)活動也很活躍。你可以在這里收到邀請。

開發(fā)風格和工程社區(qū)這些方面很難量化定性,因此,我們不妨一起來看一個開發(fā) HTTP/3 的特定例子。

F5 最近發(fā)表了 Nginx QUIC 和 HTTP/3  實現(xiàn)。這塊代碼是干凈的,沒有任何外部依賴。但是開發(fā)過程本身并不透明。在此之前的半年,Cloudflare 提出了自己的 Nginx HTTP/3  實現(xiàn)。結(jié)果便是,該社區(qū)現(xiàn)在擁有兩套單獨的用于 Nginx 的 HTTP/3 實驗版本。

再來看看 Envoy ,HTTP/3 的實現(xiàn)這塊也正在開發(fā)中,它是基于 chromium 的  “quiche”(QUIC,HTTP等)庫。該項目的進展可以通過 這個 GitHub issue  跟蹤。在補丁開發(fā)完成前,設(shè)計文檔便已經(jīng)對外公布了。剩下的工作里,想要從社區(qū)參與中獲益的部分會帶有 “help wanted” 標簽。

如你所見,后者顯然更加開放透明,而且非常鼓勵協(xié)作開發(fā)。對我們來說,這意味著我們能夠從上游獲得大量的 Envoy 相關(guān)的大大小小的變動 ——  包括從運維改進和性能調(diào)優(yōu)到新的 gRPC 轉(zhuǎn)碼功能以及負載均衡功能的一些變動。

遷移后的現(xiàn)狀

我們已經(jīng)讓 Nginx 和 Envoy 并排運行了半年多,然后通過 DNS  逐步將流量從一個切換到另一個。到目前為止,我們已經(jīng)成功將許多各式各樣的工作負載遷移到了 Envoy:

  • Ingress 高吞吐量服務(wù)。Dropbox 桌面客戶端的所有文件數(shù)據(jù)都是通過 Envoy 背后端到端 的 gRPC 提供服務(wù)。改用 Envoy  后由于在邊緣環(huán)境的連接復(fù)用效果更好,我們還略微提高了用戶的性能。

  • Ingress 高RPS服務(wù)。這是 Dropbox 桌面客戶端的所有文件元數(shù)據(jù)。同樣地,我們獲得了端到端的 gRPC  帶來的好處,而且去掉了連接池,這意味著我們不受每個連接一次請求的限制。

  • 通知和遙測服務(wù)。這里是用來處理所有實時通知的服務(wù),因此這些服務(wù)器一般會有數(shù)百萬個 HTTP  連接(每個活躍的客戶端會有一個連接)。如今我們不再需要使用昂貴的長輪詢方式來實現(xiàn)通知服務(wù),取而代之的是,我們可以通過 streaming gRPC  來實現(xiàn)。

  • 兼有高吞吐量/高RPS的混合服務(wù)。API 流量(元數(shù)據(jù)和數(shù)據(jù)本身)。這使得我們開始考慮一些公共的 gRPC API。我們甚至可以直接在邊緣環(huán)境對現(xiàn)有的基于  REST 的 API 進行轉(zhuǎn)碼。

  • Egress 高吞吐量代理。在我們的使用場景,Dropbox 和 AWS 的通信主要是 S3 這塊。最終我們會在生產(chǎn)網(wǎng)絡(luò)里下線所有的 Squid  代理,然后只留下一個 L4/L7 的數(shù)據(jù)平面。

遷移的最后一件事便是 www.dropbox.com 自己。在完成遷移后,我們便可以開始停用我們在邊緣環(huán)境部署的 Nginx  服務(wù)。一個時代即將結(jié)束。

我們遇到的一些問題

當然,整個遷移的過程并非完美無瑕。不過至少沒有導(dǎo)致任何明顯的中斷。整個遷移過程中最困難的部分是我們的 API 服務(wù)這塊。大量不同的設(shè)備通過我們的公共  API 和 Dropbox 進行通信——從 curl/wget 驅(qū)動的 Shell 腳本,以及具有自定義 HTTP/1.0  堆棧的嵌入式設(shè)備,到每個可能訪問到這里的 HTTP 庫。 Nginx 是經(jīng)過實踐檢驗的行業(yè)事實標準??梢岳斫猓蠖鄶?shù)庫都隱式地依賴于它的某些行為。除了我們的  api 用戶在依賴的 Nginx 行為這塊,在轉(zhuǎn)到 Envoy 后遇到了一些行為不一致的地方以外,我們在使用 Envoy 和它提供的類庫的過程中還發(fā)現(xiàn)了許多  bug。在社區(qū)的幫助下,所有這些問題都很快得到了解決并且反饋到了上游。

下面只是其中一些“異常的”/沒有出現(xiàn)在 RFC 里的行為的摘要:

  • 合并 URL 路徑里的斜杠。URL 規(guī)范化及斜杠合并在 Web 代理里是一項非常常見的功能。Nginx 默認啟用了斜杠歸一和斜線合并,但是 Envoy  不支持后者。我們向上游提交了一個補丁,添加了該項功能,并允許用戶通過merge_slashes 選項選擇性地加入。

  • 虛擬主機名字里的端口。Nginx 允許接收兩種形式的 Host header:要么是 example.com,又或者是  example.com:port。我們有幾個曾經(jīng)依賴于這一行為的 API 用戶。首先,我們通過在配置里復(fù)制虛擬主機(帶和不帶端口)來解決此問題,但是后來我們又在  Envoy 端添加了一個忽略匹配端口的選項:strip_matching_host_port。

  • 傳輸編碼區(qū)分大小寫。出于某種不知名的原因,一小部分子集的 API 客戶端使用了  Transfer-Encoding:Chunked(請注意大寫的“C”)header。這在技術(shù)上是可行的,因為 RFC7230 聲明了  Transfer-Encoding/TE header 不區(qū)分大小寫。修復(fù)辦法也很簡單,然后也已經(jīng)提交到了上游的 Envoy 。

  • 一個請求里同時帶有 [Content-Length](https://github.com/envoyproxy/envoy/issues/11398)  和 [Transfer-Encoding:chunked](https://github.com/envoyproxy/envoy/issues/11398)  這兩個 header。有些請求在 Nginx 下面是好的,但是遷移到 Envoy 以后就炸了。 RFC7230 有點棘手,通常大家會覺得 Web  服務(wù)器的確應(yīng)該在處理這些請求時報錯,因為它們很可能是“走私的(smuggled)”。另一方面,可能又會有人說,代理應(yīng)該去掉 Content-Length  header 然后再轉(zhuǎn)發(fā)該請求。對此,我們的做法是:我們擴展了 http-parse 然后讓使用該庫的用戶來自主選擇是否要支持這類請求,然后目前我們正在努力為  Envoy 自身引入這項功能的支持。

另外,值得一提的是,我們還遇到了一些常見的配置問題:

  • 熔斷器配置錯誤。根據(jù)我們的經(jīng)驗,如果入站代理采用 Envoy 的話,尤其是工作在 HTTP/1 以及 HTTP/2  這樣的混合環(huán)境里,那么熔斷器的配置不當可能會在流量高峰或后端中斷期間導(dǎo)致意外停機。如果不使用 Envoy 作為 mesh  代理,不妨考慮放松這塊的配置。值得一提的是,在默認情況下,Envoy 的熔斷器限制非常嚴格 ———— 特別要注意這一點!

  • 緩沖區(qū)。Nginx 允許將磁盤用作請求的緩沖區(qū)。這在用戶采用的是無法理解 chunked 傳輸編碼的傳統(tǒng)的 HTTP/1.0  后端的情況下很有用。Nginx 可以將它們先緩沖到磁盤上然后轉(zhuǎn)換成帶有 Content-Length 的請求。Envoy 有一個 Buffer  過濾器,但是由于無法將數(shù)據(jù)保存到磁盤,能夠緩沖多少內(nèi)容受限于我們機器的內(nèi)存大小。

下一步

  • HTTP/3 的黃金時代即將來臨。幾個主流瀏覽器均已加入了對 HTTP 3.0 的支持(目前由一個參數(shù)或者命令行選項來控制是否開啟)。Envoy  也已經(jīng)在進行實驗性的支持。升級 Linux 內(nèi)核支持 UDP 加速后,我們會在我們的邊緣環(huán)境上進行試驗。

  • 內(nèi)部基于 xDS 的負載均衡以及異常值檢測。目前,我們正在考慮使用負載上報服務(wù)(LRS)和端點發(fā)現(xiàn)服務(wù)(EDS)的組合作為構(gòu)建模塊,以便為 Envoy 和  gRPC 創(chuàng)建一套通用的后備型、負載感知式的負載均衡。

  • 基于 WASM 的 Envoy 擴展。等到 Golang 的 proxy-wasm SDK 可用時,我們便可以開始在 Go 里面編寫 Envoy  的擴展,這將使我們能夠訪問各種內(nèi)部的 Golang 庫。

  • 替換 Bandaid。將所有的 Dropbox 代理層統(tǒng)一成一個單個的數(shù)據(jù)平面聽上去很有吸引力。為此,我們需要將許多 Bandaid  功能(尤其是在負載均衡方面)遷移到 Envoy。這還有很長的路要走,但這是我們目前的計劃。

  • Envoy 移動端。最終,我們想看看能否將 Envoy  用于移動端的應(yīng)用程序。站在接入層的角度,在所有的移動端平臺上支持一套具有統(tǒng)一的監(jiān)控和現(xiàn)代化功能(HTTP/3,gRPC,TLS1.3  等)的單個服務(wù)棧非常耀眼。 

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Dropbox是怎么將接入層從Nginx遷移到Envoy的”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學習!


當前名稱:Dropbox是怎么將接入層從Nginx遷移到Envoy的
轉(zhuǎn)載來源:http://weahome.cn/article/gieisc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部