当前位置: 首页 > 工具软件 > CAF > 使用案例 >

CAF(C++ Actor Framework)介绍

黄昊
2023-12-01

一. 描述.


caf是一个actor模型的开源编程框架,  强c++11风格的实现, 早先的名字并不叫CAF, 而是CPPA. 改名的时间发生在版本(0.9 >> 0.10). 而最近的版本

是0.11.2, 从文档上看, caf的实现参考了akka和erlang.  默认的actor调度是基于线程池方式, 而不是协程. 因此更像akka. 由于caf是基于c++的实现, 

在性能上可能更占优势.  更让人无法拒绝的是在caf中大量使用了lambda表达式来替换通常散落一地的回调函数.  视觉上非常直观, 开发时可以少

死很多脑细胞.  当然这个项目现在还非常新, 网络io部分也比较瘦, 养肥了再用到生产环境中不迟.


二. caf的主要特性


1. actor

actor分为两种, 无类型actor和强类型actor. actor的创建非常简单, 简单到不能再简单了, 如下面的例子. 将一个自由函数作为参数传递spawn, 

一个actor就生成了, 在下面的例子中actorx内部持有一个actor的句柄self. 所有与这个actor有关的消息都从这里开始.

void actorx(event_based_actor* self)
{

}
spawn(actorx);

2. 模式匹配.

模式匹配是caf中一个十分重要的特性, 它直接导致了caf基于lambda表达式的消息回调列表成为可能. caf为此自己内建了DSL语言来达成这个目的.

下面效果就是来自模式匹配.

void actorx(event_based_actor* self)
{
    self->become(	
    [=](const string& what)
    {
        LOG_DEBUG("got a string msg: %s\n", what.c_str())
    },
    [=](const int& what)
    {
	    LOG_DEBUG("got integer msg: %d\n", what)
    });
}
auto a = spawn(actorx);
anon_send(a, "string"); /* 向actor发送一个字符串. */
anon_send(a, 0x10); /* 向actor发送一个整数. */
需要说明的是, 上面的例子中actorx函数是立即返回的, 也就是说里面的become也是立即返回的,  好像把两个消息处理回调放在actorx函数内部.

当有消息到来时, 经模式匹配后就会调用恰当的lambda表达式.  不用再到处找回调了.


3. 消息发送.

消息发送可以分为以下几种:

a). 发完就忘, 就像上面anon_send.

b). 同步发送, 等待响应. 等待是异步的, 相当于只是期待一个响应.

c). 同步发送, 等待响应, 超时后收到一个系统消息.

d). 同步发送, 同步等待. 适用阻塞的actor api.

e). 消息延迟发送, 这一点比akka做得漂亮很多.

 f). 消息前转, forward.

g). 消息优先级选择.


4. 消息接收.

主要有两种特性:

a). 等待超时, 超时后收到一个系统消息.

b). 消息跳过, skip.


5. 行为(behavior)

如果actor的消息流程是一个有限状态机, 那行为就是用来控制流程的标志. behavior是一个栈, 通过keep_behavior压栈, unbecome恢复.


6.  链接(link)

两个(或多个)actor可以相互link在一起, 生死相关. 一起活着或者默认一起死去. 

当其中一个actor异常退出时, 另一个(可能是多个)会收到一个"exit_msg"消息, 如果不捕获这个消息. 默认的行为就是当前actor也退出.

如果选择捕获, 那就自己定义行为.


7. 监视(monitor)

一个actor可选择监视另一个或另几个actor. 甚至可以同时监视同一个actor多次. 当被监视的actor退出时, 监视者就会收到一个"down_msg". 

监视者仅仅是收到这个消息而已. 不会有其它对自己的响应. 需自己定义行为. 


8. 在网络上发布一个actor.

这个功能貌似还非常骨感, 其做法是调用pubish函数将一个actor绑定在某个本地端口上, 作为服务器向外提供服务. 如下面的端口8080, 端口

后面还有一个默认的字符串参数, 允许指定本地服务ip.

auto a = spawn(actorx);
publish(a, 8080);
//
actor r = remote_actor("127.0.0.1", 8080);
anon_send(r, "information");
上面的remote_actor则用于连上publish的actor, 这样分布在不同机器上的actor就可以互相通信了. 这个功能似乎仅限于此了. 从实际的代码运

行来看.  作为服务器的actor只能收到客户端发送的业务消息,  包括连接到来, 断开等事件都无消息通知. 并且双方之间的通信似乎还遵循某种协

议(自己写一个socket, 向服务器发送消息时, 它无动于衷). 


9. 代理(broker)
broker的功能要比publish更强.  有点类似于我的前一篇博客中介绍的akka.io. 

比akka有一点好的地方在是, broker提供了有限的手动控制消息缓冲区的api.  

相信过不了多久. 用broker作服务器就会成为不错的选择.


10.  组通信.

组可以分为匿名组, 本地组和远程组.  前两个用于进程内通信, 远程组则可能适合一些分布式的应用场景. 一个actor可以加入或选择离开组. 


三. 编译.


项目地址是: https://github.com/actor-framework/actor-framework

签出: git clone https://github.com/actor-framework/actor-framework.git 

编译使用的是cmake, 过程很简单, 没什么可说的.  编译完之后, 会生成两个库, libcaf_core.so和libcaf_io.so. 如果你不打算使用网络相关的功

能, 只要链接上libcaf_core就可以了.


四.  文档


我翻译了一个libcaf的手册, 上传到百度文库了. 草稿, 无任何保证质量. 如下:

http://wenku.baidu.com/view/7e2b6be16529647d2728528e.html

原文地址: http://www.actor-framework.org/manual/




 类似资料: