很早前就想寫一篇關于 eBPF 的文章,但是遲遲沒有動手,這兩天有點時間,所以就來寫一篇。這文章主要還是簡單的介紹 eBPF 是用來干什么的,并通過幾個示例來介紹是怎么玩的。這個技術非常非常之強,Linux 操作系統(tǒng)的觀測性實在是太強大了,并在 BCC 加持下變得一覽無余。這個技術不是一般的運維人員或是系統(tǒng)管理員可以駕馭的,這個還是要有底層系統(tǒng)知識并有一定開發(fā)能力的技術人員才能駕馭的了的。我在這篇文章的最后給了個彩蛋。
介紹
eBPF(extened Berkeley Packet Filter)是一種內核技術,它允許開發(fā)人員在不修改內核代碼的情況下運行特定的功能。eBPF 的概念源自于 Berkeley Packet Filter(BPF),后者是由貝爾實驗室開發(fā)的一種網(wǎng)絡過濾器,可以捕獲和過濾網(wǎng)絡數(shù)據(jù)包。
出于對更好的 Linux 跟蹤工具的需求,eBPF 從 dtrace中汲取靈感,dtrace 是一種主要用于 Solaris 和 BSD 操作系統(tǒng)的動態(tài)跟蹤工具。與 dtrace 不同,Linux 無法全面了解正在運行的系統(tǒng),因為它僅限于系統(tǒng)調用、庫調用和函數(shù)的特定框架。
在 Berkeley Packet Filter(BPF)(一種使用內核 VM 編寫打包過濾代碼的工具)的基礎上,一小群工程師開始擴展 BPF 后端以提供與 dtrace 類似的功能集。eBPF 誕生了。2014 年隨 Linux 3.18 首次限量發(fā)布,充分利用 eBPF 至少需要 Linux 4.4 以上版本。
eBPF 比起傳統(tǒng)的 BPF 來說,傳統(tǒng)的 BPF 只能用于網(wǎng)絡過濾,而 eBPF 則可以用于更多的應用場景,包括網(wǎng)絡監(jiān)控、安全過濾和性能分析等。另外,eBPF 允許常規(guī)用戶空間應用程序將要在 Linux 內核中執(zhí)行的邏輯打包為字節(jié)碼,當某些事件(稱為掛鉤)發(fā)生時,內核會調用 eBPF 程序。此類掛鉤的示例包括系統(tǒng)調用、網(wǎng)絡事件等。用于編寫和調試 eBPF 程序的最流行的工具鏈稱為 BPF 編譯器集合(BCC),它基于 LLVM 和 CLang。
eBPF 有一些類似的工具。例如,SystemTap 是一種開源工具,可以幫助用戶收集 Linux 內核的運行時數(shù)據(jù)。它通過動態(tài)加載內核模塊來實現(xiàn)這一功能,類似于 eBPF。另外,DTrace 是一種動態(tài)跟蹤和分析工具,可以用于收集系統(tǒng)的運行時數(shù)據(jù),類似于 eBPF 和 SystemTap。[Ⅰ]
以下是一個簡單的比較表格,可以幫助您更好地了解 eBPF、SystemTap 和 DTrace 這三種工具的不同之處:[Ⅰ]
工具 | eBPF | SystemTap | DTrace |
---|---|---|---|
定位 | 內核技術,可用于多種應用場景 | 內核模塊 | 動態(tài)跟蹤和分析工具 |
工作原理 | 動態(tài)加載和執(zhí)行無損編譯過的代碼 | 動態(tài)加載內核模塊 | 動態(tài)插接分析器,通過 probe 獲取數(shù)據(jù)并進行分析 |
常見用途 | 網(wǎng)絡監(jiān)控、安全過濾、性能分析等 | 系統(tǒng)性能分析、故障診斷等 | 系統(tǒng)性能分析、故障診斷等 |
優(yōu)點 | 靈活、安全、可用于多種應用場景 | 功能強大、可視化界面 | 功能強大、高性能、支持多種編程語言 |
缺點 | 學習曲線高,安全性依賴于編譯器的正確性 | 學習曲線高,安全性依賴于內核模塊的正確性 | 配置復雜,對系統(tǒng)性能影響較大 |
對比表格[Ⅰ]
從上表可以看出,eBPF、SystemTap 和 DTrace 都是非常強大的工具,可以用于收集和分析系統(tǒng)的運行情況。[Ⅰ]
用途
eBPF 是一種非常靈活和強大的內核技術,可以用于多種應用場景。下面是 eBPF 的一些常見用途:[Ⅰ]
網(wǎng)絡監(jiān)控:eBPF 可以用于捕獲網(wǎng)絡數(shù)據(jù)包,并執(zhí)行特定的邏輯來分析網(wǎng)絡流量。例如,可以使用 eBPF 程序來監(jiān)控網(wǎng)絡流量,并在發(fā)現(xiàn)異常流量時進行警報。[Ⅰ]
安全過濾:eBPF 可以用于對網(wǎng)絡數(shù)據(jù)包進行安全過濾。例如,可以使用 eBPF 程序來阻止惡意流量的傳播,或者在發(fā)現(xiàn)惡意流量時對其進行攔截。[Ⅰ]
性能分析:eBPF 可以用于對內核的性能進行分析。例如,可以使用 eBPF 程序來收集內核的性能指標,并通過特定的接口將其可視化。這樣,可以更好地了解內核的性能瓶頸,并進行優(yōu)化。[Ⅰ]
虛擬化:eBPF 可以用于虛擬化技術。例如,可以使用 eBPF 程序來收集虛擬機的性能指標,并進行負載均衡。這樣,可以更好地利用虛擬化環(huán)境的資源,提高系統(tǒng)的性能和穩(wěn)定性。[Ⅰ]
總之,eBPF 的常見用途非常廣泛,可以用于網(wǎng)絡監(jiān)控、安全過濾、性能分析和虛擬化等多種應用場景。[Ⅰ]
基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
項目地址:https://github.com/YunaiV/ruoyi-vue-pro
視頻教程:https://doc.iocoder.cn/video/
工作原理
eBPF 的工作原理主要分為三個步驟:加載、編譯和執(zhí)行。
eBPF 需要在內核中運行。這通常是由用戶態(tài)的應用程序完成的,它會通過系統(tǒng)調用來加載 eBPF 程序。在加載過程中,內核會將 eBPF 程序的代碼復制到內核空間。
eBPF 程序需要經(jīng)過編譯和執(zhí)行。這通常是由Clang/LLVM的編譯器完成,然后形成字節(jié)碼后,將用戶態(tài)的字節(jié)碼裝載進內核,并通過一個JIT編譯步驟將程序的通用字節(jié)碼轉換為機器特定指令集,以優(yōu)化程序的執(zhí)行速度。
在內核中運行時,eBPF 程序通常會掛載到一個內核鉤子(hook)上,以便在特定的事件發(fā)生時被執(zhí)行。例如,可以將 eBPF 程序掛載到網(wǎng)絡協(xié)議棧的某個位置,以便在收到網(wǎng)絡數(shù)據(jù)包時被執(zhí)行。
最后,eBPF 程序還需要經(jīng)過內核安全機制的檢查。這是為了確保 eBPF 程序不會破壞內核的穩(wěn)定性和安全性。在檢查過程中,內核會對 eBPF 程序的代碼進行分析,以確保它不會進行惡意操作,如系統(tǒng)調用、內存訪問等。如果 eBPF 程序通過了內核安全機制的檢查,它就可以在內核中正常運行了。在運行過程中,eBPF 程序可以訪問內核的數(shù)據(jù)結構,并通過內核接口與其他組件進行交互。例如,eBPF 程序可以捕獲網(wǎng)絡數(shù)據(jù)包,并通過內核接口將它們轉發(fā)給用戶態(tài)的應用程序。總之,eBPF 的工作原理是通過動態(tài)加載、執(zhí)行和檢查無損編譯過的代碼來實現(xiàn)的。[Ⅰ]
下圖是其架構圖。
圖片來自:https://www.infoq.com/articles/gentle-linux-ebpf-introduction/
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權限、多租戶、數(shù)據(jù)權限、工作流、三方登錄、支付、短信、商城等功能
項目地址:https://github.com/YunaiV/yudao-cloud
視頻教程:https://doc.iocoder.cn/video/
示例
eBPF 可以用于對內核的性能進行分析。下面是一個基于 eBPF 的性能分析的 step-by-step 示例:
第一步:準備工作:首先,需要確保內核已經(jīng)支持 eBPF 功能。這通常需要在內核配置文件中啟用 eBPF 相關的選項,并重新編譯內核。檢查是否支持 eBPF,你可以用這兩個命令查看 ls /sys/fs/bpf 和 lsmod | grep bpf。
第二步:寫 eBPF 程序:接下來,需要編寫 eBPF 程序,用于收集內核的性能指標。eBPF 程序的語言可以選擇 C 或者 Python,它需要通過特定的接口訪問內核的數(shù)據(jù)結構,并將收集到的數(shù)據(jù)保存到指定的位置。
下面是一個 Python 示例:
#!/usr/bin/python3 from?bcc?import?BPF from?time?import?sleep #?定義?eBPF?程序 bpf_text?=?""" #include?BPF_HASH(stats,?u32); int?count(struct?pt_regs?*ctx)?{ ????u32?key?=?0; ????u64?*val,?zero=0; ????val?=?stats.lookup_or_init(&key,?&zero); ????(*val)++; ????return?0; } """ #?編譯?eBPF?程序 b?=?BPF(text=bpf_text,?cflags=["-Wno-macro-redefined"]) #?加載?eBPF?程序 b.attach_kprobe(event="tcp_sendmsg",?fn_name="count") name?=?{ ??0:?"tcp_sendmsg" } #?輸出統(tǒng)計結果 while?True: ????try: ????????#print("Total?packets:?%d"?%?b["stats"][0].value) ????????for?k,?v?in?b["stats"].items(): ???????????print("{}:?{}".format(name[k.value],?v.value)) ????????sleep(1) ????except?KeyboardInterrupt: ????????exit()
這個 eBPF 程序的功能是統(tǒng)計網(wǎng)絡中傳輸?shù)臄?shù)據(jù)包數(shù)量。它通過定義一個 BPF_HASH 數(shù)據(jù)結構來保存統(tǒng)計結果,并通過捕獲 tcp_sendmsg 事件來實現(xiàn)實時統(tǒng)計。最后,它通過每秒輸出一次統(tǒng)計結果來展示數(shù)據(jù)。這個 eBPF 程序只是一個簡單的示例,實際應用中可能需要進行更復雜的統(tǒng)計和分析。
第三步:運行 eBPF 程序:接下來,需要使用eBPF編譯器將 eBPF 程序編譯成內核可執(zhí)行的格式(這個在上面的Python程序里你可以看到——Python引入了一個bcc的包,然后用這個包,把那段 C語言的程序編譯成字節(jié)碼加載在內核中并把某個函數(shù)attach到某個事件上)。這個過程可以使用 BPF Compiler Collection(BCC)工具來完成。BCC 工具可以通過命令行的方式將 eBPF 程序編譯成內核可執(zhí)行的格式,并將其加載到內核中。
下面是運行上面的 Python3 程序的步驟:
sudo?apt?install?python3-bpfcc
注:在Python3下請不要使用 pip3 install bcc (參看:https://github.com/iovisor/bcc/issues/2278#issuecomment-825356087)
如果你是 Ubuntu 20.10 以上的版本,最好通過源碼安裝(否則程序會有編譯問題),參看https://github.com/iovisor/bcc/issues/3993#issuecomment-1228217609:
apt?purge?bpfcc-tools?libbpfcc?python3-bpfcc wget?https://github.com/iovisor/bcc/releases/download/v0.25.0/bcc-src-with-submodule.tar.gz tar?xf?bcc-src-with-submodule.tar.gz cd?bcc/ apt?install?-y?python-is-python3 apt?install?-y?bison?build-essential?cmake?flex?git?libedit-dev???libllvm11?llvm-11-dev?libclang-11-dev?zlib1g-dev?libelf-dev?libfl-dev?python3-distutils apt?install?-y?checkinstall mkdir?build cd?build/ cmake?-DCMAKE_INSTALL_PREFIX=/usr?-DPYTHON_CMD=python3?.. make checkinstall
接下來,需要將上面的 Python 程序保存到本地,例如保存到文件 netstat.py。運行程序:最后,可以通過執(zhí)行以下命令來運行 Python 程序:
$?chmod?+x?./netstat.py $?sudo?./netstat.py tcp_sendmsg:?29 tcp_sendmsg:?216 tcp_sendmsg:?277 tcp_sendmsg:?379 tcp_sendmsg:?419 tcp_sendmsg:?468 tcp_sendmsg:?574 tcp_sendmsg:?645 tcp_sendmsg:?29
程序開始運行后,會在控制臺輸出網(wǎng)絡數(shù)據(jù)包的統(tǒng)計信息??梢酝ㄟ^按 Ctrl+C 組合鍵來結束程序的運行。
下面我們再看一個比較復雜的示例,這個示例會計算TCP??的發(fā)包時間(示例參考于 Github 上這個 issue[1] 里的程序):
#!/usr/bin/python3 from?bcc?import?BPF import?time #?定義?eBPF?程序 bpf_text?=?""" #include?#include? #include? #include? struct?packet_t?{ ????u64?ts,?size; ????u32?pid; ????u32?saddr,?daddr; ????u16?sport,?dport; }; BPF_HASH(packets,?u64,?struct?packet_t); int?on_send(struct?pt_regs?*ctx,?struct?sock?*sk,?struct?msghdr?*msg,?size_t?size) { ????u64?id?=?bpf_get_current_pid_tgid(); ????u32?pid?=?id; ????//?記錄數(shù)據(jù)包的時間戳和信息 ????struct?packet_t?pkt?=?{};?//?結構體一定要初始化,可以使用下面的方法 ??????????????????????????????//__builtin_memset(&pkt,?0,?sizeof(pkt));? ????pkt.ts?=?bpf_ktime_get_ns(); ????pkt.size?=?size; ????pkt.pid?=?pid; ????pkt.saddr?=?sk->__sk_common.skc_rcv_saddr; ????pkt.daddr?=?sk->__sk_common.skc_daddr; ????struct?inet_sock?*sockp?=?(struct?inet_sock?*)sk; ????pkt.sport?=?sockp->inet_sport; ????pkt.dport?=?sk->__sk_common.skc_dport; ????packets.update(&id,?&pkt); ????return?0; } int?on_recv(struct?pt_regs?*ctx,?struct?sock?*sk) { ????u64?id?=?bpf_get_current_pid_tgid(); ????u32?pid?=?id; ????//?獲取數(shù)據(jù)包的時間戳和編號 ????struct?packet_t?*pkt?=?packets.lookup(&id); ????if?(!pkt)?{ ????????return?0; ????} ????//?計算傳輸時間 ????u64?delta?=?bpf_ktime_get_ns()?-?pkt->ts; ????//?統(tǒng)計結果 ????bpf_trace_printk("tcp_time:?%llu.%llums,?size:?%llu\n",? ???????delta/1000,?delta%1000%100,?pkt->size); ????//?刪除統(tǒng)計結果 ????packets.delete(&id); ????return?0; } """ #?編譯?eBPF?程序 b?=?BPF(text=bpf_text,?cflags=["-Wno-macro-redefined"]) #?注冊?eBPF?程序 b.attach_kprobe(event="tcp_sendmsg",?fn_name="on_send") b.attach_kprobe(event="tcp_v4_do_rcv",?fn_name="on_recv") #?輸出統(tǒng)計信息 print("Tracing?TCP?latency...?Hit?Ctrl-C?to?end.") while?True: ????try: ????????(task,?pid,?cpu,?flags,?ts,?msg)?=?b.trace_fields() ????????print("%-18.9f?%-16s?%-6d?%s"?%?(ts,?task,?pid,?msg)) ????except?KeyboardInterrupt: ????????exit()
上面這個程序通過捕獲每個數(shù)據(jù)包的時間戳來統(tǒng)計傳輸時間。在捕獲 tcp_sendmsg 事件時,記錄數(shù)據(jù)包的發(fā)送時間;在捕獲 tcp_v4_do_rcv 事件時,記錄數(shù)據(jù)包的接收時間;最后,通過比較兩個時間戳來計算傳輸時間。
從上面的兩個程序我們可以看到,eBPF 的一個編程的基本方法,這樣的在 Python 里向內核的某些事件掛載一段 “C語言” 的方式就是 eBPF 的編程方式。
實話實說,這樣的代碼很不好寫,而且有很多非常詭異的東西,一般人是很難駕馭的(上面的代碼我也很不是很容易都能寫通的,把 Google 都用了個底兒掉,讀了很多晦澀的文檔……)。好在這樣的代碼已經(jīng)有人寫了,我們不必再寫了,在 Github 上的 bcc 庫下的 tools 目錄[2]有很多……
BCC(BPF Compiler Collection)是一套開源的工具集,可以在 Linux 系統(tǒng)中使用 BPF(Berkeley Packet Filter)程序進行系統(tǒng)級性能分析和監(jiān)測。BCC 包含了許多實用工具,如:
bcc-tools:一個包含許多常用的 BCC 工具的軟件包。
bpftrace:一個高級語言,用于編寫和執(zhí)行 BPF 程序。
tcptop:一個實時監(jiān)控和分析 TCP 流量的工具。
execsnoop:一個用于監(jiān)控進程執(zhí)行情況的工具。
filetop:一個實時監(jiān)控和分析文件系統(tǒng)流量的工具。
trace:一個用于跟蹤和分析函數(shù)調用的工具。
funccount:一個用于統(tǒng)計函數(shù)調用次數(shù)的工具。
opensnoop:一個用于監(jiān)控文件打開操作的工具。
pidstat:一個用于監(jiān)控進程性能的工具。
profile:一個用于分析系統(tǒng) CPU 使用情況的工具。
下面這張圖你可能見過多次了,你可以看看他可以干多少事,內核里發(fā)生什么事一覽無余。
延伸閱讀
一些經(jīng)典的文章和書籍關于 eBPF 包括:
Brendan Gregg 的《BPF Performance Tools: Linux System and Application Observability[3]》一書是一個全面的指南,涵蓋了 eBPF 的基礎知識和實踐應用。
eBPF 的官網(wǎng):https://ebpf.io/ 由 Cilium 建立
Cilium’s BPF and XDP Reference Guide:http://docs.cilium.io/en/latest/bpf/
BPF Documentation:https://www.kernel.org/doc/html/latest/bpf/index.html
BPF Design Q&A:https://www.kernel.org/doc/html/latest/bpf/bpf_design_QA.html
還有 Github 上的 Awesome eBPF:https://github.com/zoidbergwill/awesome-ebpf
彩蛋
最后來到彩蛋環(huán)節(jié)。因為最近 ChatGPT 很火,于是,我想通過 ChatGPT 來幫助我書寫這篇文章,一開始我讓 ChatGPT 幫我列提綱,并根據(jù)提綱生成文章內容,并查找相關的資料,非常之順利,包括生成的代碼,我以為我們以很快地完成這篇文章。
但是,到了代碼生成的時候,我發(fā)現(xiàn),ChatGPT 生成的代碼的思路和方法都是對的,但是是比較老的,而且是跑不起來的,出現(xiàn)了好些低級錯誤,如:使用了未聲明的變量,沒有引用完整的C語言的頭文件,沒有正確地初始化變量,錯誤地獲取數(shù)據(jù),類型沒有匹配……等等,在程序調試上,挖了很多的坑,C 語言本來就不好搞,挖的很多運行時的坑很難察覺。
所以,耗費了我大量的時間來排除各種各樣的問題,其中有環(huán)境上的問題,還有代碼上的問題,這些問題即便是通過 Google 也不容易找到解決方案,我找到的解決方案都放在文章中了,尤其是第二個示例,讓我調試了3個多小時,讀了很多 bcc 上的 issue 和相關的晦澀的手冊和文檔,才讓程序跑通。
到了文章收關的階段,我讓 ChatGPT 給我?guī)讉€延伸閱讀,也是很好的,但是沒有給出鏈接,于是我只得人肉 Google 了一下,然后讓我吃驚的是,好多 ChatGPT 給出來的文章是根本不存在的,完全是它偽造的。我連讓它干了兩次都是這樣,這個讓我驚掉大牙。
這讓我開始懷疑它之前生成的內容,于是,我不得我返回仔細 Review 我的文章,尤其是“介紹”、“用途”和“工作原理”這三個章節(jié),基本都是 ChatGPT 生成的,在 Review 完后,我發(fā)現(xiàn)了 ChatGPT 給我生造了一個叫 “無損編譯器”的術語,這個術語簡直了,于是我開始重寫我的文章。我把一些段落重寫了,有一些沒有,保留下來的我都標記上了 [Ⅰ],大家讀的時候要小心閱讀。
最后,我的結論是,ChatGPT 只是一個不成熟的玩具,只能回答一些沒有價值的日常聊天的問題,要說能取代 Google,我覺得不可能,因為 Google 會基于基本的事實,而 ChatGPT 會基于內容生成的算法,在造假方面稱得上是高手,可以列為電信詐騙的范疇了,我以后不會再使用 ChatGPT 生成文章內容或是作我的幫手了。StackOverflow 把其 ban 了真是不能太贊了!
附件一:ChatGPT的造假載圖和樣本
?
ChatGPT 生成的樣本一
Brendan Gregg 的《BPF Performance Tools: Linux System and Application Observability》一書是一個全面的指南,涵蓋了 eBPF 的基礎知識和實踐應用。
Alexei Starovoitov 在 2015 年的 LPC 大會上發(fā)表的《eBPF and XDP: fast programmable datapath in the Linux kernel》一文,是一個介紹 eBPF 和 XDP(eXpress Data Path)的綜述。
谷歌的《BPF: The Future of Linux Monitoring and Observability》一文介紹了 eBPF 的基本概念,并探討了它對于 Linux 監(jiān)控和可觀察性的影響。
微軟的《A Survey of Techniques for Hardware Acceleration of BPF》一文,介紹了 eBPF 在硬件加速方面的研究現(xiàn)狀。
Daniel Borkmann 的《Linux kernel networking: implementation and theory》一書涵蓋了 eBPF 的實現(xiàn)和理論。
Martin KaFai Lau 在 2015 年的 SOSP 大會上發(fā)表的《eBPF: a new execution environment for the Linux kernel》一文,介紹了 eBPF 在 Linux 內核中的新執(zhí)行環(huán)境。
來自兩名谷歌工程師的《eBPF: A New Frontier in Performance Analysis》一文,探討了 eBPF 對性能分析的影響。
《BPF Performance Tools: Linux System and Application Observability》一書中的第三章,討論了 eBPF 的編譯器和運行時系統(tǒng)。
來自三名谷歌工程師的《eBPF: The New Solaris DTrace》一文,比較了 eBPF 和 Solaris DTrace 系統(tǒng)的區(qū)別。
ChatGPT 生成的樣本二
eBPF 程序開發(fā)指南:https://cilium.io/doc/ebpf/ebpf-guide/
eBPF 官方文檔:https://www.kernel.org/doc/Documentation/networking/filter.txt
Linux 內核 eBPF 介紹:https://www.ibm.com/developerworks/cn/linux/kernel/ebpf/index.html
eBPF 性能優(yōu)化技巧:https://www.infoq.com/cn/news/2018/08/ebpf-performance-tips/
eBPF 實戰(zhàn)經(jīng)驗分享:https://blog.cloudflare.com/ebpf-in-practice/
eBPF 在網(wǎng)絡安全中的應用:https://www.zdnet.com/article/ebpf-how-to-use-it-for-network-security/
eBPF 實現(xiàn) Linux 系統(tǒng)性能監(jiān)控:https://www.percona.com/blog/2017/08/15/how-to-use-ebpf-to-monitor-linux-system-performance/
eBPF 入門教程:https://sysdig.com/?blog/ebpf-getting-started/
eBPF 與 BPF 比較:https://lwn.net/Articles/724647/
eBPF 提高課程:https://www.pluralsight.com/courses/ebpf-advanced
附件二:發(fā)明的術語:無損編譯器
?
相關鏈接:
https://github.com/iovisor/bcc/issues/2972
https://github.com/iovisor/bcc/tree/master/tools
https://book.douban.com/subject/34467459
作者介紹
陳皓:網(wǎng)名“左耳朵耗子”。前阿里云資深架構師、亞馬遜高級研發(fā)經(jīng)理,擁有 20 多年互聯(lián)網(wǎng)和金融行業(yè)從業(yè)經(jīng)驗?,F(xiàn)任 MegaEase 創(chuàng)始人,致力于為企業(yè)提供 Cloud Native 和行業(yè)頭部企業(yè)(亞馬遜/ 阿里)標準的高可用、高性能和高并發(fā)架構的技術產(chǎn)品。
編輯:黃飛
評論
查看更多