TypeScript:使用ZeroMQ ROUTER / DEALER

时间:2018-06-21 12:54:39

标签: node.js typescript zeromq blockingqueue

我们最近已开始为其中一种应用程序使用 Typescript语言进行工作,在这种应用程序中,服务器和客户端之间应该进行队列通信。

为了实现队列通信,我们尝试将 ZeroMQ 库版本4.6.0用作npm软件包: npm install -g zeromq and npm install -g @types/zeromq

确切情况:

客户端将通过ZeroMQ向服务器发送数千条消息。反过来,服务器将根据来自客户端的每个传入消息响应一些确认消息。客户端将根据确认消息发送下一条消息。

使用的ZeroMQ模式:

ROUTER/DEALER模式(我们不能使用任何其他模式)。

客户端代码:

    import Zmq  = require('zeromq');
    let clientSocket : Zmq.Socket;
    let messageQueue = [];

    export class ZmqCommunicator
    {
        constructor(connString : string)
        {
           clientSocket = Zmq.socket('dealer');
           clientSocket.connect(connString);
           clientSocket.on('message', this.ReceiveMessage);
        }

        public ReceiveMessage = (msg)  => {
            var argl = arguments.length,
            envelopes = Array.prototype.slice.call(arguments, 0, argl - 1),
            payload = arguments[0];
            var json = JSON.parse(msg.toString('utf8'));

            if(json.type != "error" && json.type =='ack'){
                if(messageQueue.length>0){
                  this.Dispatch(messageQueue.splice(0, 1)[0]);
            }
        }

        public Dispatch(message) {
              clientSocket.send(JSON.stringify(message));
        }

        public SendMessage(msg: Message, isHandshakeMessage : boolean){
             // The if condition will be called only once for the first handshake message. For all other messages, the else condition will be called always. 
             if(isHandshakeMessage == true){
                clientSocket.send(JSON.stringify(message));
             }
             else{ 
                 messageQueue.push(msg);
            }
        }
  }

在服务器端,我们已经配置了 ROUTER套接字。 上面的代码非常简单。 SendMessage() 函数实际上是为成千上万条消息调用的,并且代码可以成功运行,但会消耗大量内存

问题:

由于 ZeroMQ 的行为是异步,因此客户端必须在有以下情况时等待回叫 ReceiveMessage() 将新消息发送到ZeroMQ ROUTER(这在方法 Dispatch 的流程中很明显)。

基于我们对TypeScript的有限知识和对ZeroMQ与TypeScript的结合使用,问题在于,因为默认线程运行打字稿代码(该脚本会创建所需的1000余条消息并发送到 SendMessage() )在发送第一条消息(本质上是握手消息)后继续执行(创建和发送更多消息),除非所有1000条以上的消息均已创建并发送到 SendMessage() (不是发送数据,但由于我们要解释路由器套接字发送的确认消息而仅对数据排队,并且仅基于我们要发送下一条消息的确认),因此呼叫不会到达< strong> ReceiveMessage() 回调方法。

这就是说,只有在创建和调用ReceiveMessage()的默认线程完成了1000条以上的消息之后,才调用 SendMessage() ,现在没有了还有其他任务可以做。

由于ZeroMQ不提供使用ROUTER/DEALER发送/接收数据的任何同步机制,因此我们必须使用 messageQueue 对象按照上述代码利用队列

此机制将在内存中加载庞大的messageQueue(带有1000多个消息),并且仅在默认线程最后到达 ReceiveMessage() 调用之后才出队。如果说我们有10000条甚至更多的消息要发送,情况只会变得更糟。

问题:

  1. 我们已经肯定了这种行为。因此,我们确信上面已经解释了理解。我们对TypeScript或ZeroMQ用法的理解是否有差距?

  2. 是否有像Typescript中的阻塞队列/大小限制数组这样的概念,它将在队列中接收有限的条目,并阻塞队列中的所有新添加内容,直到现有的添加到队列中为止(本质上适用于默认线程)暂停处理,直到调用回叫 ReceiveMessage() 时,这将使队列中的条目出队)?

  3. 是否有任何同步ZeroMQ方法(我们在C#的类似设置中使用了它,我们在ZeroMQ上合并并同步接收数据)。

  4. 在这种情况下,是否有人使用多线程?不确定Typescript是否在很大程度上支持多线程。

注意::我们在许多论坛上进行了搜索,但在任何地方都没有任何潜在客户。上面的描述可能在一个问题中有多个问题(违反stackoverflow论坛的规则);但是对我们来说,所有这些问题都与在Typescript中有效使用ZeroMQ相互关联。

期待从社区中获得一些线索。

1 个答案:

答案 0 :(得分:0)

欢迎来到ZeroMQ

如果这是您第一次阅读有关ZeroMQ的文章,请先阅读5秒钟,以了解[ ZeroMQ hierarchy in less than a five seconds ]部分中的主要概念差异。


  

1)... 我们对或者/或者TypeScript或 ZeroMQ的使用情况有什么了解?

尽管我不能担任TypeScript部分的工作,但让我提及一些细节,这可能有助于您前进。虽然ZeroMQ主要是一种无代理的异步信号发送/消息框架,但它具有多种使用方式,并且存在一些工具来强制应用程序代码与ZeroMQ Context()-instance之间的同步和异步合作。所有服务设计的基石。

本机API提供了一种方法,用于定义是否应阻止相应的调用,直到能够完成Context()实例边界上的消息处理为止,或者相反,是否应遵循调用 ZMQ_DONTWAIT ,然后将控制异步返回给调用方,而与操作(完成)的操作无关。

作为其他技巧,人们可以选择配置 ZMQ_SND_HWM + ZMQ_RCV_HWM 和其他相关的.setsockopt()选项,以满足特定的阻止/静默行为。

>
  

因为ZeroMQ 不提供任何发送/接收数据的同步机制

好吧,ZeroMQ API确实提供了对.send()/.recv()方法的同步调用的方法,在该方法中,调用者被阻止,直到任何可行的消息可以从 Context() 引擎的控制范围。

很明显,TypeScript语言绑定/包装负责将这些本机API服务公开给您。


  

3)是否有任何同步ZeroMQ方法学(我们在C#的类似设置中使用了该方法,我们在ZeroMQ上合并并同步接收数据)

是的,有几种这样的方法:
-如果未通过 ZMQ_DONTWAIT 标志指示,则本机API会阻塞,直到可以发送消息为止
-本机API提供了 Poller() 对象,如果给定 .poll() 作为{{1},则可以-1 }持续时间说明符,以等待所寻求的事件,阻塞呼叫者,直到任何此类事件出现并出现在long实例中为止。

同样,TypeScript语言绑定/包装负责将这些本机API服务公开给您。


  

... 大内存消耗...

嗯,这可能表明资源管理不善。一旦分配了ZeroMQ消息,则在适当的情况下也应成为Poller()-d。如果资源被系统性地释放并从内存中释放出来,请检查您的TypeScript代码和TypeScript语言绑定/包装器源。