我正在开发一个python脚本,它监视一个目录(使用libinotify)以查找新文件,并对每个新文件进行一些处理,然后将其复制到存储服务器。我们使用的是NFS挂载,但是有一些性能问题,现在我们正在用FTP进行测试。看起来FTP使用的资源比nfs少得多(负载总是低于2,而nfs的负载高于5)。在
我们现在遇到的问题是在TIME_WAIT状态下保持打开状态的连接数量。在时间等待中,存储的峰值约为15k个连接。在
我想知道有没有什么方法可以重复使用以前的连接进行新的传输。在
有人知道有没有办法做到这一点?在
谢谢
Tags:
是的,您可以使用
ftplib
重用连接。你所要做的就是不要关闭它们,继续使用它们。在例如,假设您有一个模块
filegenerator
,它的generate()
方法注册到inotify
,将通知排队,yield
一个接一个:我有点困惑:
听起来你的问题不是为每个文件创建一个新的连接,而是你从来没有关闭旧的连接。在这种情况下,解决办法很简单:只需关闭它们。在
要么是这样,要么你试着同时做这些事情,但没有意识到你在做什么。在
如果您希望一些并行,但不是无限的,您可以很容易地,例如创建一个由4个线程组成的池,每个线程都有一个打开的
ftplib
连接,每个线程从一个队列读取数据,然后是一个刚刚推到该队列上的inotify
线程。在这是一个新的答案,基于对前一个的评论。在
我们将使用一个TCP套接字,通过交替发送名称和内容来发送每个文件,如netstrings,每个文件都在一个大流中。在
我假设Python2.6,两边的文件系统使用相同的编码,并且您不需要很多并发客户机(但是您可能偶尔需要两个,例如,真实的客户机和一个测试人员)。我再次假设您有一个模块
filegenerator
,它的generate()
方法注册到inotify
,将通知排队,yield
一个接一个。在在客户端.py公司名称:
在服务器.py公司名称:
^{pr2}$如果在Windows上需要200多个客户机,在linux和BSD(包括Mac)上需要100多个客户机,在不太好的平台上需要十几个客户机,那么您可能希望使用事件循环设计而不是线程设计,在linux上使用
epoll
,在BSD上使用kqueue
,在Windows上使用IO完成端口。这是一个痛苦的过程,但幸运的是,有一些框架可以为您概括一切。两个流行的(也是非常不同的)选择是Twisted和{a3}。在尤其是
gevent
的一个优点是,您现在可以编写线程化代码,通过一些简单的更改,您可以将它变成像魔术一样基于事件的代码。在另一方面,如果您最终想要基于事件的代码,那么最好从一开始就学习和使用一个框架,这样您就不必处理}的所有繁琐工作,直到您得到完整的消息并干净地关闭等等,只需编写您关心的部分。毕竟,上面一半以上的代码基本上都是每个服务器共享的东西的样板,所以如果你不必编写它,何必费心呢?在
accept
循环和{你在评论中说:
请注意,我以二进制模式(},这会改变一些代码。)
'rb'
和'wb'
)打开了每个文件,并有意选择了一个协议(netstring),该协议可以处理二进制字符串,而不必尝试将它们解释为字符,也不必将嵌入的NUL字符视为EOF或类似的东西。而且,当我使用str.format
时,在python2.x中,它不会进行任何隐式编码,除非您给它提供unicode
字符串或提供基于区域设置的格式类型,而这两种我都没有做。(请注意,在3.x中,您需要使用bytes
而不是{换句话说,客户机和服务器的编码不会进入它;您执行的二进制传输与FTP的I模式完全相同。在
但是,如果您想要相反的情况,为目标系统自动传输文本和重新编码呢?有三种简单的方法:
使用第三个选项,假设文件将使用默认的文件系统编码,更改后的客户端代码是:
在服务器上:
默认情况下,
io.open
函数还使用通用换行符,因此客户机将把任何内容转换为Unix风格的换行符,而服务器将转换为它自己的本机换行符类型。在注意,FTP的T模式实际上并不进行任何重新编码;它只进行换行转换(以及它的一个更有限的版本)。在
相关问题 更多 >
编程相关推荐