تيك تاك تو ، الجزء 6: قارورة والكرفس / RabbitMQ

تيك تاك تو: دورة المحتوى

دعنا نحاول توصيل Celery / RabbitMQ بمشروعنا. كأساس ، خذ مشروعًا مع Flask . سوف الكرفس حساب عدد عشوائي.


تركيب المشروع

نحن استنساخ المشروع على جهاز الكمبيوتر الخاص بك:


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

حاويات الاطلاق:


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

نحن نبني تطبيق الويب:


 cd front npm install npm run-script build 

افتح المتصفح على http: // localhost .


حاويات قفص الاتهام

ظلت خدمة nginx بدون تغيير. في خدمة القارورة ، أضافوا تثبيت حزمة Celery إلى ملف requirements.txt وحملوا المجلد مع مصدر مشروع Celery:


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

تم إضافة خدمات جديدة للكرفس والأرانب .


  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 

خدمة الكرفس

تعتمد خدمة الكرفس على هذا البرنامج التعليمي . بالنسبة لأولئك الذين ليسوا على دراية بكرفس ، فمن المنطقي الاطلاع على هذا البرنامج التعليمي هنا:


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

كما ترون ، تم تصميم مشروعنا في كيليري كحزمة بروج . في مهام الكرفس ، تتم إضافة مهمة getnumber الخاصة بنا إلى ملف task.py :


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

خدمة القارورة

اسمحوا لي أن أذكرك بأننا أضفنا حزمة Celery إلى هذه الخدمة وقمنا بتحميل المجلد مع مشروع proj . شفرة المصدر لهذا المشروع موجودة الآن في خدمتين ، قارورة والكرفس .


 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) 

في معالج الأرقام ، نسمي مهمة getnumber ، التي تعمل في عامل الكرفس ، وتُرجع معرف المهمة. في معالج النتائج ، نحصل على نتيجة المهمة المكتملة بواسطة المعرف ونعيد الاستجابة بتنسيق JSON للجهة الأمامية.


الواجهة

في مدير لعبتنا ، من خلال النقر على زر الحصول على رقم عشوائي ، نرسل أولاً طلبًا إلى الواجهة الخلفية على العنوان / الرقم ونحصل على معرف مهمة Celery منه. بعد ذلك ، في دالة getResult ، نرسل بشكل دوري طلبًا إلى الواجهة الخلفية لتلقي النتيجة على العنوان / النتيجة / <مهمة> .


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

تم تغيير مخرجات نتائج الاستعلامات إلى الواجهة الخلفية:


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

الواجب المنزلي

في الواقع ، الآن تأتي النتيجة مباشرة بعد الطلب الأول. جرب عميلنا الذكي الذي يعيش في كرفس لتقديم القليل من التفكير ، حتى لا تعطي إجابة على الفور.


من وقت لآخر ، يبدأ ظهور الخطأ من القارورة "500 (خطأ خادم داخلي)" ، وهذا يثير الاستثناء "celery.exceptions.TimeoutError: انتهت مهلة العملية." في الكرفس . خدمات إعادة التشغيل فقط يساعد. بينما لا تحفر ما الأمر ، يرجى إلقاء نظرة.


يعالج GetResult الاستجابة فقط مع حالة النجاح ؛ وفي حالات أخرى ، يتم تقديم طلب ثانٍ. يمكنك إضافة التعامل مع الاستجابة مع الفشل والمعلقة. قد يعتمد تكوين الاستجابة في معالج النتائج أيضًا على حالة المهمة.


بدلاً من وسيط الرسائل RabbitMQ ، يمكنك محاولة ربط Redis.


يمكنك محاولة تنفيذ الطلبات من التطبيق من خلال وسطاء الرسائل.


وحاول أيضًا القيام بذلك بناءً على مثال Boost.Beast.


مستودع جيثب

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

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


All Articles