Rubyで洗流速度制限が機能しないのはなぜですか?

Rubyで洗流速度制限が機能しないのはなぜですか?

リンクがあふれ、他のトラフィックに影響を与えるのを防ぐために、実行中のRubyプロセスで使用できる帯域幅を制限したいと思います。プロセスはHTTP経由で大容量ファイルをダウンロードしています。

trickle私はこれを便利なユーザーエリア専用のオプションとして提案する多くの人を見つけました(例:https://unix.stackexchange.com/a/34123/160146)。

scp downloadでテストした結果、ダウンロード速度が制限されることを確認しました。

trickle -s -d 50 scp [email protected] localfile.dat

また、Python 2.7スクリプトをテストしてダウンロード速度が制限されていることを確認しました。

# cat test.py
import urllib

testfile = urllib.URLopener()
testfile.retrieve("http://example.com/bigfile.dat")
# trickle -s -d 50 python test.py

最後に、基本的なRubyスクリプトでテストしてみましたが、水滴は何の効果もありませんでした。このスクリプトはダウンストリーム帯域幅を最大化します。

# cat test.rb 
require 'net/http'

Net::HTTP.get_response(URI.parse("http://example.com/bigfile.dat"))
# trickle -s -d 50 ruby test.rb

Ruby 2.1、2.2、2.3でテストしましたが、動作に違いはありません。

私はTrickleのドキュメントに動的にリンクされたプログラムでのみ動作することを示していますが、私にも当てはまると確信しています。私はDebianが提供するRubyを使用しており、リンクさ/usr/binlddたライブラリを報告しています。

# ldd /usr/bin/ruby2.3 
        linux-vdso.so.1 (0x00007fffdcdc6000)
        libruby-2.3.so.2.3 => /usr/lib/x86_64-linux-gnu/libruby-2.3.so.2.3 (0x00007f277e11a000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f277defd000)
        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f277dc79000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f277da75000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f277d83e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f277d538000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f277d194000)
        /lib64/ld-linux-x86-64.so.2 (0x0000558796396000)

興味深いことに、私がcurb(libcurlバインディング)gemを使用している場合、Trickleは私のRubyプロセスの速度を制限できます。

# cat test.rb
require 'curb'
http = Curl.get("http://example.com/bigfile.dat"))
# trickle -s -d 50 ruby test.rb

Net::HTTPこれは、Rubyの基本ライブラリがトリクルと互換性のない方法でソケットを使用することを意味しますか?

アイデアが足りません。 TrickleがRubyで動作しない固定された理由はありますか?それともRubyで一緒に動作させる方法はありますか?

答え1

私はこれを発見したと思います。trickle発生するエラーと呼ばれることがあります。クリッピング特性socket()図書館から電話で。

ご存知のように、コードが上書きtrickleされました。そのタイプの接続のみを処理できるように、埋め込みファイルsocket()の再実装の上部にtrickle-overload.cチェックがあります。type == SOCK_STREAMSOCK_STREAM

このrubyコードはソケットを開くために使用されますtype = SOCK_STREAM | SOCK_CLOEXEC。これは、close-on-execフラグを設定するためのSOCK_CLOEXEC後続の呼び出しを防止するLinux拡張(2.6.27以降)です。fcntl

残念ながらSOCK_STREAMこれとは異なるSOCK_STREAM | SOCK_CLOEXECため、フィールド内で現在許可されている拡張をtrickle許可するようにコードが変更されるまで処理されません。sockettype

trickle修正されたソケットタイプ比較を使用してシステムを再コンパイルする以外に回避策がないことがわかります。

(私が提出しました。エラーレポートDebian Bugsは私が好むプラットフォームだからです。 )

関連情報