O que acontece se eu iniciar muitos trabalhos em segundo plano?

13

Preciso fazer algum trabalho em 700 dispositivos de rede usando um script de expectativa. Posso fazer isso sequencialmente, mas até agora o tempo de execução é de cerca de 24 horas. Isso se deve principalmente ao tempo necessário para estabelecer uma conexão e ao atraso na saída desses dispositivos (antigos). Sou capaz de estabelecer duas conexões e executá-las em paralelo muito bem, mas até onde posso empurrar isso?

Eu não imagino que eu poderia fazer todos os 700 deles ao mesmo tempo, certamente há algum limite para o não. de conexões telnet que minha VM pode gerenciar.

Se eu tentasse iniciar 700 deles em algum tipo de loop como este:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Com

  • CPU 12 CPUs x Intel (R) Xeon (R) CPU E5649 a 2,53GHz

  • Memória 47,94 GB

Minha pergunta é:

  1. Todas as 700 instâncias poderiam ser executadas simultaneamente?
  2. Até onde posso chegar até que meu servidor atinja seu limite?
  3. Quando esse limite é atingido, ele apenas espera para iniciar a próxima iteração fooou a caixa trava?

Infelizmente, estou rodando em um ambiente de produção corporativa, então não posso apenas tentar ver o que acontece.

KuboMD
fonte
3
Eu tive boa sorte parallel, usando cerca de 50 empregos simultâneos. É um ótimo meio entre o paralelismo de 1 e 700. A outra coisa legal é que é sem lotes. Uma única conexão paralisada será interrompida apenas, não nenhuma das outras. A principal desvantagem é o gerenciamento de erros. Nenhuma dessas abordagens baseadas em shell lidará normalmente com erros. Você precisará verificar manualmente o sucesso e fazer suas próprias tentativas.
Adam
1
Sua fila de tarefas pode ser 700 hoje, mas o tamanho pode ser expandido? Observe o espaço de troca aumentar - isso é uma indicação de que você atingiu o limite de memória. E cpu% não é uma boa medida (para linux / unix), é melhor considerar a carga média (comprimento da fila de execução).
ChuckCottrill
1
A maneira mais recente de interromper a produção em meu trabalho ainda meio novo foi acidentalmente executar um milhão de empregos em segundo plano, de vida curta, de uma só vez. Eles envolveram JVMs (espere, espere, abaixe os forquilhas); portanto, as consequências foram 'limitadas' a centenas de milhares de arquivos de relatórios de erros que não permitiam iniciar encadeamentos.
michaelb958 - GoFundMonica
4
Nitpick: Não analisa a lssaída
l0b0
1
@KuboMD E desde que ninguém mais queira usar seu código.
L0b0:

Respostas:

17

Todas as 700 instâncias poderiam ser executadas simultaneamente?

Isso depende do que você quer dizer com simultaneamente. Se estamos sendo exigentes, não, eles não podem, a menos que você tenha 700 threads de execução em seu sistema, que você pode utilizar (provavelmente não). Realisticamente, sim, eles provavelmente podem, desde que você tenha RAM e / ou espaço suficiente no sistema. O UNIX e seus vários filhos são extraordinariamente bons no gerenciamento de grandes níveis de simultaneidade, e é por isso que eles são tão populares no uso de HPC em larga escala.

Até onde posso chegar até que meu servidor atinja seu limite?

É impossível responder concretamente sem muito mais informações. Praticamente, você precisa ter memória suficiente para atender:

  • Todos os requisitos de memória de tempo de execução de um trabalho, vezes 700.
  • Os requisitos de memória do bash para gerenciar muitos trabalhos (o bash não é horrível sobre isso, mas o controle do trabalho não é exatamente eficiente em termos de memória).
  • Quaisquer outros requisitos de memória no sistema.

Supondo que você cumpra isso (novamente, com apenas 50 GB de RAM, você ainda precisa lidar com outros problemas:

  • Quanto tempo de CPU será desperdiçado pelo bash no controle de tarefas? Provavelmente não muito, mas com centenas de empregos, isso pode ser significativo.
  • Quanta largura de banda de rede é necessária? Apenas abrir todas essas conexões pode invadir sua rede por alguns minutos, dependendo da largura de banda e latência.
  • Muitas outras coisas em que provavelmente não pensei.

Quando esse limite for atingido, será necessário aguardar o início da próxima iteração ou a caixa falhará?

Depende do limite atingido. Se for memória, algo morrerá no sistema (mais especificamente, será morto pelo kernel na tentativa de liberar memória) ou o próprio sistema poderá travar (não é incomum configurar sistemas para travar intencionalmente quando ficar sem memória). Se for tempo de CPU, ele continuará sem problemas, será impossível fazer muito mais no sistema. Se for a rede, você poderá travar outros sistemas ou serviços.


O que você realmente precisa aqui não é executar todos os trabalhos ao mesmo tempo. Em vez disso, divida-os em lotes e execute todos os trabalhos em um lote ao mesmo tempo, deixe-os terminar e inicie o próximo lote. O GNU Parallel ( https://www.gnu.org/software/parallel/ ) pode ser usado para isso, mas é menos do que o ideal nessa escala em um ambiente de produção (se você continuar, não fique muito agressivo, como eu disse, você pode invadir a rede e afetar os sistemas que de outra forma não tocaria). Eu realmente recomendaria procurar uma ferramenta de orquestração de rede adequada como o Ansible ( https://www.ansible.com/), pois isso não apenas resolverá seus problemas de simultaneidade (o Ansible faz o lote como eu mencionei acima automaticamente), mas também oferece muitos outros recursos úteis para trabalhar (como execução idempotente de tarefas, bons relatórios de status e integração nativa com um número muito grande de outras ferramentas).

Austin Hemmelgarn
fonte
Existem maneiras de executar um número limitado de tarefas em segundo plano (usando bash, perl, python etc.), monitorar a conclusão de tarefas e executar mais tarefas à medida que as tarefas anteriores são concluídas. Uma abordagem simples seria coletar lotes de tarefas representadas por arquivos em subdiretórios e processar um lote por vez. Há outras maneiras ...
ChuckCottrill
Isso também inclui sistemas do tipo unix? E o que é "GUN paralelo"?
Biswapriyo 30/04/19
2
@ChuckCottrill Sim, existem outras maneiras de fazer isso. Porém, dada minha própria experiência em lidar com esse tipo de coisa, é quase sempre melhor obter uma ferramenta de orquestração real do que tentar lançar sua própria solução, especialmente quando você passa por algumas dezenas de sistemas em termos de escala.
precisa saber é o seguinte
3
@forest Sim, você pode usar rlimits para impedir que o sistema falhe, mas não é fácil acertá-los em um caso como esse (você precisa saber quais são os requisitos de recursos para as tarefas antes) e não protege o restante da rede de qualquer impacto que esses trabalhos possam causar (o que é um problema potencialmente muito maior do que travar o sistema local).
Austin Hemmelgarn
12

É difícil dizer especificamente quantas instâncias podem ser executadas como trabalhos em segundo plano da maneira que você descreve. Mas um servidor normal certamente pode manter 700 conexões simultâneas, desde que você o faça corretamente. Servidores da Web fazem isso o tempo todo.

Posso sugerir que você use o GNU paralelo ( https://www.gnu.org/software/parallel/ ) ou algo semelhante para fazer isso? Isso daria várias vantagens à abordagem de trabalho em segundo plano:

  • Você pode alterar facilmente o número de sessões simultâneas.
  • E aguardará até que as sessões sejam concluídas antes de iniciar novas.
  • É mais fácil abortar.

Dê uma olhada aqui para um início rápido: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source

laenkeio
fonte
1
Interessante! Vou dar uma olhada nisso. Você sabe se tentar esse tipo de operação (sem a ajuda da Parallel) correria o risco de travar o hipervisor?
KuboMD 29/04/19
2
@KuboMD se você pode derrubar o hypervisor com algo tão mundano, é um bug no hypervisor :)
hobbs
processamento como um aparte, servidores web costumam usar segmentação ou evento-based (exemplo: gunicorn.org )
ChuckCottrill
10

Usar &para processamento paralelo é bom quando você faz alguns e quando monitora o progresso. Mas se você estiver executando em um ambiente de produção corporativo, precisará de algo que lhe permita um melhor controle.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Isso será executado foopara cada arquivo em ~/sagLogs. Ele inicia um trabalho a cada 0,5 segundos, executa o maior número possível de trabalhos em paralelo, desde que 1 GB de RAM esteja livre, mas respeitará os limites do seu sistema (por exemplo, número de arquivos e processos). Normalmente, isso significa que você estará executando 250 trabalhos em paralelo se não tiver ajustado o número permitido de arquivos abertos. Se você ajustar o número de arquivos abertos, não deverá ter problemas ao executar 32000 em paralelo - desde que tenha memória suficiente.

Se um trabalho falhar (ou seja, retornar com um código de erro), ele será tentado novamente 10 vezes.

my.log dirá se um trabalho foi bem-sucedido (depois de uma nova tentativa) ou não.

Ole Tange
fonte
Isso parece muito promissor, obrigado.
KuboMD
Fiz um teste simples cat ~/sagLogs/* >> ~/woah | parallele Holy Moly que foi rápido. 1.054.552 linhas em um piscar de olhos.
KuboMD
3
O comando que você deu tem redirecionamento duplo, então eu acho que não faz o que você pretende que ele faça. O GNU Parallel possui uma sobrecarga de 10 ms por trabalho, portanto, 1 milhão de trabalhos deve levar na ordem de 3 horas.
precisa saber é o seguinte
1
Não é aplicável se tudo o que você deseja fazer é simplesmente concatenar os arquivos.
precisa
1
@KuboMD um loop ocupado trivial da CPU, como se awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' fosse usado para brincar. Ou tente fazê-lo em uma tarefa como sleep 10a de manter os ntrabalhos em andamento sem usar muito tempo da CPU. por exemplo, time parallel sleep ::: {100..1}correr dorme de 100 a 1 segundo.
Peter Cordes
1

O que acontece se eu iniciar muitos trabalhos em segundo plano?

o sistema ficará lento e sem resposta, o pior caso é tão sem resposta que seria melhor apertar o botão liga / desliga e fazer uma reinicialização forçada ... isso estaria rodando algo como raiz, onde tinha o privilégio de se livrar disso. Se o seu script bash está sendo executado com privilégios de usuário normal, então a primeira coisa que vem à mente é /etc/security/limits.confe /etc/systemd/system.confe todas as variáveis nela para [Idealmente falando] evitar que usuário (s) a partir de sobrecarregar o sistema.

  • CPU = xeon E5649, que é uma CPU de 12 núcleos ; então você tem 12 núcleos para 12 processos para executar simultaneamente, cada um utilizando um dos doze núcleos a 100%. Se você iniciar 24 processos, cada um deles funcionará com 50% de utilização em cada um dos doze núcleos, 700 processos = 1,7%, mas é um computador, desde que tudo seja concluído corretamente em uma quantidade razoável de tempo; ser eficiente nem sempre é relevante.

    1. Todas as 700 instâncias poderiam ser executadas simultaneamente? Certamente, 700 não é um número grande; meu /etc/security/limits.conf maxprocpadrão é 4.135.275, por exemplo

    2. Até onde posso chegar até que meu servidor atinja seu limite? Muito mais do que 700, tenho certeza.

    3. Limites ... o que acontecerá se o script for iniciado em uma conta de usuário [e geralmente a raiz também limits.confse aplica a todos] é que o script será encerrado depois de tentar foo &700 vezes; você esperaria ver 700 processos foo , cada um com um pid diferente, mas poderá ver apenas 456 (escolha de número aleatório) e os outros 244 nunca foram iniciados porque foram bloqueados por algum limite de segurança ou sistema.

Pergunta de milhões de dólares: quantos você deve executar simultaneamente?

estando envolvido com a rede e você disse que cada um fará uma conexão telnet, o palpite é que você terá limites de rede e sobrecarga antes de fazer os limites de CPU e RAM. Mas eu não sei o que você está fazendo especificamente, o que provavelmente acontecerá é que você pode iniciar todos os 700 de uma só vez, mas as coisas serão bloqueadas automaticamente até que os processos e as conexões de rede anteriores sejam concluídos e fechados com base em vários limites do sistema ou algo como o os primeiros 500 serão iniciados e os 200 restantes não, porque os limites do sistema ou do kernel o impedem. Mas, por mais que muitos corram de uma só vez, haverá alguma sensação adocicadalocal para fazer as coisas o mais rápido possível ... minimizando a sobrecarga e aumentando a eficiência. Sendo 12 núcleos (ou 24 se você tiver 2 cpu), comece com 12 (ou 24) de uma só vez e aumente esse número de lote simultâneo em 12 ou 24 até que você não veja a melhoria no tempo de execução.

dica: conexões max telnet do google e veja como isso se aplica ao (s) seu (s) sistema (s). Também não se esqueça dos firewalls. Também faça um cálculo rápido da memória necessária por processo x 700; verifique se <RAM disponível (cerca de 50 gb no seu caso), caso contrário, o sistema começará a usar SWAP e basicamente não responderá. Então, inicie 12, 24, N processos de cada vez e monitore a RAM livre e aumente N já tendo algum conhecimento do que está acontecendo.

Por padrão, o RHEL limita o número de conexões telnet de um único host a 10 sessões simultâneas. Este é um recurso de segurança ... definido como 10, /etc/xinetd.conf, altere o valor "per_source".

Ron
fonte