我们有一个Node应用程序,Node代码的一部分作为后台作业运行。该作业使用的是BullMQ,它是用JavaScript编写的,并在后台使用Redis。
我们正在将一些Node应用程序移植到Rails。但是,我想保留后台工作,按原样写在Node中。
有可能有:
- Rails中的路由,接受请求,调度作业并将其推送到Redis队列
- 作业是否由工作人员用Node/JavaScript编写
- Rails是否监听队列(Websockets或长轮询(,并在完成后将结果发送到浏览器
换句话说,是否存在独立于语言的Redis/Queue系统?
+-------------+
| |
| |
| REDIS QUEUE |
+----------------+ |
| | |
| | +^--+
| +---------------+ |
+---------+ | ^ | |
| | +-------v--+ | | |
| browser +--------------+ +--------------------+ | |
| <--------------+ Rails | | |
+---------+ | | | |
+----------+ +---------v----+
| |
| |
| NODE worker |
| |
| |
+--------------+
与Rails相比,我更熟悉Node中的Jobs/Queue。我看到了很多选项,比如SideKick和Resque,但似乎工人大多是用Ruby编写的。
回答以下3个问题:
- 在Rails中路由,接受请求,调度作业并将其推送到Redis队列
是的,当然可以将新作业的属性推送到redis队列。您只需构建参数(可能将其序列化为JSON(,并使用Redis的rpush
将其推送到队列中(可以使用Ruby的Redis-gem(。
- 让工人用Node/Javascript编写作业
是的,Redis基本上没有任何内容表明编写器需要用与读取器相同的语言编写-如果Rails应用程序将输入序列化为JSON,Node应用程序可以弹出该JSON并对其进行处理
- 让Rails监听队列并在完成时将结果发送到浏览器
这是更棘手的部分。需要理解的关键是,请求是一个同步过程,但整个后台作业系统是异步-假设你可以告诉你的控制器sleep
并在循环中检查确认,但这效率低下有两个原因-首先,实际上没有必要在循环中查询redis以获得确认(因为redis具有"订阅"功能(,其次,如果将控制器设为sleep
,则会浪费一些内存。
更好的方法是使用websocket。要安排作业,您可以使用常规控制器或入站websocket消息处理程序-在任何一种情况下,它都会安排作业并立即响应"作业已入队"。然后,在Rails应用程序中(控制器方法之外(,您可以单独设置Redis对"作业完成"队列的订阅。当它收到一条消息时,它将找到到相关客户端的websocket连接,并发送一条出站消息,说明作业已被处理。