Estou escrevendo um aplicativo no Flask, que funciona muito bem, exceto que WSGI
é síncrono e bloqueador. Tenho uma tarefa em particular que chama uma API de terceiros e essa tarefa pode levar vários minutos para ser concluída. Eu gostaria de fazer essa ligação (na verdade, é uma série de ligações) e deixá-la funcionar. enquanto o controle é devolvido ao Flask.
Minha visão é semelhante a:
@app.route('/render/<id>', methods=['POST'])
def render_script(id=None):
...
data = json.loads(request.data)
text_list = data.get('text_list')
final_file = audio_class.render_audio(data=text_list)
# do stuff
return Response(
mimetype='application/json',
status=200
)
Agora, o que eu quero fazer é ter a linha
final_file = audio_class.render_audio()
execute e forneça um retorno de chamada a ser executado quando o método retornar, enquanto o Flask pode continuar a processar as solicitações. Esta é a única tarefa que preciso que o Flask execute de forma assíncrona, e gostaria de alguns conselhos sobre a melhor forma de implementar isso.
Eu olhei para Twisted e Klein, mas não tenho certeza se eles são exageros, já que talvez Threading fosse suficiente. Ou talvez o aipo seja uma boa escolha para isso?
fonte
Respostas:
Eu usaria o Celery para lidar com a tarefa assíncrona para você. Você precisará instalar um corretor para servir como sua fila de tarefas (RabbitMQ e Redis são recomendados).
app.py
:Execute seu aplicativo Flask e inicie outro processo para executar seu trabalhador de aipo.
Também gostaria de referir-se a Miguel Gringberg escrever-se para um mais em guia de profundidade para usar aipo com garrafa.
fonte
O threading é outra solução possível. Embora a solução baseada em Celery seja melhor para aplicativos em escala, se você não está esperando muito tráfego no terminal em questão, o encadeamento é uma alternativa viável.
Esta solução é baseada na apresentação PyCon 2016 Flask at Scale de Miguel Grinberg , especificamente o slide 41 em seu conjunto de slides. Seu código também está disponível no github para os interessados no código-fonte original.
Da perspectiva do usuário, o código funciona da seguinte maneira:
Para converter uma chamada de API em uma tarefa em segundo plano, basta adicionar o decorador @async_api.
Aqui está um exemplo completo:
fonte
Você também pode tentar usar
multiprocessing.Process
comdaemon=True
; oprocess.start()
método não bloqueia e você pode retornar uma resposta / status imediatamente ao chamador enquanto sua função cara é executada em segundo plano.Eu experimentei um problema semelhante ao trabalhar com o framework Falcon e usar o
daemon
processo ajudou.Você precisaria fazer o seguinte:
Você deve obter uma resposta imediatamente e, após 10s, deverá ver uma mensagem impressa no console.
NOTA: Lembre-se de que os
daemonic
processos não podem gerar nenhum processo filho.fonte
/render/<id>
endpoint espera algo como resultadomy_func()
?my_func
enviar resposta / pulsação para algum outro terminal, por exemplo. Ou você pode estabelecer e compartilhar alguma fila de mensagens através da qual você pode se comunicar commy_func