处理多插座连接 [英] Handle multiple socket connections

查看:122
本文介绍了处理多插座连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Python编写了一个客户端 - 服务器应用程序。这个想法是有一个主服务器和成千上万的客户端将与它连接。服务器将随机发送小文件到要处理的客户端,客户端必须每分钟做一次工作并将其状态更新到服务器。我的问题是,目前我只有一个小的老家庭服务器,所以我认为它不能处理这么多的连接。也许你可以帮助我:

I'm writing a client-server app with Python. The idea is to have a main server and thousands of clients that will connect with it. The server will send randomly small files to the clients to be processed and clients must do the work and update its status to the server every minute. My problem with this is that for the moment I only have an small and old home server so I think that it can't handle so many connections. Maybe you could help me with this:


  • 如何增加我的服务器中的连接数?

  • 如何平衡客户端的负载?

  • 如何改善通信?我的意思是,我需要一个客户端列表的服务器上的状态(也许在一个DB?),这个更新将被不时接收,所以我不需要一个永久的连接。使用UDP发送更新是个好主意吗?如果没有,我是否每次收到更新都要创建一个新的线程?

EDIT:我更新了问题,解释一个更好的问题,但主要是要清楚足够的人有相同的问题。实际上在@TimMcNamara答案有一个很好的解决方案。

I updated the question to explain a little better the problem but mainly to be clear enough for people with the same problems. There is actually a good solution in @TimMcNamara answer.

推荐答案

设置自己成功:访问模式重要



什么是可能影响如何实现网络解决方案的设计决策?您立即开始列出几个:

Setting yourself up for success: access patterns matter

What are some of design decisions that could affect how you implement a networking solution? You immediately begin to list down a few:


  • 可编程性

  • 可用内存

  • 可用处理器

  • 可用带宽

  • programmability
  • available memory
  • available processors
  • available bandwidth

。我们想要的东西,很容易编程,是相当高规格。但是,此列表失败。我们在这里做的只是看服务器。这可能是我们可以在Web应用程序中控制的,但是我们可以完全控制的分布式系统,如传感器网络呢?

This looks like a great list. We want something which is easy enough to program, and is fairly high spec. But, this list fails. What we've done here is only look at the server. That might be all we can control in a web application, but what about distributed systems that we have full control over, like sensor networks?

我们有10,000个设备想要更新他们最新的传感器读数,他们每分钟。现在,我们可以使用与所有设备保持并发连接的高端服务器。

Let's say we have 10,000 devices that want to update you with their latest sensor readings, which they take each minute. Now, we could use a high-end server that holds concurrent connections with all of the devices.

但是,即使你有一个极端高端的服务器,你可以仍然发现自己与性能麻烦。如果设备都使用相同的时钟,并且所有的尝试在分钟的顶部发送数据,那么服务器将做大量的CPU工作,每分钟1-2秒,其余的。效率非常低。

However, even if you had an extremely high-end server, you could still be finding yourself with performance troubles. If the devices all use the same clock, and all attempt to send data at the top of the minute, then the server would be doing lots of CPU work for 1-2 seconds of each minute and nothing for the rest. Extremely inefficient.

由于我们可以控制传感器,我们可以要求他们自己负载平衡。一种方法是给每个设备一个ID,然后使用模运算符只在每分钟正确的时间发送数据:

As we have control over the sensors, we could ask them to load balance themselves. One approach would be to give each device an ID, and then use the modulus operator to only send data at the right time per minute:

import time        

def main(device_id):
    data = None
    second_to_send = device_id % 60
    while 1:
        time_now = time.localtime().tm_sec
        if time_now == 0:
            data = read_sensors()
        if time_now == second_to_send and data:
            send(data)
        time.sleep(1)

这种类型的负载平衡的一个后果是,我们不再需要这么高的功率服务器。我们认为我们需要保持与每个人的连接的内存和CPU不是必需的。

One consequence of this type of load balancing is that we no longer need such a high powered server. The memory and CPU we thought we needed to maintain connections with everyone is not required.

我想说的是,你应该确保你的特定解决方案专注于整个问题。通过您提供的简短描述,似乎我们不需要在整个时间保持大量的连接。但是,假设我们需要100%的连接。我们有什么选择?

What I'm trying to say here is that you should make sure that your particular solution focuses on the whole problem. With the brief description you have provided, it doesn't seem like we need to maintain huge numbers of connections the whole time. However, let's say we do need to have 100% connectivity. What options do we have?

非阻塞I / O的效果意味着文件描述符为数据时,没有立即返回。对于网络,这可能是坏的,因为尝试从套接字读取的函数将不向调用者返回数据。因此,有时候生成一个线程,然后调用 read 可以简化很多。

The effect of non-blocking I/O means that functions that are asking a file descriptor for data when there is none return immediately. For networking, this could potentially be bad as a function attempting to read from a socket will return no data to the caller. Therefore, it can be a lot simpler sometimes to spawn a thread and then call read. That way blocking inside the thread will not affect the rest of the program.

线程的问题包括内存低效,涉及线程创建的延迟和与上下文切换相关的计算复杂性。

The problems with threads include memory inefficiency, latency involved with thread creation and computational complexity associated with context switching.

为了利用非阻塞I / O,你可以在中轮询每个相关的文件描述符,同时1: loop。这将是伟大的,除了事实,CPU将运行在100%。

To take advantage of non-blocking I/O, you could protentially poll every relevant file descriptor in a while 1: loop. That would be great, except for the fact that the CPU would run at 100%.

为了避免这种情况,已创建基于事件的库。当没有要完成的工作时,它们将以0%运行CPU,仅当要读取数据时发送。在Python世界中, Twisted 龙卷风 gevent 都是大玩家。但是,还有很多选项。具体来说,柴油看起来很有吸引力。

To avoid this, event-based libraries have been created. They will run the CPU at 0% when there is no work to be done, activating only when data is to be read to send. Within the Python world, Twisted, Tornado or gevent are big players. However, there are many options. In particular, diesel looks attractive.

以下是Tornado网页的相关摘录:

Here's the relevant extract from the Tornado web page:


因为它是非阻塞的并且使用epoll或kqueue,它可以处理数千个同时的连接,这意味着它是真正的 - 时间网络服务。

Because it is non-blocking and uses epoll or kqueue, it can handle thousands of simultaneous standing connections, which means it is ideal for real-time web services.

每个选项采用略有不同的方法。 Twisted和Tornado在他们的方法上非常相似,依赖于非阻塞操作。 Tornado专注于Web应用程序,而Twisted社区对网络更广泛感兴趣。随后有更多的工具用于非HTTP通讯。

Each of those options takes a slightly different approach. Twisted and Tornado are fairly similar in their approach, relying on non-blocking operations. Tornado is focused on web applications, whereas the Twisted community is interested in networking more broadly. There is subsequently more tooling for non-HTTP communications.

gevent不同。库修改套接字调用,以便每个连接在极其轻量级的类似线程的上下文中运行,尽管实际上这是作为程序员隐藏的。每当有阻塞调用(例如数据库查询或其他I / O)时,gevent会非常​​快速地切换上下文。

gevent is different. The library modifies the socket calls, so that each connection runs in an extremely lightweight thread-like context, although in effect this is hidden from you as a programmer. Whenever there is a blocking call, such as a database query or other I/O, gevent will switch contexts very quickly.

这些选项的结果是

您的操作系统强加了限制它将允许的连接数。如果你达到你正在谈论的数字,你可以达到这些限制。特别是,Linux在 /etc/security/limits.conf 中为每个用户维护限制。您可以通过在shell中调用 ulimit 来访问用户的限制:

Your operating system imposes limits on the number of connections that it will allow. You may hit these limits if you reach the numbers you're talking about. In particular, Linux maintains limits for each user in /etc/security/limits.conf. You can access your user's limits by calling ulimit in the shell:


$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63357
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 63357
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我在这里加入了最相关的行, $ c>打开文件。打开的外部连接被认为是打开的文件。一旦达到1024的限制,没有应用程序将能够打开另一个文件,也不会有更多的客户端能够连接到您的服务器。假设您有一个用户 httpd 作为您的网络服务器。这应该提供您可以修改以提高该限制的想法:

I have emboldened the most relevant line here, that of open files. Open external connections are considered to be open files. Once that 1024 limit is hit, no application will be able to open another file, nor will any more clients be able to connect to your server. Let's say you have a user, httpd as your web server. This should provide you with an idea of the modifications you could make to raise that limit:

httpd soft nofile 20480
httpd hard nofile 20480

对于极高的卷数,您可能会遇到系统范围的限制。您可以通过 cat / proc / sys / fs / file-max 查看它们:

For extremely high volumes, you may hit system-wide limits. You can view them through cat /proc/sys/fs/file-max:

$ cat /proc/sys/fs/file-max
801108

要修改此限制,请使用 sudo sysctl -w fs.file-max = n ,其中n是您要允许的打开文件数。修改 /etc/sysctl.conf 即可重新启动。

To modify this limit, use sudo sysctl -w fs.file-max=n, where n is the number of open files you wish to permit. Modify /etc/sysctl.conf to have this survive reboots.

这篇关于处理多插座连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆