Por que não classifica a limitação com o trabalho trickle com ruby?

5

Estou tentando limitar a largura de banda disponível para um processo Ruby em execução, a fim de evitar que ele sobrecarregue nosso link e afete outros tráfegos. O processo está baixando arquivos grandes via HTTP.

Encontrei várias pessoas sugerindo trickle como uma opção conveniente somente para usuários (como link ) .

Eu testei com um download scp e confirmei que limita a taxa de download:

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

Eu também testei um script python 2.7 e confirmei que ele limita a taxa de download:

# cat test.py
import urllib

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

Finalmente, testei com um script ruby básico e o trickle não tem efeito. Os scripts maximizam minha largura de banda de downstream:

# cat test.rb 
require 'net/http'

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

Eu testei com rubi 2.1, 2.2 e 2.3 sem diferença de comportamento.

Eu noto que a documentação do gotejamento diz que ele só funciona com programas vinculados dinamicamente, mas tenho quase certeza que isso é o caso para mim. Estou usando o ruby fornecido pelo Debian em /usr/bin e ldd reports vinculados a bibliotecas:

# 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)

Curiosamente, o trickle pode limitar o limite do meu processo de ruby se eu usar a gem do meio fio (libcurl bindings):

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

Isso sugere que a biblioteca Net::HTTP padrão do ruby usa sockets de uma maneira incompatível com o trickle?

Estou sem ideias. Existe uma razão fixa pela qual o trickle não funciona com o ruby ou há algo que eu possa fazer para que eles trabalhem juntos?

    
por James Healy 08.03.2016 / 14:13

1 resposta

3

Eu acredito que eu rastreei isso. É indiscutivelmente uma falha em trickle que ocorreu como resultado de um caracteristico rastejante na chamada da biblioteca socket() .

O código trickle redefine socket() , como você sabe. Na parte superior de sua reimplementação no arquivo trickle-overload.c , há uma verificação que inclui type == SOCK_STREAM , de forma que somente as conexões do tipo SOCK_STREAM sejam elegíveis para processamento.

O código ruby abre o soquete com type = SOCK_STREAM | SOCK_CLOEXEC . O SOCK_CLOEXEC é uma extensão do Linux (desde 2.6.27) que evita o uso de uma chamada fcntl subsequente para definir o sinalizador de fechamento no exec.

Infelizmente SOCK_STREAM não é o mesmo que SOCK_STREAM | SOCK_CLOEXEC , portanto, o processamento trickle não ocorrerá até que seu código seja corrigido para permitir as extensões agora permitidas no campo socket type .

Eu não conheço outra alternativa além de recompilar trickle para o seu sistema com uma comparação de tipo de soquete modificada.

(Eu enviei um relatório de erros para o Debian Bugs, já que é o meu preferido plataforma.)

    
por 17.05.2016 / 01:22