Lua Web快速开发指南(10) - 利用MQ实现异步任务、订阅/发布、消息队列

本篇博客介绍了如何利用MQ库进行Lua Web开发,涵盖了MQ库的基本概念、API使用,包括MQ:new()、MQ:on()、MQ:emit()等方法,并通过实例展示了模拟生产者消费者、单播、广播和WebSocket消息推送的实现,强调了MQ在异步任务和消息队列中的应用。
摘要由CSDN通过智能技术生成

本章节我们将学习如何使用MQ库.

MQ库简介

MQ库实现了各类消息代理中间件(Message Broker)的连接协议, 目前支持:redismqttstomp协议.

MQ库基于上述协议实现了: 生产者 -> 消费者订阅 -> 发布模型, 可以在不依赖其它服务的情况下独立完成任务.

API介绍

cf框架提供了多种MQ的封装, 当我们需要使用的时候需要根据实际的协议进行选择:

-- local MQ = require "MQ.mqtt"
-- local MQ = require "MQ.redis"
-- local MQ = require "MQ.stomp"
MQ:new(opt)

此方法将会创建一个的MQ对象实例.

opt是一个table类型的参数, 可以传递如下值:

  • host - 字符串类型, 消息队列的域名或者IP地址.

  • port - int类型, 消息队列监听的端口.

  • auth/db - 字符串类型, 仅在redis协议下用作登录认证或者db选择(没有可以不填写).

  • username/password - 字符串类型, 仅在stomp/mqtt协议下用作登录认证(没有可以不填写).

  • vhost - 字符串类型, 仅在使用某些特定消息队列server的时候填写(例如:rabbit).

  • keepalive - int类型, 仅在使用mqtt的时候用来出发客户端主动发出心跳包的时间.

以redis broker为示例:

local MQ = require "MQ.redis"
local mq = MQ:new {
  host = "localhost",
  port = 6379,
  -- db = 0,
  -- auth = "123456789",
}
MQ:on(pattern, function)

此方法用来订阅一个指定pattern. 当broker将消息传递到cf后, function将会被调用.

MQ库会为function注入一个table类型的参数msg, 此参数将在断开连接的时候为nil.

msg根据采用的协议的不同msg的内容也将有所不同. 具体内容以logging库的打印为准.

标准使用示例:

local Log = require("logging"):new()
mq:on("/notice", function(msg)
  if not msg then
    return Log:ERROR("['/notice'] SUBSCRIBE ERROR: 连接已断开.")
  end
  Log:DEBUG(msg)
end)

开发者可以同时订阅多个parttern.

MQ:emit(pattern, msg)

此方法用来向指定pattern发送消息. msg为字符串类型的消息.

使用示例:

mq:emit('/notice', '{"code":200,"data":[1,2,3,4,5,6,7,8,9,10]}')

单个MQ可以一直复用emit, 内部会创建一个写入队列去完成消息的顺序发送. (在多个实例中无法保证消息先后)

MQ:start()

此方法在作为独立运行服务端时候调用.

使用示例:

mq:start()
MQ:clsoe()

此方法可以关闭不再使用的MQ; 在任何情况下MQ使用完毕后都需要调用此方法来释放资源.

使用示例:

mq:close()
开始实践

为了演示更加直观, 这里仅使用redis作为broker中专消息.

1. 模拟生产者与消费者

我们模拟100个生产者向redis的/queue投递消息, 同时定义了一个消费者订阅/queue持续进行消费

代码如下:

local cf = require "cf"
local json = require "json"
local Log = require("logging"):new()
local MQ = require "MQ.redis"

cf.fork(function ()
  local consumer = MQ:new {
    host = "localhost",
    port = 6379
  }

  local count = 0
  consumer:on("/queue", function (msg)
    if not msg then
      Log:ERROR("[/queue]连接失败", "已经消费了"..count.."个消息")
      return
    end
    count = count + 1
    Log:DEBUG("开始消费:", msg, "已经消费了"..count.."个消息")
  end)

  consumer:start() -- Websoket内部无需使用这个方法
end)

for i = 1, 100 do
  cf.fork(function()

    local producer = MQ:new {
      host = "localhost",
      port = 6379
    }

    producer:emit("/queue", json.encode({
      code = 200,
      data = {
        id = math.random(1, 1 << 32)
      },
    }))

    producer:close()
  end)
end

输出如下:

[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":3912595079}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了1个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":2938696189}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了2个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":3499397173}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了3个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":1711272453}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了4个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":3968420025}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了5个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   ["pattern"]="/queue", ["payload"]="{"code":200,"data":{"id":1887895479}}", ["source"]="/queue", ["type"]="pmessage"}, 已经消费了6个消息
[2019-06-25 16:05:36,240] [@script/main.lua:19] [DEBUG] : 开始消费:, {
   [
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值