【问题标题】:Trickle Fails to Shape My Python Script's Upload Bandwidth涓流无法塑造我的 Python 脚本的上传带宽
【发布时间】:2014-05-16 02:10:01
【问题描述】:

我有一个非常简单的 Python 脚本——flickr.py——将文件上传到 Flickr。它看起来像这样:

#!/usr/bin/python
import sys
import os.path
import flickr_api
KEY = '<key>'
SECRET = '<secret>'
filename = sys.argv[1]
basename = os.path.basename(filename)
flickr_api.set_keys(api_key=KEY, api_secret=SECRET)
flickr_api.set_auth_handler('/home/pi/.flickr/token')
flickr_api.upload(photo_file=filename, title=basename)

效果很好。我输入flickr photo.jpg,它就在我的 Flickr 页面上。

但是,我想限制上传速度,这样我就可以在后台运行它,而不会对其他 Internet 流量造成太大影响。于是我跑了……

trickle -s -u 10 flickr photo.jpg

...而且,可悲的是,它似乎没有像我希望的那样将上传速度限制为 10kbps。我已经在另一个窗口中打开了 NetHogs 对此进行了测试。最高可达 80kbps,就像我在没有 trickle 的情况下运行它一样。

我尝试了各种方法——以超级用户身份运行它,在命令前面加上我的 Python 解释器 (trickle -s -u 10 /usr/bin/python flickr photo.jpg) 的完整路径。似乎没有任何效果。

我已经用这个盒子上的其他程序测试了trickle——wgetscp——它的工作原理完全符合预期。我错过了什么?

可能相关的说明:这是在 Raspberry Pi 上。

更新:我使用的 Flickr API 模块就是这个......

https://github.com/alexis-mignon/python-flickr-api

...但我只是用这个重写了我的示例...

http://stuvel.eu/flickrapi

...结果相同。

【问题讨论】:

  • 也许只有我一个人,但我对涓涓细流不熟悉;这是指这个应用程序吗:monkey.org/~marius/pages/?page=trickle(请注意,pypi 上有一个 python 库也称为涓流,但我认为这不是你正在使用的)
  • 是的,就是这个。不是 pypi/Tornado 涓涓细流。
  • 您是否尝试过使用普通的 python 套接字应用程序来查看它是否是闪烁应用程序所独有的,或者与 python 与涓流交互的东西有关?
  • 看起来涓涓细流依赖于库预加载来将自己插入应用程序和内核之间......也许您的应用程序正在绕过预期的套接字功能?我最好的猜测是 Flickr API 使用 SSL 并且由此产生的 OpenSSL 使用会以某种方式扰乱预加载逻辑。
  • @James_pic,此时 strace 是你的朋友。例如,请参阅here 以了解您可能正在打开哪些共享对象。您还可以使用它来比较工作案例与不工作案例的套接字调用。

标签: python raspberry-pi flickr bandwidth-throttling


【解决方案1】:

TL;DR

无法在相同的硬件上重现 OP 问题,因此我认为这是对单位的误读 (10 KB/s == 80 kbps)。一个类似但不完全相同的问题引发了对该问题的赏金,因此我为此提供了一些诊断技术。我已将回复分成几个部分:

  1. 原来的问题
  2. 诊断步骤建议
  3. 假设使用awscli 可能是什么问题

1。原始问题(非)再现

我使用 Raspbian OS(无 GUI)设置了一个 Raspberry Pi,其库与 OP 完全相同(全部使用 sudo 完成以提高速度...)

sudo pip install flickr_api
sudo apt-get install nethogs
sudo apt-get trickle

然后您必须注册一个 Flickr 帐户,创建一个(非商业)应用程序并设置 API 密钥等 - 用于 app creation here 和 api 密钥获取的说明 here 或通过 Python 包装器 @987654323 @。

我找到了一张 1.9MB 的图片,将其命名为 test.jpg 并尝试了以下操作:

  1. /usr/bin/python flickr.py test.jpg
  2. trickle -s -u 10 /usr/bin/python flickr.py photo.jpg

结果

  1. 图片在~3秒内上传,nethogs显示上传速度峰值~400KB/s
  2. 图片上传花了一分钟多的时间,nethogs 显示上传速率在13 KB/s(短暂)达到峰值,然后稳定在10.081

一切正常

因此,我认为 OP 问题就这么简单:trickle 中的上传限制设置为每秒千字节 (kB/s),我认为 OP 是可能以千每秒读取速度(kbps)。因此系数为 8。


2。但是...类似问题的诊断

@James_pic 在这个问题上发布了一个赏金,事实证明他的场景与 OP 不同。特别是,在使用 aws-cli 上传到 Amazon Web 服务时,他发现没有任何限制

既然如此,我将发布一些进一步的诊断方法。 paper describing how trickle works is here 并描述了 trickle 不起作用的几个场景:

  1. 当用户不自愿在涓流下运行时
  2. 其次,Trickle 影响较小,无法处理静态链接的二进制文件。

2 在这里可能是相关的,所以我将概述一种方法,您可能会开始使用strace 来诊断它。此站点上还有另一个问题涉及 strace usage in general 和特定用法,以查找正在使用的共享库 here

由于我没有 aws-cli 的可重现示例,我将展示我在 flickr_api 案例中验证操作所做的工作。

来自手册页,strace

拦截并记录进程调用的系统调用和进程接收到的信号。当我们正在调查正在使用哪些系统库时,我们对open 消息感兴趣,所以我使用了以下内容,实际上用strace“包装”了上面的命令,然后为open 查找输出:

  1. strace /usr/bin/python flickr.py test.jpg 2&gt;&amp;1 | grep open &gt; strace.out
  2. strace trickle -s -u 10 /usr/bin/python flickr.py test.jpg | grep open &gt; strace_with_trickle.out

最后,我运行了这两个文件的差异:

diff strace_with_trickle.out strace.out

不出所料,带有trickle 的版本多输出了几行 - 特别是这些:

< open("/lib/arm-linux-gnueabihf/libbsd.so.0", O_RDONLY) = 3
< open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY) = 3
< open("/lib/arm-linux-gnueabihf/libgcc_s.so.1", O_RDONLY) = 3
< open("/usr/lib/trickle/trickle-overload.so", O_RDONLY) = 3
< open("/etc/ld.so.preload", O_RDONLY)    = 3
< open("/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so", O_RDONLY) = 3
< open("/etc/ld.so.cache", O_RDONLY)      = 3

这些是在进程运行时覆盖trickle-overload.so 插入的行。特别是,我们可以观察到标准套接字库正在使用并在此处动态加载 - 即 libc.so.6libbsd.so.0,这让我们确信 trickle 应该可以工作。

这种技术非常通用 - 使用一个工作案例和一个非工作案例,然后 diffing 输出应该会让你走得更远。


3。终于……awscli假设

我怀疑awscli 可能会在其上传过程中产生新进程。如果是这种情况,我认为带有-s 选项的trickle 不会限制这些子进程。您可以在守护程序模式下使用它 - 这可能会更好 - 您可以通过输入 man trickled 来查看如何执行此操作

本质上 - 你首先启动守护进程,例如

trickled -u 10

然后“订阅”它的进程,例如

trickle /usr/bin/python flickr.py test.jpg

警告对于awscli 问题,我没有可重现的测试用例,所以这是推测。

【讨论】:

    【解决方案2】:

    您使用的是哪个发行版?我知道 Ubuntu(至少 18.04 和 20.04)的滴流包缺少一些上游修复,例如https://github.com/mariusae/trickle/commit/bb2825a1fe938e303acd5d65508476ca03961d85

    我建议你从源代码编译涓流并重试。

    这个提交将特别修复 python3 的问题。 Python2 显然不使用SOCK_CLOEXECSOCK_NONBLOCK,因此不受影响。

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多