技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 系统架构 --> 回调还是消息队列

回调还是消息队列

浏览:2631次  出处信息

   前几天在做 Hive 的 socket  库的时候, 遇到一个问题很典型,我记得不是第一次遇到了。值得记录一下。

   socket 底层有一个 poll 的 api ,通过 epoll 或  kqueue 或 select 取得一系列的事件。用 lua 怎么封装它呢?

   一个比较直接的想法是注入一个 callback function ,对于每个事件回调一个 lua 函数。但这容易引起许多复杂的问题。因为回调函数很不可控,内部可能抛出异常,也可能引起函数重入,或是做了一些你不喜欢去做的事情。

   如果面面俱到,就会让原本 C/Lua 边界的性能问题更加恶化。

   所以,我采用了方案二:把所有事件以及相关数据全部返回,让后续的 Lua 代码去处理 C 层获取的所有事件。

   这个方案也容易造成性能问题,那就是临时构件复杂数据结构,对 Lua VM 的 GC 造成的压力。

   为了优化这点,我主张从外部传入一个接收结构的 table ,也就是一个空的消息队列。

   然后在 C  层使用 rawseti 把消息加进去。rawseti 是一个相当高效的 lua api 。因为 lua table 如果只有顺序的整数做 key 的话,性能和 C 数组无异。

   因为每条消息上有不只一个数据,所以最终的数据结构是一个二维数组。为了不每次临时创建大量的 table ,可以缓存用过的 table 到另一个 table 中。

   比如,上次收到 4 条消息,这次收到 5 条的话,就新创建一个 table 保存第  5 条消息关联的参数。下次又收到三条消息的话,就把过剩的两个 table 转移到 cache 中备用。当系统稳定运行后,相当于创建好了整个二维数组接收 C 层产生的数据,而不会临时构建 lua 表了。


   再说一个不那么相关的话题:Lua 下实现一个简单的消息队列,我觉得如下简单的几条代码就可以了。

local q1 = {}
local q2 = {}

-- 产生消息只需要
table.insert(q1, msg)

-- 分发消息需要两层循环, 可以处理 dispatch 过程中产生的新消息
while q1[1] do
  q1,q2 = q2,q1
  for i=1,#q2 do
    dispatch(q2[i])
    q2[i] = nil
  end
end

建议继续学习:

  1. Redis消息队列的若干实现方式    (阅读:10574)
  2. 各消息队列软件产品大比拼    (阅读:5037)
  3. 使用django+celery+RabbitMQ实现异步执行    (阅读:4898)
  4. 终于把搜索更新改成基于MQ(Message Queue, 消息队列)的方式了    (阅读:3264)
  5. 在回调和闭包中的内存泄漏    (阅读:2907)
  6. State Threads 回调终结者    (阅读:1583)
  7. HQueue:基于HBase的消息队列    (阅读:1455)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1