【问题标题】:Compute data from multiple clients simultaneously同时计算来自多个客户端的数据
【发布时间】:2013-07-10 14:32:32
【问题描述】:

我正在尝试用 C 语言编写一个能够同时处理多个(超过一千个)客户端连接的服务器。每个连接都意味着完成三件事:

  1. 向服务器发送数据
  2. 服务器处理数据
  3. 服务器向客户端返回数据

我正在使用非阻塞套接字和 epoll() 来处理所有连接,但我的问题是在服务器从一个客户端接收数据并且必须调用一个花费几秒钟处理数据返回之前必须在关闭连接之前发送回客户端的结果。

我的问题是,我可以使用什么范例以便能够在一个客户端的数据“正在烹饪”时继续处理更多的连接?

我一直在研究通过每次创建线程或进程来实现它的可能性我需要调用计算函数,但我不确定这是否会考虑到可能的并发连接数量,这就是为什么我来到这里希望有人在这件事上比我更有经验的人可以阐明我的无知。


代码 sn-p:

while (1)
                {
                  ssize_t count;
                  char buf[512];
                  count = read (events[i].data.fd, buf, sizeof buf); // read the data
                  if (count == -1)
                    {
                      /* If errno == EAGAIN, that means we have read all
                         data. So go back to the main loop. */
                      if (errno != EAGAIN)
                        {
                          perror ("read");
                          done = 1;
                        }
                      /* Here is where I should call the processing function before
                         exiting the loop and closing the actual connection */

                         answer = proc_function(buf);
                         count = write (events[i].data.fd, answer, sizeof answer); // send the answer to the client
                         break;
                    }
                    ...

提前致谢。

【问题讨论】:

    标签: c linux concurrency tcp epoll


    【解决方案1】:

    多线程或多进程在某种程度上实现这一点似乎是明智的。多线程或多进程的程度是个问题。

    1) 您可以完全转储轮询系统并为每个连接使用一个线程/进程。只要该线程想要处理该连接,它就可以停止。然后,您必须决定每次创建/终止一个线程/进程(可能最简单)还是拥有一个线程/进程池(可能最快)。

    2) 您可以为网络位设置一个线程/进程,并将处理移交给另一个线程。这不太并行,但这确实意味着您至少可以在浏览工作列表时继续处理网络连接。这使您至少可以控制正在处理的处理。以这种方式确定传入连接的优先级很容易,而选项 1 可能不会。

    3)(可能的 1 和 2)您可以使用异步 I/O 来多路复用连接。你还是按照上面1和2的方式来处理。

    您还有线程与进程的问题。线程可能启动得更快,但更难确保数据完整性。流程将更具弹性,但它们之间需要更多的接口。

    您还必须决定在线程/进程之间传递数据的方式。对于选项 1,这不是问题,因为您只需将连接传递给线程。选项 2 可能(取决于您的数据是什么)更成问题。您可以使用消息队列来传递消息,但如果您有大量数据要发送共享内存更合适。共享内存对于进程的设计来说是一件痛苦的事情,但对于线程来说却很容易(因为所有线程共享相同的内存空间)。

    达到这个规模时也会出现性能问题。值得研究这些东西的性能特征。当您处理大量连接时,select 和 poll 等调用规模的差异非常显着。

    如果不知道发送和接收的数据是什么,就很难给出可靠的建议。

    顺便说一句,这不是一个新问题。几年前Dan Kegel 有一个关于它的good article。它现在已经过时了,但概述仍然很好。不过,您应该研究一下他所讨论的概念的最新技术。

    【讨论】:

    • 首先,感谢您的回答@Joe,它包含了一些有趣且有启发性的想法。关于答案:正在发送的数据是每个连接上的单个 jpeg 图像(它是二进制表示)(不超过 100kB)。我一直在寻找为每个连接创建一个线程的选项,虽然这三个选项对我来说是最吸引人的,但鉴于规模如此之大,我对它的实现表示怀疑。如果有人在类似的案例中成功使用了这种方法,那将是非常鼓舞人心的,但我没有找到。
    • 我还发现了有希望的选项 3,但我没有使用它的经验,而且我在网上找到的示例显示了非常不同的方法(协程、状态机、绿色线程等),我真的不知道我应该关注哪一个。 (p.s.:C10k 是一篇非常好的文章,但很难找到对其提出的想法的一些明确更新)
    猜你喜欢
    • 2015-10-13
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多