3

我使用 AsyncProgressWorker 线程制作了一个 Node 插件来处理我的套接字消息。这是我的代码:

class ProgressWorker : public AsyncProgressWorker {
 public:
  ProgressWorker(
      Callback *callback
    , Callback *progress)
    : AsyncProgressWorker(callback), progress(progress) {}
  ~ProgressWorker() {}

  void Execute (const AsyncProgressWorker::ExecutionProgress& progress) {
    char response[4096];
    int result;
    int connected = 1;
    int timeout = 0;
    int pending = 0;

    while(connected) {
        result = sctp_recvmsg(sock, (void *)&response, (size_t)sizeof(response), NULL, 0, 0, 0);
        if (result > 0 && result < 4095) {
            if (debug) {
                printf("Server replied (size %d)\n", result);
            }
            pending = 0;
            progress.Send((const char *)response, size_t(result));
            result = 0;
        }
        else {
            // Don't mind my timeout mechanism. :))
            if ((result == -1 && errno != EWOULDBLOCK) || pending) {
                if (timeout == 0) {
                    printf("Can't receive from other end. Waiting for 3 seconds. Error code: %d\n", errno);
                    pending = 1;
                }
                if (timeout >= 3000) {
                    connected = 0;
                    close(sock);
                }
                else {
                    timeout += 5;
                    usleep(5000);
                }
            }
            else {
                usleep(5000);
            }
        }
    }

  }

  void HandleProgressCallback(const char *data, size_t count) {
    HandleScope scope;

    v8::Local<v8::Value> argv[] = {
        CopyBuffer(const_cast<char*>(data), count).ToLocalChecked()
    };
    progress->Call(1, argv); // This is the callback to nodejs
  }

 private:
  Callback *progress;
};

现在我直到今晚才对此进行压力测试,然后我注意到有些消息无法返回节点。它会打印我的“服务器回复”调试日志,但不会记录我放在进度回调中的调试日志。我在这里错过了什么吗?提前致谢。

4

1 回答 1

4

AsyncProgressWorker基于 a uv_async_t,它允许任何线程唤醒主线程。但是,如文档中所述:

libuv 将合并对 uv_async_send() 的调用,也就是说,并非对它的每次调用都会产生回调的执行。例如:如果 uv_async_send() 在调用回调之前连续调用了 5 次,那么回调只会被调用一次。如果调用回调后再次调用 uv_async_send(),则会再次调用。

^^ 这就是当您的应用程序处于压力之下时,您有时可能无法收到某些事件的原因。这条线上方是问题的答案。以下是我处理您的问题的“超越”可能的解决方案:

碰巧我正在努力添加一个新的替代方案,以AsyncProgressWorker承诺交付每个事件,就像这样AsyncProgressWorker做一样,但使用队列。此功能最近被合并到NAN中。如果您想测试它,请在https://github.com/nodejs/nan尝试 git 存储库,然后将您的替换AsyncProgressWorkerAsyncProgressQueueWorker<char> 重新运行您的测试,所有事件都将被传递。

添加此新功能的拉取请求在这里:https ://github.com/nodejs/nan/pull/692 - 2017 年 10 月 6 日合并。

此新功能在NAN 2.8.0 版中发布

您可以通过更改package.json使用 nan 版本 2.8.0 或更高版本来使用这个新的类模板:

   "dependencies": {
     "nan": "^2.8.0"
   },
于 2017-09-05T11:11:47.687 回答