ffrpc-c++过程间(办事器端、客户端)通信框架

    添加时间:2013-6-7 点击量:

    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((
    XXfoo_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(测试获取类名:%s\nin.get_type_name());//输出为:测试获取类名:echo_t::in_t

    forint i = 0; i < 100; ++i)
    {
    //! 如你所想,echo接口被调用,然后echo_callback被调用,每一秒反复该过程
    ffrpc_client.call(echoin, 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

    彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
    分享到: