Linux Shell 從入門到刪除根目錄跑路指南
阿新 • • 發佈:2022-04-28
FFRPC
github 地址 https://github.com/fanchy/FFRPC
FFRPC 已經陸陸續續開發了1年,6月6日這天終於完成了我比較滿意的版本,暫稱之為 V0.2,FFRPC實現了一個C++版本 的非同步程序間通訊庫。我本身是做遊戲伺服器程式的,在伺服器程式領域,系統是分散式的,各個節點需要非同步的進行通訊, 我的初衷是開發一個易用、易測試的程序間socket通訊元件。實際上FFRPC 已經是一個框架。
FFRPC 主要特性
- FFRPC 採用Epoll Edge Trigger模式,這裡特別提一下ET是因為在非同步工作模式,ET方式才是epoll最簡單也是最高效的方式 網上的很多帖子寫LT簡單易用,那純碎是沒有理解ET的精髓之所在,如果讀者想要從ffrpc中探究一下ET的奧妙,提醒讀者的是 請把Epoll 看成一個狀態機!FFRPC 採用Broker模式,這樣的好處是 Scalability!! 在遊戲領域的開發者一定很熟悉Master/Gateway/Logic Server的概念, 實際上Master 實際上扮演的Broker master的角色,而gateway扮演的是Broker slave的角色,Broker Slave負責轉發客戶端的 請求到Logic Service,提供一個轉發層雖然會增加延遲,但是系統變得可擴充套件,大大提高了吞吐量,這就是Scalability!! 而Broker master負責管理所有的Master Slave,負責負載均衡。不同的client分配不同的Broker SLave。
- FFRPC 就是基於以上的思路,有如下四個關鍵的概念:
- 一:broker master 負責負載均衡,同步所有節點的資訊,所有的slave broker和rpc service/ rpc cleint都要連線broker master。
- 二:slave broker負責完成service和client間轉發訊息,如果service、client和broker在同一程序,那麼直接在記憶體間投遞訊息, 這是v0。2的重要的優化,v0。1時沒有此功能,網友很多反應這個問題,看來大夥對優化還是太敏感! 另一個創新之處在於ffmsg_t,封裝了訊息的序列化和反序列化,我已經厭倦了protobuff,如果你也研究了為每個訊息定義cmd 和為cmd寫switch(有些人可能已經用上註冊回撥函式,但還有更好用的)。實際上定義訊息結構體時一個訊息本身就是獨一無二的, 所以為什麼我們還要給訊息在定義一個cmd呢?比如定義了struct echo_t{int a;}訊息,echo_t名稱本身就是獨一無二的,否則編譯 器肯定報錯了,那麼為什麼不直接用echo_t這個名稱作為cmd呢?在FFRPC中可以使用TYPE_NAME(echo_t)獲得訊息體名稱字串, 是滴TYPE_NAME是一個很有意思的實現,c++中並沒喲關鍵字可以獲取一個類的名稱,但是所有的編譯器都實際上已經提供了這個功能! 詳情請看原始碼。有讀者可能會糾結使用訊息體結構的名稱做cmd固然省事,但是浪費了流量!32位的cmd總是比字串省流量,是的這個 結論雖然我很不喜歡(我總是懶的優化,除非...被逼的),但是他是對的!ffrpc中很好的解決了這個問題,當每個節點初始化時都要 註冊到broker master,這時所有的訊息都會在master中分配一個唯一的msg id,這樣就可以用整數1代表echo_t結構了,由於每個節點 都知道echo_t到1的對映,所以程式設計師再也不用手動定義cmd了,broker唯一初始化時動態定義。
- 三:ffrpc service,提供介面的模組,也就就是服務端,通過ffrpc類註冊的介面基於非同步模式,推薦的模式是每個訊息都返回 一個結果訊息
- 四:ffrpc client是呼叫的ffrpc service的模組,基於非同步模式,記住服務名成和訊息名稱唯一的確定一個介面,這個c++的類和類介面 概念是一致的,而且呼叫遠端介面時可以指定回撥函式,而且回撥函式還支援lambda引數繫結!
- 想快速見證ffrpc庫的魅力可以小看如下的示例,只要你有linux系統,可以1分鐘內測試這個示例,ffrpc沒有其他依賴,提醒你的是 FFRPC的日誌元件是彩色的哦!
示例程式碼
#include <stdio.h> #include "base/daemon_tool.h" #include "base/arg_helper.h" #include "base/strtool.h" #include "base/smart_ptr.h" #include "rpc/ffrpc.h" #include "rpc/ffbroker.h" #include "base/log.h" using namespace ff; //! 定義echo 介面的訊息, in_t代表輸入訊息,out_t代表的結果訊息 //! 提醒大家的是,這裡沒有為echo_t定義神馬cmd,也沒有制定其名稱,ffmsg_t會自動能夠獲取echo_t的名稱 struct echo_t { struct in_t: public ffmsg_t<in_t> { void encode() { encoder() << data; } void decode() { decoder() >> data; } string data; }; struct out_t: public ffmsg_t<out_t> { void encode() { encoder() << data; } void decode() { decoder() >> data; } string data; }; }; struct foo_t { //! echo介面,返回請求的傳送的訊息ffreq_t可以提供兩個模板引數,第一個表示輸入的訊息(請求者傳送的) //! 第二個模板引數表示該介面要返回的結果訊息型別 void echo(ffreq_t<echo_t::in_t, echo_t::out_t>& req_) { echo_t::out_t out; out.data = req_.arg.data; LOGDEBUG(("XX", "foo_t::echo: %s", req_.arg.data.c_str())); req_.response(out); } //! 遠端呼叫介面,可以指定回撥函式(也可以留空),同樣使用ffreq_t指定輸入訊息型別,並且可以使用lambda繫結引數 void echo_callback(ffreq_t<echo_t::out_t>& req_, int index) { LOGDEBUG(("XX", "%s %s %d", __FUNCTION__, req_.arg.data.c_str(), index)); } }; int main(int argc, char* argv[]) { //! 美麗的日誌元件,shell輸出是彩色滴!! LOG.start("-log_path ./log -log_filename log -log_class XX,BROKER,FFRPC -log_print_screen true -log_print_file true -log_level 6"); //! 啟動broker,負責網路相關的操作,如訊息轉發,節點註冊,重連等 ffbroker_t ffbroker; ffbroker.open("app -l tcp://127.0.0.1:10241"); //! broker客戶端,可以註冊到broker,並註冊服務以及介面,也可以遠端呼叫其他節點的介面 ffrpc_t ffrpc_service("echo"); foo_t foo; ffrpc_service.reg(&foo_t::echo, &foo); ffrpc_service.open("app -broker tcp://127.0.0.1:10241"); ffrpc_t ffrpc_client; ffrpc_client.open("app -broker tcp://127.0.0.1:10241"); echo_t::in_t in; in.data = "helloworld"; //! 你沒有看見get_type_name定義,但是他確定存在 printf("測試獲取類名:%sn", in.get_type_name());//輸出為:測試獲取類名:echo_t::in_t for (int i = 0; i < 100; ++i) { //! 如你所想,echo介面被呼叫,然後echo_callback被呼叫,每一秒重複該過程 ffrpc_client.call("echo", in, ffrpc_ops_t::gen_callback(&foo_t::echo_callback, &foo, i)); sleep(1); } sleep(300); ffbroker.close(); return 0; }
總結
- ffrpc中broker、client、service可以啟動在不同的程序,如果在同一程序,那麼直接記憶體間投遞訊息
- ffrpc 每個例項單獨啟動一個執行緒和任務佇列,保證service和client的操作都是有序、執行緒安全的。
- 如果你研究過protobuff、thrift、zeromq、ice等等類庫/框架, 更要試用一下ffrpc。
- github 地址 https://github.com/fanchy/FFRPC