Tic Tac Toe, Teil 6: Flasche und Sellerie / RabbitMQ

Tic Tac Toe: Inhaltszyklus

Versuchen wir, Sellerie / RabbitMQ mit unserem Projekt zu verbinden. Nehmen Sie als Basis ein Projekt mit Flask . Sellerie führt die Zufallszahlenberechnung durch.


Projektinstallation

Wir klonen das Projekt auf Ihren Computer:


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

Container starten:


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

Wir erstellen die Webanwendung:


 cd front npm install npm run-script build 

Öffnen Sie den Browser unter http: // localhost .


Docker-Container

Der Nginx- Service ist unverändert geblieben. Im Flask- Service haben wir die Installation des Celery-Pakets zur Datei require.txt hinzugefügt und den Ordner mit der Celery-Projektquelle bereitgestellt:


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

Neue Sellerie- und Kaninchenservices wurden hinzugefügt .


  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 

Sellerieservice

Der Sellerieservice basiert auf diesem Tutorial . Wenn Sie mit Sellerie nicht vertraut sind, ist es sinnvoll, dieses Tutorial hier durchzugehen:


 $ 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> >>> 

Wie Sie sehen, ist unser Projekt in Sellerie als Projektpaket konzipiert . In den Sellerie-Tasks wird unsere getnumber- Task zur Dateiasks.py hinzugefügt:


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

Flaschenservice

Ich möchte Sie daran erinnern, dass wir diesem Service das Selleriepaket hinzugefügt und den Ordner mit dem proj- Projekt gemountet haben . Der Quellcode für dieses Projekt ist jetzt in zwei Diensten vorhanden: Flasche und Sellerie .


 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) 

Im Nummernhandler rufen wir die getnumber- Task auf, die im Sellerie- Worker ausgeführt wird, und geben die Task- ID zurück. Im Ergebnis- Handler erhalten wir das Ergebnis der abgeschlossenen Aufgabe durch einen Bezeichner und geben die Antwort im Front-End-JSON-Format zurück.


Frontend

Im Manager unseres Spiels senden wir durch Klicken auf die Schaltfläche Zufallszahl abrufen zunächst eine Anfrage an das Backend unter der Adresse / Nummer und erhalten die ID der Sellerie-Aufgabe. Danach senden wir in der Funktion getResult regelmäßig eine Anfrage an das Backend, um das Ergebnis unter der Adresse / result / <task_id> zu empfangen.


 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); } 

Die Ausgabe der Ergebnisse von Abfragen im Backend wurde geändert:


 {#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} 

Hausaufgaben

Tatsächlich kommt das Ergebnis jetzt unmittelbar nach der ersten Anfrage. Versuchen Sie unseren intelligenten Agenten, der in Sellerie lebt, ein wenig nachdenklich zu machen, um nicht sofort eine Antwort zu geben.


Von Zeit zu Zeit kommt ein Fehler vom Kolben 'a "500 (INTERNAL SERVER ERROR)", dies löst die Ausnahme "celery.exceptions.TimeoutError: Die Operation ist abgelaufen." In Sellerie . Nur ein Neustart der Dienste hilft. Bitte werfen Sie einen Blick darauf, ohne zu graben, was los ist.


GetResult verarbeitet die Antwort nur mit dem Status SUCCESS, in anderen Fällen wird eine zweite Anforderung gestellt. Sie können die Antwortbehandlung mit FAILURE und PENDING hinzufügen. Die Bildung der Antwort im Ergebnishandler kann auch vom Status der Aufgabe abhängen.


Anstelle des RabbitMQ-Nachrichtenbrokers können Sie versuchen, Redis zu verbinden.


Sie können versuchen, Anforderungen aus der Anwendung über Nachrichtenbroker auszuführen.


Und versuchen Sie es auch anhand des Boost.Beast-Beispiels.


GitHub-Repository

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

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


All Articles