【问题标题】:Optimizing Linux Socket优化 Linux 套接字
【发布时间】:2011-10-28 10:47:14
【问题描述】:

我想问一些关于优化 linux socket 的问题。 我尝试通过使用 boost 和简单的 linux 套接字来制作多线程负载均衡器。 负载均衡器的工作方式与以下步骤一样简单:

  1. 一个请求进来,tcp监听器会接受一个socket,直接说clientSocket并创建一个新线程
  2. 线程启动时,会创建一个后端socket,直接说serverSocket给后端服务器(服务)
  3. serverSocket 建立后,我生成一个新线程来读取 serverSocket 并将数据/响应发送到 clientSocket
  4. 对于主线程,我调用了一个函数,该函数将从 clientSocket 读取并发送到 serverSocket
  5. 当这两个套接字中的一个变为无效时,worker 将关闭这两个套接字并死亡

我还使用了ting库中的Waitset,它使用了epoll,使recv方法处于阻塞模式,这样它就会等到有事件发生,然后从socket中读取数据。

问题是当我用 AB 测试负载均衡器时,-n 10000 -c 100 -k,结果非常令人失望。我只有~1600 tps。我试图记录每个请求所花费的请求时间,但结果很好。每次往返都小于 1000 微秒/1 毫秒。

但是当我记录传入的请求间隔时,下一个请求处理的时间大约是从当前收到的请求开始 > 5000 微秒/5 毫秒。也许任何人都可以在这里提出一个更好的解决方案来优化套接字操作?谢谢。

【问题讨论】:

  • 这和boost有什么关系?您的意思是提升性能吗?
  • 我使用 boost::thread 生成线程。我这里说的是如何提高linux tcp socket性能。
  • 每次收到 TCP 连接时生成一个新线程并不是一种非常有效的处理方式。您可能想查看 C10K 问题文章 (kegel.com/c10k.html) 以了解有关替代方案的想法。 (至少你可以实现一个线程池,这样在大多数情况下,一个已经运行的线程可以负责这项工作,而不是每次都产生一个新线程)
  • 我不明白你在做什么。你真的每个连接创建两个线程吗?这是荒谬的。这些事情的完成方式是在每个 CPU 上绑定一个线程来处理 epoll 事件。

标签: c++ multithreading performance sockets boost


【解决方案1】:

您使这变得过于复杂。每个连接的线程不会超出琐碎的示例,请阅读C10K problem 了解更多详细信息。

我建议阅读有关负载均衡器的 Boost.Asio 库的信息。它在 Linux 系统上使用 epoll(4) 进行异步事件多路分离,并且比每个连接一个线程的扩展性要好得多。

【讨论】:

  • 实际上,这个想法是每个线程都会专注于 1 个 TCP 连接,直到连接终止。如果我可以问,从哪个角度来看这个想法是有缺陷的?我只想创建多线程网络服务器。
  • 我想我是在阅读 C10K 问题后明白了这一点。不是用 1 个线程服务 1 个 TCP 连接,线程应该通过利用 epoll 服务 N 连接。这样,服务器就可以处理 N x T(产生的线程数)连接并提高效率,对吗?
  • @Xzorax 是正确的。虽然每个 CPU 核心应该只生成一个线程。
【解决方案2】:

嗯,问题在于您要为每个连接创建一个线程。这不会很好地扩展。那么你为什么不创建一个线程来监控传入的连接请求和使用 epoll 的 in/out/hup 事件。线程不做其他事情以使其简单高效。当数据可用时,将其传递给执行工作的线程工作者。您可以通过输入/输出队列加入事件线程和线程工作者(初始化时创建的线程池)。

好吧,如果在你有很多连接的情况下这还不够高效,你可以在多进程中平衡连接。然后模型变成你在初始化期间分叉几个子进程,并将服务器套接字传递给每个子进程。当一个连接请求进来时,每个子进程都有机会接受。真正的多进程负载均衡。

根据上述模型,一台服务器中的 20,000+ 个连接不是问题。希望对你有帮助:)

【讨论】:

  • 很抱歉我的写作风格不佳:(
猜你喜欢
  • 2011-05-31
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多