Commit 2cacb563 authored by Mickael Desfrenes's avatar Mickael Desfrenes
Browse files

first commit

parents
#!/bin/sh
celery -A tasks worker --loglevel=INFO
#!/bin/sh
sanic web.app
#!/bin/sh
python3 test_post.py
# Utilisation de Celery pour Redis
But: illustrer la mise en place d'une application web récupérant du
JSON en post qui sera traité en asynchrone par Celery.
## Pré-requis
- Python > 3.7
- Un serveur Redis tournant sur la boucle locale sans authentification.
## Installation
Créer et activer le venv:
python3 -m venv venv
. ./venv/bin/activate
Installer les dépendances:
pip install -r requirements.txt
## Exécution
Lancer Celery:
./1_demarrer_celery.sh
Lancer le serveur web (Sanic):
./2_demarrer_sanic.sh
Tester l'appli:
./3_faire_un_d_envoi_de_donnee_en_post.sh
Aller ensuite voir dans la console où tourne Celery,
le log devrait afficher un hello.
## Notes pour une mise en production
- Maintenir les processus de Sanic et de Celery via systemd
- Mettre Sanic derrière Apache, NGinX ou [Caddy](https://caddyserver.com) via reverse proxy
- Adapter le nombre de workers web et le nombre de workers Celery à la charge
Voir la doc de Circe pour un exemple de config sur une appli réelle:
- https://git.unicaen.fr/fnso/i-fair-ir/circe-server
_Circe utilise Huey à la place de Celery. Le but était de simplifier
l'installation en utilisant SQLite comme broker à la place de Redis
ou RabbitMQ pour Celery, mais le principe est le même. Dans la mesure
où vous avez déjà un Redis qui tourne, préférez Celery._
\ No newline at end of file
from celery import Celery
from time import sleep
import random
import os
# Pour la config, permet de surcharger
# les variables d'environnement via un
# fichier .env dans le dossier en cours.
# Idéalement, on versionne un .env.dist
# que chaque développeur copie et
# customise en .env
from dotenv import load_dotenv
load_dotenv()
CELERY_PORT = os.getenv("CELERY_PORT") or "6379"
CELERY_HOST = os.getenv("CELERY_HOST") or "127.0.0.1"
app = Celery(
"hello",
backend=f"redis://{CELERY_HOST}:{CELERY_PORT}",
broker=f"redis://{CELERY_HOST}:{CELERY_PORT}/0",
)
# "app" fournit le décorateur "task"
# qui permet de marquer une fonction
# comme étant une tâche exécutable par
# Celery.
@app.task
def hello(name: str) -> str:
# Pour simuler une charge,
# la tâche terminera soit immédiatement
# soit en 2s, de manière aléatoire.
sleep(random.choice([0, 2]))
return f"hello {name}"
from requests import post
response = post("http://localhost:8000/post", json={"name": "Emmanuel"})
print(response.text)
import sanic
from sanic.response import text
from tasks import hello
from celery.exceptions import TimeoutError
# Le nom de l'appli est arbitraire,
# il apparait dans les logs.
app = sanic.Sanic("LeNomDeMonAppliWeb")
# Devrait être accessible à
# http://127.0.0.1:8000/
@app.get("/")
async def index(request: sanic.request):
tache = hello.delay("John doe")
# On pourrait s'arrêter là et retourner un texte,
# mais pour le besoin de la démo on va essayer de
# récupérer le résultat de la tâche en l'attendant.
# (aucun intérêt à faire ça en production, ça
# revient à rendre la tâche synchrone).
try:
# On simule un Celery occupé
# en répondant parfois en 1s et
# parfois moins vite (cf. tasks.py).
# Comme ici on a un timeout d'1s,
# on affichera un résultat ou un échec.
tache.wait(timeout=1)
return text(
"Résultat de la tâche {} produit par Celery à {}: {}".format(
tache.id, tache.date_done, tache.result
)
)
except TimeoutError:
return text(
"Celery n'a pas terminé la tâche {} assez vite :-(".format(tache.id)
)
# Un exemple de récupération de post JSON,
# devrait être accessible à
# http://127.0.0.1:8000/post
@app.post("/post")
async def postjson(request: sanic.request):
# En supposant que le JSON posté dans le
# body HTTP est de cette forme:
# {"name": "toto"}
data = request.json or {}
name = data.get("name", "John Doe")
tache = hello.delay(name)
return text("Celery traitera la tâche {} (param name: {})".format(tache.id, name))
# A ce moment, aller voir dans la console l'exécution
# de Celery, un "Hello toto" devrait apparaitre.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment