Dav*_*cía 5 python sockets client-server
我正在用Python编写客户端 - 服务器应用程序.我们的想法是拥有一台主服务器和数千个将与之连接的客户端.服务器将随机发送小文件到要处理的客户端,客户端必须每分钟完成工作并将其状态更新到服务器.我的问题是,目前我只有一个小而老的家庭服务器,所以我认为它无法处理这么多连接.也许你可以帮我这个:
编辑:我更新了问题,以解释问题稍微好一点,但主要是为了解决同样问题的人.在@TimMcNamara答案中实际上有一个很好的解决方案.
Tim*_*ara 14
哪些设计决策可能会影响您实施网络解决方案的方式?你马上开始列出一些:
这看起来很棒.我们想要一些容易编程的东西,而且规格相当高.但是,这个列表失败了.我们在这里做的只是看服务器.这可能是我们可以在Web应用程序中控制的全部内容,但是我们可以完全控制的分布式系统如传感器网络呢?
假设我们有10,000台设备想要用最新的传感器读数更新您,他们每分钟都会读取一次.现在,我们可以使用一个高端服务器来保存与所有设备的并发连接.
但是,即使您拥有一台极其高端的服务器,您仍然可能会遇到性能问题.如果设备都使用相同的时钟,并且所有设备都在一分钟的时间内尝试发送数据,那么服务器将在每分钟1-2秒内完成大量的CPU工作,其余部分则没有.非常低效.
由于我们可以控制传感器,我们可以要求它们自己进行负载平衡.一种方法是为每个设备提供一个ID,然后使用模数运算符仅在每分钟的正确时间发送数据:
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)
Run Code Online (Sandbox Code Playgroud)
这种负载平衡的一个后果是我们不再需要这样的高功率服务器.我们认为我们需要与每个人保持联系的内存和CPU不是必需的.
我在这里要说的是,你应该确保你的特定解决方案关注整个问题.通过您提供的简要描述,我们似乎不需要一直保持大量的连接.但是,假设我们确实需要100%连接.我们有什么选择?
非阻塞I/O的作用意味着当没有立即返回时,向文件描述符请求数据的函数.对于网络,这可能是坏的,因为尝试从套接字读取的函数将不向调用者返回任何数据.因此,有时产生一个线程然后调用可能会简单得多read
.这样阻塞线程内部不会影响程序的其余部分.
线程的问题包括内存低效,与线程创建有关的延迟以及与上下文切换相关的计算复杂性.
要利用非阻塞I/O,您可以while 1:
循环地轮询每个相关的文件描述符.这将是很好的,除了CPU将以100%运行的事实.
为避免这种情况,已创建基于事件的库.当没有工作要做时,它们将以0%运行CPU,仅在要读取数据时才激活.在Python世界中,Twisted,Tornado或gevent是大玩家.但是,有很多选择.特别是柴油看起来有吸引力.
以下是Tornado网页的相关摘录:
因为它是非阻塞的并且使用epoll或kqueue,它可以处理数千个同时站立的连接,这意味着它是实时Web服务的理想选择.
每个选项都采用略有不同的方法.Twisted和Tornado在他们的方法上非常相似,依赖于非阻塞操作.Tornado专注于Web应用程序,而Twisted社区则对更广泛的网络感兴趣.随后有更多用于非HTTP通信的工具.
gevent是不同的.该库修改了套接字调用,因此每个连接都在一个非常轻量级的类似线程的上下文中运行,尽管实际上这对于程序员来说是隐藏的.只要存在阻塞调用(例如数据库查询或其他I/O),gevent就会非常快速地切换上下文.
每个选项的结果是您可以在单个OS线程中为许多客户端提供服务.
您的操作系统对允许的连接数施加限制.如果达到您正在谈论的数字,您可能会达到这些限制.特别是,Linux维护每个用户的限制/etc/security/limits.conf
.您可以通过调用ulimit
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
我在这里鼓励了最相关的那条线open files
.打开外部连接被视为打开文件.一旦达到1024限制,没有应用程序将能够打开另一个文件,也不会有任何其他客户端能够连接到您的服务器.假设您有一个用户,httpd
作为您的Web服务器.这应该可以让您了解为提高该限制可以进行的修改:
httpd soft nofile 20480
httpd hard nofile 20480
Run Code Online (Sandbox Code Playgroud)
对于极高的数量,您可能会达到系统范围的限制.您可以通过cat /proc/sys/fs/file-max
以下方式查看
$ cat /proc/sys/fs/file-max
801108
Run Code Online (Sandbox Code Playgroud)
要修改此限制,请使用sudo sysctl -w fs.file-max=n
,其中n是您希望允许的打开文件数.修改/etc/sysctl.conf
以使其重新启动.