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/bin있으며 ldd링크된 라이브러리를 보고하고 있습니다.

# 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는 제가 선호하는 플랫폼이기 때문입니다. )

관련 정보