標籤:

cort_proto v0.9.0 第一版發布

開源一個超簡單的無棧協程原型(2) 原來我開源了一個很簡單的無棧協程,很多同學都說太toy了,不實用,好,我花約2個月的功夫(中間包含一個旅遊和一個過年,以及一次網路部分介面的大改),終於趕在正式上班前一天(其實已經到凌晨3點了)搞定一套包含了hook,tcp RPC, 有棧協程的無棧協程大餐。

github地址在:

yuanzhubi/cort_protogithub.com圖標

注意他依然只是個原型設計(prototype coroutine )下的協程,你把他用到其他非後台場景照樣可用,如果你不使用其中的定時器等系統相關的部分而只使用cort_proto.h。同理,如果你在windows或者bsd上使用,目前具有可移植性的組件也只有cort_proto.h了(此外hook的腳本你還是可以繼續在bsd上使用,但是hook的結果需要移植一下了)。

Q:這個庫能做什麼?

A:yuanzhubi/cort_proto 這裡有個發布項,我簡單說一下。

  1. 無棧協程。支持同時並發await多個無棧協程,甚至在一個協程數組區間內的所有協程。
  2. 時間等待協程。通過await這種協程,我們支持co_sleep(無阻塞睡眠),和定時任務等等(重複設鬧鐘可以實現repeater,壓測神器)。毫秒級精度, 目前僅支持linux, 因為基於epoll.
  3. 文件描述符等待協程。用他來監視io操作, 通過await這種協程,實現只在I/O可用時發起io操作,避免阻塞。目前僅支持linux, 因為基於epoll.
  4. 基於socket tcp的無阻塞協程rpc(沒有引入netmap或者dpdk)。目前先把半雙工的ping-pong rpc 支持了(這是rpc的絕對主流方式,,除了http2),長連接當然也是支持的。下一階段會支持流式的全雙工io操作(實現不難,但是全雙工測試比較難,為了避免N久之後才上線,所以這個版本先不上。。沒有那麼多人要開發聊天室吧),以及udp操作。
  5. 有棧協程和hook。支持像libco一樣的有棧協程+hook,但是我們用的是鏈接前靜態hook靜態庫或者目標文件,性能更佳而且可以選擇對哪些庫hook, 哪些庫不hook, 哪些庫的hook結果和其他庫不一樣,完全自由。也支持把有棧協程包裝成無棧協程來和其他無棧協程一起並發await。我們提供了絕大部分網路函數基於"3."的hook, 使用static_hook.sh 對你需要hook的庫進行hook。壓測示例中用Libcurl來做了個hook示例。如果你不用腳本去hook處理你的代碼,和libco不同,此項功能的啟用後也是零開銷的。
  6. 極簡的編程(無棧協程帶來的好處),對外部庫高度親和(用hook+有棧協程唄,如果你連http1或者redis這樣的協議都懶得解),極易的測試和壓測(附帶了很多用來定時或並發發起請求的基礎設施)。未來會貼一些在不同環境下的壓力測試結果(基本瓶頸都落到內核,帶寬這些地方,所以結果和環境有很大關係)。
  7. 不錯的tcp性能。2月份剛買的騰訊雲最便宜的65元 單核1GHz 1G內存 1M帶寬,還打了熔斷補丁的x64 centos機器上, 50bytes echo, 設置300ms超時,3s長連接過期,同時部署服務端和客戶端(也在這一個核上運行!) 6wqps壓測下性能和機器佔用如下(這台機裝redis也就只能跑個3萬不到的get-set, 除了把埠範圍稍微調大了些,禁用了交換分區外,沒有做任何內核參數的修改),注意耗時平均很小,是因為很多請求處理少於1ms 所以被當成了0。。內存開銷很小這倒是真的。吐槽一下這個最便宜的雲主機連rdtscp指令都不支持。

Q: 這個庫怎麼用?

A:

  1. make 會生成libcort_proto.a和測試程序, 你還可以去修改make_lib來剔除你不需要的模塊或者修改編譯選項。 以後記得鏈接它來用咯。
  2. static_hook.sh 用來hook第三方的靜態庫。make_pressure_test.sh 裡面有個hook libcurl的例子。
  3. 用法可以參考unit_test pressure_test(如果你做網路編程就看pressure_test里的例子吧)裡面的內容。或者直接issue。易用性的提升也是我的設計目標。

Q: 接下來他還有什麼後續消息?

A: 我會寫一個系列來介紹他的使用和設計,包括但不限於以下系列:

  1. 平常編程,包括RPC的主要痛點在哪裡?為什麼我們需要協程?
  2. 有棧協程的好處在哪裡?為什麼還需要無棧協程?C++20傳說中的協程提案怎樣?c++出現這麼多年了為什麼還有人沉迷於達夫設備?沒有有棧協程的純無棧協程為什麼不方便接入第三方庫?
  3. cort_proto的設計邊界:不允許跨協程亂用異常!不允許單獨取消一個在等待中的協程!級聯取消比異常回卷還邪惡!
  4. 性能第一要素:定時器的數據結構選擇。redis為什麼單核能那麼快?
  5. 可測試性設計的第一要素:後台程序和服務也得優雅關閉!不帶內存泄漏的退出!不許ctrl+c。仔細討論有棧協程和無棧協程是怎麼依序回收的。
  6. 天大的秘密:tcp連接對於用戶態代碼是個弱引用對象!不用引用計數來寫框架面對長連接時複雜度會指數爆炸(5年前我還以為muduo用引用計數是偷懶,後來才漸漸發現自己很多網路邊界條件沒有考慮到,或者過於延遲的進行一些資源的回收)!如何在tcp連接的狀態變化中插入我們的用戶態代碼,並儘快響應連接狀態中來自對端的變化?
  7. 儘可能最小化服務端和客戶端的設計差異,但要重視他們的參數配置上的差異。為什麼cort_proto的tcp連接不處理自連接?
  8. 怎樣儘可能精確的壓測?壓測關心的內容包括哪些?
  9. hook的各種流派,libco,libgo等等,,,為什麼hook+有棧協程是一種偷懶而保險的引入第三方庫的方法?為什麼Go和C語言庫通信那麼痛苦?
  10. rpc框架=網路庫+日誌庫,日誌庫會下一階段進行開源。

推薦閱讀:

深入python協程的實現,帶你一層一層揭開協程的神秘面紗!

TAG:協程 | 高並發 |