Tic Tac Toe, Parte 6: Frasco y apio / RabbitMQ

Tic Tac Toe: Ciclo de contenido

Intentemos conectar Celery / RabbitMQ a nuestro proyecto. Como base, tome un proyecto con Flask . Apio har谩 el c谩lculo de n煤meros aleatorios.


Proyecto de instalacion

Clonamos el proyecto en su computadora:


git clone https://github.com/nomhoi/tic-tac-toe-part6.git 

Lanzamiento de contenedores:


 cd tic-tac-toe-part6 docker-compose up -d 

Construimos la aplicaci贸n web:


 cd front npm install npm run-script build 

Abra el navegador en http: // localhost .


Contenedores Docker

El servicio nginx se ha mantenido sin cambios. En el servicio de matraz , agregaron la instalaci贸n del paquete Celery al archivo require.txt y montaron la carpeta con la fuente del proyecto Celery:


  volumes: - ./flask:/code - ./celery/app/proj:/code/proj 

Se han agregado nuevos servicios de apio y conejo .


  celery: container_name: celery build: context: celery/ dockerfile: Dockerfile volumes: - ./celery/app:/app depends_on: - rabbit networks: - backend rabbit: container_name: rabbit hostname: rabbit image: rabbitmq:3.7.15-alpine environment: - RABBITMQ_DEFAULT_USER=admin - RABBITMQ_DEFAULT_PASS=CT2gNABH8eJ9yVh ports: - "5672:5672" networks: - backend 

Servicio de apio

El servicio de apio se basa en este tutorial . Para aquellos que no est谩n familiarizados con el apio, tiene sentido seguir este tutorial aqu铆:


 $ docker exec -it celery python Python 3.7.3 (default, May 11 2019, 02:00:41) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from proj.tasks import add >>> add.delay(2, 2) <AsyncResult: 43662174-657f-4dd3-ab1a-22f5950c8794> >>> 

Como puede ver, nuestro proyecto en Apio est谩 dise帽ado como un paquete de proyectos. En las tareas de Celery, nuestra tarea getnumber se ha agregado al archivo task.py :


 @app.task def getnumber(): return randrange(9) 

Servicio de matraz

Perm铆tame recordarle que agregamos el paquete Celery a este servicio y montamos la carpeta con el proyecto de proyecto. El c贸digo fuente de este proyecto ahora est谩 presente en dos servicios, frasco y apio .


 from flask import Flask, jsonify from proj.tasks import getnumber from proj.celery import app as celery app = Flask(__name__) @app.route('/number') def number(): task = getnumber.delay() return task.id @app.route('/result/<task_id>') def result(task_id): task = getnumber.AsyncResult(task_id) result = task.get(timeout = 3) response = { 'state': task.state, 'number': result, } return jsonify(response) 

En el controlador de n煤meros , llamamos a la tarea getnumber , que se ejecuta en el trabajador de apio , y devuelve el identificador de la tarea. En el controlador de resultados , obtenemos el resultado de la tarea completada por identificador y devolvemos la respuesta en formato JSON de front-end.


Frontend

En el administrador de nuestro juego, al hacer clic en el bot贸n Obtener n煤mero aleatorio , primero enviamos una solicitud al backend en / number y obtenemos la ID de la tarea de Apio. Despu茅s de eso, en la funci贸n getResult , enviamos peri贸dicamente una solicitud al backend para recibir el resultado en la direcci贸n / resultado / <task_id> .


 async function getResult(task_id) { var i = 1; var timerId = setTimeout(async function go() { console.log("Result request: " + i); console.log("Task Id: " + task_id) const res = await fetch(`result/` + task_id); const response = await res.text(); if (res.ok) { let result = JSON.parse(response); console.log(result) if (result.state === 'SUCCESS') { let i = parseInt(result.number); if ($status === 1 || $history.state.squares[i]) { promise_number = result.number + ' - busy'; return; } promise_number = i; history.push(new Command($history.state, i)); return; } } if (i < 5) setTimeout(go, 500); i++; }, 500); } 

Cambi贸 la salida de los resultados de la consulta de fondo:


 {#await promise} <p>...</p> {:then taskid} <p>Task Id: {taskid}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} {#await promise_number} <p>...</p> {:then number} <p>Number: {number}</p> {:catch error} <p style="color: red">{error.message}</p> {/await} 

Tarea

De hecho, ahora el resultado llega inmediatamente despu茅s de la primera solicitud. Pruebe a nuestro agente inteligente que vive en el apio para reflexionar un poco, a fin de no dar una respuesta inmediata.


De vez en cuando comienza a producirse un error del matraz 'a "500 (ERROR DEL SERVIDOR INTERNO)", esto genera la excepci贸n "celery.exceptions.TimeoutError: La operaci贸n ha excedido el tiempo de espera". Solo reiniciar los servicios ayuda. Si bien no est谩 cavando lo que pasa, eche un vistazo.


GetResult procesa la respuesta solo con el estado de 脡XITO; en otros casos, se realiza una segunda solicitud. Puede agregar manejo de respuestas con FALLO y PENDIENTE. La formaci贸n de la respuesta en el controlador de resultados tambi茅n puede depender del estado de la tarea.


En lugar del agente de mensajes RabbitMQ, puede intentar conectar Redis.


Puede intentar ejecutar solicitudes desde la aplicaci贸n a trav茅s de corredores de mensajes.


Y tambi茅n intenta hacerlo en base al ejemplo de Boost.Beast.


Repositorio de GitHub

https://github.com/nomhoi/tic-tac-toe-part6

Source: https://habr.com/ru/post/461531/


All Articles