1. 程式人生 > 其它 >Linux Shell 從入門到刪除根目錄跑路指南

Linux Shell 從入門到刪除根目錄跑路指南

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