Existe uma maneira melhor de servir os resultados de um processo caro e bloqueador do Python sobre o HTTP?

StackOverflow https://stackoverflow.com/questions/1929681

  •  20-09-2019
  •  | 
  •  

Pergunta

Temos um serviço da Web que serve pequenos segmentos arbitrários de um inventário fixo de arquivos MP3 maiores. Os arquivos MP3 são gerados on-the-fly por um aplicativo Python. O modelo é, faça uma solicitação de obter um URL especificando quais segmentos você deseja, obtenha um audio/mpeg fluxo em resposta. Este é um processo caro.

Estamos usando o nginx como o manipulador de solicitação front-end. O NGINX cuida das respostas de cache para solicitações comuns.

Inicialmente, tentamos usar o tornado no back-end para lidar com solicitações do NGINX. Como seria de esperar, a operação de MP3 bloqueador impediu o tornado de fazer suas coisas (E/S assíncrona). Então, fomos multithread, que resolveu o problema de bloqueio e teve um desempenho muito bem. No entanto, introduziu uma condição de raça sutil (sob carga do mundo real) que ainda não conseguimos diagnosticar ou reproduzir. A condição da corrida corrompe nossa saída MP3.

Por isso, decidimos definir nosso aplicativo como um manipulador WSGI simples atrás do apache/ mod_wsgi (ainda com nginx na frente). Isso elimina o problema de bloqueio e a condição de corrida, mas cria uma carga em cascata (ou seja, o Apache cria muitos processos) no servidor em condições do mundo real. Estamos trabalhando para ajustar o Apache/Mod_wsgi no momento, mas ainda em uma fase de tentativa e erro. (Atualização: voltamos para o tornado. Veja abaixo.)

Finalmente, a pergunta: estamos perdendo alguma coisa? Existe uma maneira melhor de atender aos recursos caros da CPU sobre o HTTP?

Atualizar: Graças ao artigo informado de Graham, tenho certeza de que este é um problema de ajuste do Apache. Enquanto isso, voltamos a usar tornado e estamos tentando resolver o problema de corrupção de dados.

Para aqueles que foram tão rápidos em jogar mais ferro no problema, o tornado e um pouco de threading múltiplo (apesar do problema de integridade dos dados introduzidos pelo encadeamento) lida com a carga aceitavelmente em uma pequena instância do Amazon EC2 (núcleo único).

Foi útil?

Solução

Você está cometendo o erro de usar o modo incorporado de apache/mod_wsgi? Ler:

http://blog.dscpl.com.au/2009/03/load-spikes-and-excessive-memory-usage.html

Certifique -se de usar o Modo Daemon se estiver usando Apache/Mod_WSGI.

Outras dicas

Você tentou Desova? É um servidor WSGI com uma variedade flexível de modos de rosqueamento.

Você pode considerar um sistema de filas com métodos de notificação AJAX.

Sempre que houver uma solicitação para seu recurso caro e esse recurso precisa ser gerado, adicione essa solicitação à fila (se ainda não estiver lá). Essa operação de filas deve retornar um ID de um objeto que você pode consultar para obter seu status.

Em seguida, você deve escrever um serviço de fundo que gire os threads de trabalhadores. Esses trabalhadores simplesmente desencadeiam a solicitação, geram os dados e salvam a localização dos dados no objeto de solicitação.

A página da web pode fazer as chamadas do AJAX para o seu servidor para descobrir o progresso da geração e fornecer um link para o arquivo assim que estiver disponível.

É assim que os grandes sites de mídia funcionam - aqueles que precisam lidar com o vídeo em particular. No entanto, pode ser um exagero para o seu trabalho de MP3.

alternativamente, veja a execução de algumas máquinas para distribuir a carga. Seus threads no Apache ainda serão bloqueados, mas pelo menos você não consumirá recursos no servidor da Web.

Defina "carga em cascata", pois não tem significado comum.

Seu problema mais provável será se você estiver executando muitos processos Apache.

Para uma carga como essa, verifique se você está usando o MPM Pre -Fork e verifique se está se limitando a um número apropriado de processos (nada menos que um por CPU, não mais que dois).

Parece que você está fazendo as coisas certas - apenas sem energia da CPU: você pode determinar o que é o carregamento da CPU no processo de geração desses MP3?

Eu acho que a próxima coisa que você precisa fazer é adicionar mais hardware para renderizar os MP3 em outras máquinas. Ou isso ou encontre uma maneira de entregar MP3 pré-renderizado (talvez você possa cahce algumas das suas mídias?)

BTW, a escala para a web foi o tema de uma palestra de Jacob Kaplan-Moss no Pycon Brasil este ano, e está longe de ser um problema fechado. A pilha de tecnologias necessárias é bastante impressionante - (não consegui encontrar uma cópia on -line da apresentação - - Sentria por isso)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top