Linux 什么是最好的,单线程或多线程服务器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5961536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 04:01:30  来源:igfitidea点击:

What is best, a Single-threaded or a multi-threaded server?

clinuxnetwork-programming

提问by Dail

I have to create a simple client<->server communication to transfer files using C language (Linux).

我必须创建一个简单的客户端<->服务器通信来使用 C 语言(Linux)传输文件。

The server accept connections on the 10000 port, I don't know if is better to create a new thread each request or create a fixed numbers of threads and use asynchronous technique.

服务器接受 10000 端口上的连接,我不知道是每个请求创建一个新线程还是创建固定数量的线程并使用异步技术更好。

CASE A:

client --> server --> (new thread) --> process the request

CASE B:

SERVER --> create thread 1 - thread 2 - thread 3

then

client1 --> server --> thread 1
client2 --> server --> thread 2
client3 --> server --> thread 3
client4 --> server --> thread 1
client5 --> server --> thread 2
client6 --> server --> thread 3

In this case thread 1 could process many client's requests

在这种情况下,线程 1 可以处理许多客户端的请求

My considerations:

我的考虑:

CASE 1:Is faster but waste a lot of memory

案例1:速度更快但浪费大量内存

CASE 2:Is slower but use a low memory

案例 2:速度较慢但使用的内存不足

Am I wrong?

我错了吗?

回答by Antony Woods

This is entirelydown to you. There is no right or wrong answer. You've identified the pros and cons of both already and you're right with both of those; 1 is faster but more intensive, 2 is slower because clients may have to wait.

完全取决于你。没有正确或错误的答案。您已经确定了两者的优缺点,并且您对两者都是正确的;1 更快但更密集,2 更慢,因为客户端可能需要等待。

回答by Tony The Lion

I would go with the pool of pre created threads and re-use them when they are done with the current request they're handling. Creating threads can be expensive, as it mostly involves calls into the kernel.

我会使用预先创建的线程池,并在它们处理完当前请求后重新使用它们。创建线程可能很昂贵,因为它主要涉及对内核的调用。

There is "threadpool" type project hereusing pthreads. Perhaps you can get some ideas from there on how to implement.

有“线程池”类型的项目在这里使用并行线程。也许你可以从那里得到一些关于如何实施的想法。

回答by Kiril Kirov

There's no right answer here. Depends on a lot of things. And you need to choose by yourself.

这里没有正确答案。取决于很多事情。而你需要自己选择。

"CASE 1: Is faster but waste a lot of memory
"CASE 2: Is slower but use a low memory"

“CASE 1:更快但浪费大量内存
”CASE 2:更慢但使用低内存“

Wrong. Depends on a lot of things. Creating threads is not that expensive (it is, but not that much), but if the threads got too many, you'll have a problem.

错误的。取决于很多事情。创建线程并没有那么昂贵(它是,但不是那么多),但是如果线程太多,您就会遇到问题。

This depends on the load very much - what is the expected load? If it is, lets say, about 1000 requests per second - you know, if you create 1000 threads each second..... this will be disaster :D

这在很大程度上取决于负载 - 预期负载是多少?如果是这样的话,每秒大约 1000 个请求 - 你知道,如果你每秒创建 1000 个线程......这将是灾难:D

Also - create as many threads, as the CPU will be able to handle, without (much) switching between them. There's a big chance (depends on your program, of course), a single-core CPU to work much, much slower with 10 threads, instead of 1(or 2). This really depends on what will these threads do, too.

此外 - 创建尽可能多的线程,因为 CPU 将能够处理,而无需(太多)在它们之间切换。有很大的机会(当然取决于您的程序),单核 CPU 在 10 个线程而不是 1 个(或 2 个)的情况下工作速度要慢得多。这实际上也取决于这些线程将做什么。

I'd choose to create a thread pool and reuse the threads.

我会选择创建一个线程池并重用线程。

回答by Klas Lindb?ck

My first choice would be to do it single-threaded using select(2). If that wasn't good enough performance-wise I'd go with a thread-pool solution. It will scale better.

我的第一选择是使用 select(2) 进行单线程。如果这在性能方面还不够好,我会使用线程池解决方案。它将更好地扩展。

There are times where creating one thread per client is perfectly ok. I've done that and it worked well for that application, with usually around 100 client up to a maximum of 1000 clients. That was 15 years ago. Today the same application can probably handle 10000 clients due to better hardware. Just be aware that one thread per client doesn't scale very well.

有时为每个客户端创建一个线程是完全可以的。我已经这样做了,它对那个应用程序运行良好,通常有大约 100 个客户端,最多 1000 个客户端。那是 15 年前。今天,由于更好的硬件,同一个应用程序可能可以处理 10000 个客户端。请注意,每个客户端的一个线程不能很好地扩展。

回答by Mihails Strasuns

If you consider checking architecture of widely used http servers ( nginx, lighttpd, apache ) you'll notice, that ones using fixed thread count ( so called "worker threads", their amount should depend on processsor count on server ) are a lotfaster then one using large thread pool. However, there are very important moments:

如果你考虑检查广泛使用的HTTP服务器(Nginx的,lighttpd的,阿帕奇),你会发现,那那些使用固定的线程数(所谓的“工作线程”,其数额应取决于processsor计数在服务器上)的架构是很多快然后一个使用大线程池。但是,也有非常重要的时刻:

  1. "Worker thread" implementation should not be as straightforward as it is tempting, or there will be no real performance gain. Each thread should implement each one pseudo concurrency using state machine, processing multiple requests at time. No blocking operations can be allowed here - for example, the time in thread that is wated to wait for I/O from hard drive to get file contents can be used to parse request for next client. That is pretty difficult code to write, though.

  2. Thread-based solution ( with re-usable thread pool, as thread creation IS heavyweight operation ) is optimal when considering performance vs coding time vs code support. If your server is not supposed to handle thousands of requests per second, you'll get ability to code in pretty natural blocking style without risking to fail in performance completely.

  3. As you can notice, "worker thread" solutions itself service only statical data, they proxy dynamic script execution to some other programs. As far as I know ( may be wrong ), that is due to complexities with non-blocking processing of request with some unknown dynamic stuff executed in their context. That should not be an issue in your case, anyway, as you speak about simple file transfer.

  1. “工作线程”的实现不应该那么简单,因为它很诱人,否则不会有真正的性能提升。每个线程应该使用状态机实现每个伪并发,一次处理多个请求。这里不允许阻塞操作——例如,线程中等待来自硬盘驱动器的 I/O 以获取文件内容的时间可用于解析下一个客户端的请求。但是,编写代码非常困难。

  2. 在考虑性能、编码时间和代码支持时,基于线程的解决方案(具有可重用的线程池,因为线程创建是重量级操作)是最佳的。如果您的服务器不应该每秒处理数千个请求,您将能够以非常自然的阻塞风格进行编码,而不会冒性能完全失败的风险。

  3. 正如您所注意到的,“工作线程”解决方案本身仅服务于静态数据,它们将动态脚本执行代理给其他一些程序。据我所知(可能是错误的),这是由于在其上下文中执行了一些未知动态内容的请求的非阻塞处理的复杂性。无论如何,当您谈到简单的文件传输时,这对您来说应该不是问题。

The reason why limited thread solution is faster on heavy-load systems - thread http://en.wikipedia.org/wiki/Context_switchis pretty costful operation, as it requires saving data from registers and loading new one, as long as some other thread-local data. If you have too many threads compared to process count ( like 1000x more ), a lot of time in your application will be wasted simply switching between threads.

有限线程解决方案在重负载系统上更快的原因 - 线程http://en.wikipedia.org/wiki/Context_switch是非常昂贵的操作,因为它需要从寄存器保存数据并加载新的数据,只要其他一些线程本地数据。如果与进程数相比,线程数过多(例如多出 1000 倍),则应用程序中的大量时间将被浪费在线程之间简单地切换上。

So, short answer to your question is: "No, it has nothing to do with memory usage, choice is all about type of data served, planned request/second count and ability to spend a lot of time on coding".

因此,对您的问题的简短回答是:“不,它与内存使用无关,选择完全与提供的数据类型、计划的请求/秒计数以及在编码上花费大量时间的能力有关”。

回答by MarkR

It reallydepends on what your server is doing.

实际上取决于您的服务器在做什么。

I would recommend that you do the simplest thing possible. This is probably a single-process model, which multiplexes all available connections using, select, poll, libevent or similar.

我建议你做最简单的事情。这可能是一个单进程模型,它使用、选择、轮询、libevent 或类似方法多路复用所有可用连接。

That is, if you're using TCP.

也就是说,如果您使用的是 TCP。

If you use UDP, it's even easier as the application can do everything with one socket, so it can (possibly) use a blocking socket.

如果您使用 UDP,它会更容易,因为应用程序可以使用一个套接字完成所有操作,因此它可以(可能)使用阻塞套接字。

回答by Miki Berkovich

I know it has been quite a while since you asked this, but here's my take on your question from a perspective of someone who already wrote a handful of servers in C.

我知道你问这个问题已经有一段时间了,但这是我从一个已经用 C 编写了一些服务器的人的角度对你的问题的看法。

If your server is your own, totally dependent, and non-dependent on others codes, I would highlyrecommend that you do it single-threadedwith non-blocking sockets and using epoll (Linux), kqueue (BSD) or WSAEventSelect (Windows).

如果你的服务器是你自己的,完全依赖和非依赖于他人的代码,我会强烈建议你这样做的单线程与非阻塞套接字和使用的epoll(Linux)的,的kqueue(BSD)或WSAEventSelect(视窗) .

This may require that you split down a code that would have been otherwise "simple" to much smaller chunks, but if scalability is what you're looking after, this will beat any thread-based / select based servers.

这可能需要您将原本“简单”的代码拆分成更小的块,但如果您正在关注可扩展性,这将击败任何基于线程/选择的服务器。

There was a great article once called "The C10K Problem" that is focused entirely around the problem of how to handle 10,000 concurrent connections. I actually learned alot myself from it, Here's the link to it: http://www.kegel.com/c10k.html.

曾经有一篇很棒的文章叫做“C10K 问题”,它完全围绕如何处理 10,000 个并发连接的问题展开。我实际上从中学到了很多,这是它的链接:http: //www.kegel.com/c10k.html

There is also another great article that focus around scalability called "Scalable Networking" that you can find here: http://bulk.fefe.de/scalable-networking.pdf.

还有另一篇关于可扩展性的精彩文章,称为“可扩展网络”,您可以在此处找到:http: //bulk.fefe.de/scalable-networking.pdf

Those two are great reads, hope that helps.

这两本很好看,希望能帮到你。