cpp-httplib 使用阻塞套接字 I/O 的缺点是什么

问题描述 投票:0回答:1

我们一直在使用优秀的 cpp-httlib 来发出 REST 请求。我们现在想将它用作服务器。文档的顶部是:

重要

该库使用“阻塞”套接字 I/O。如果您正在寻找具有“非阻塞”套接字 I/O 的库,这不是您想要的。

我不确定这在实际意义上意味着什么,因为虽然我了解IP/UDP/TCP等的基本原理,但我不熟悉套接字编程。我通过向服务器发出多个请求来测试服务器,例如如果第一个请求是通过休眠30s来实现的,那么第二个“hello world”请求仍然会立即返回。

调试代码,我看到主线程正在运行:

    while (svr_sock_ != INVALID_SOCKET) {
      // socket operations 

      if (!task_queue->enqueue(
              [this, sock]() { process_and_close_socket(sock); })) {
        detail::shutdown_socket(sock);
        detail::close_socket(sock);
      }
    }

工作线程运行

      for (;;) {
        std::function<void()> fn;
        {
          // Lock / wait for new request

          fn = pool_.jobs_.front();
          pool_.jobs_.pop_front();
        }
        fn();
      }

即主线程就像 GUI 应用程序中的事件循环,接收每个传入请求,但不是执行请求本身,而是将其放入队列中以供工作线程拾取。

之前我在 Python FastAPI Web 服务器中封装了对 C++ 的调用,这很好,但是运行 Python 以及 C++ 显然会增加开销/复杂性,并且了解如何执行请求并不完全简单。全局解释器锁。使用 cpp-httlib 的直接 C++ 方法看起来好多了,但是关于“阻塞”套接字 I/O 的评论让我担心。如果不使用非阻塞套接字 I/O,我会错过什么?

(服务器将为 Windows 和 Linux 构建;但是产品将是 Linux。)

c++ multithreading sockets blocking
1个回答
0
投票

阻塞 IO 库使用线程进行抢占式多任务处理,而非阻塞 IO 库则使用协作式多任务处理,另请参阅协作式多任务处理和抢占式多任务处理有什么区别?

使用抢占式多任务处理(cpp-httplib),如果您希望一次处理 1000 个套接字,那么您将需要 1000 个活动线程,并且大部分 CPU 时间将浪费在操作系统调度上,而不是执行实际工作(上下文切换)可能需要几微秒,在云提供商使用的虚拟化操作系统上甚至可能需要更多时间。

使用协作多任务处理(asio),如果你有一个4核的服务器,你只需要4个线程来管理1000个套接字,操作系统将不必进行任何过多的调度,并且你的应用程序将处理这个额外的调度但在用户态,系统调用较少,最终速度更快。 (因为操作系统有复杂的调度程序,而用户态调度程序很简单,因此速度很快)。

如果您对每个任务进行大量计算或一次管理非常有限数量的套接字,并且您不受 IO 限制,那么使用抢占式多任务处理 (cpp-httplib) 是可以的,但如果您受 IO 限制(例如html 或文件服务器)那么您应该使用协作多任务处理(asio)。

协作多任务处理(asio)可能更难使用,但速度更快,而抢占式多任务处理(cpp-httplib)可能更慢,但更容易使用。

© www.soinside.com 2019 - 2024. All rights reserved.