Asynchrone Verarbeitung mit LINE BOT: RQ (Redis Queue) in Python

Ich habe LINE BOT gemacht, also werde ich es vorstellen. Der Quellcode ist auf Github.

Was ich gemacht habe

Es ist ein LINE BOT, der Sie benachrichtigt, wenn die eingegebene Zeit (Sekunden) abgelaufen ist. Es ist nicht interessant, aber es war ein gutes Thema für die asynchrone Verarbeitung. Unten ist ein Screenshot von dem, was ich erstellt habe. Wenn Sie jedoch "180" eingeben, werden Sie nach 180 Sekunden benachrichtigt. Natürlich müssen während dieser 180 Sekunden andere Nachrichten verarbeitet werden.

s_timer3.PNG

Aufgrund der Spezifikationen der LINE-API läuft das Zeitlimit für Anfragen von Benutzern jedoch innerhalb von 180 Sekunden ab, sodass keine Antwort möglich ist. Es wäre schön, wenn Sie überhaupt vor dem Timeout antworten könnten, Wenn eine große Menge an Verarbeitung kommt, schwere Verarbeitung wie Bildverarbeitung, die nicht rechtzeitig durchgeführt werden kann, So etwas wie dieser Timer kann nur nach einmaliger Rückgabe der Anfrage verarbeitet werden.

Grundlegende Richtlinien

Derzeit läuft der LINE BOT-Server wie viele andere auf Heroku. Die SSL-Kommunikation ist für LINE BOT unerlässlich, daher ist es etwas mühsam, sich selbst vorzubereiten. Dies liegt daran, dass Heroku standardmäßig möglich ist. Das ist der Vorteil von PaaS.

Ich habe auf den folgenden Artikel über die Architektur von LINE BOT verwiesen.

  1. Artikel über LINE BOT 1.1. LINE BOT-Serverarchitektur, die auch dann sicher ist, wenn eine große Anzahl von Nachrichten eingeht

  2. Artikel über Heroku 2.1 Worker Dynos, Background Jobs and Queueing 2.2 Background Tasks in Python with RQ

Hintergrundarbeiter für die asynchrone Verarbeitung verwenden RQ gemäß 2.2. Sie benötigen einen Redis-Server, um RQ verwenden zu können, aber Heroku ist einfach, da Sie nur ein Add-On namens RedisToGo hinzufügen müssen.

$ heroku addons:create redistogo

Wenn Sie beim Ausführen von LINE BOT mit RQ das MessageEvent grob zeichnen, wenn eine Nachricht vom Benutzer empfangen wird, ist die Reihenfolge wie in der folgenden Abbildung dargestellt.

  1. Anforderungen (Absender-ID, Nachricht, Antworttoken) kommen vom LINE-Server zum BOT-Server
  2. Antworten Sie mit dem Antworttoken auf eine Nachricht an den LINE-API-Server (nicht erforderlich).
  3. Registrieren Sie den Job für die Nachricht in RQ (Job Queue).
  4. Geben Sie 200 an den LINE-Server zurück
  5. Entfernen Sie den Job aus der Jobwarteschlange
  6. Verarbeiten Sie den Job
  7. Benachrichtigen Sie den LINE API-Server über das Auftragsergebnis

Hier wird die an den LINE-API-Server gesendete Nachricht auf dem LINE-Bildschirm des Benutzers angezeigt. Wichtig ist, dass die Zeit von 1 bis 4 sowohl in Bezug auf LINE als auch in Bezug auf Heroku begrenzt ist. Das Antworttoken hat übrigens auch ein Ablaufdatum. Wenn Sie es verwenden, lassen Sie es uns schnell verwenden. Und sofort 200 an den LINE-Server zurückgeben. Wenn Sie die Absender-ID kennen, können Sie jederzeit 5-7 ausführen. (Es ist ein Problem, dass die Ergebnisbenachrichtigung zu spät ist.)

s_be5196d2-02cb-43d3-96f9-c5b8ca806f28.png

In diesem LINE BOT existieren die folgenden drei Prozesse. Ich konnte nicht für jede Anforderung einen Timer-Thread erstellen, daher habe ich beschlossen, den Timer mit Redis zu verwalten.

Der Timer-Worker wird in der obigen Reihenfolge nicht angezeigt. Da der RQ-Worker nur ausgeführt wird, wenn der Job registriert ist, ist das Timing des Timers unbekannt. Daher erkennt der Timer-Worker, ob der Timer die eingestellte Zeit erreicht hat, und benachrichtigt den LINE-API-Server.

Heroku-Free-Frame-Restriktionsmaßnahmen

Quellcode dieser Zeit, aber es funktioniert nicht mit Herokus freiem Frame wie er ist. Ich habe einen Webserver und zwei Hintergrundarbeiter in der Procfile angegeben. Dies liegt daran, dass Sie in der freien Stufe jeweils nur zwei Dynos festlegen können.

Procfile


web: gunicorn app:app
rq_worker: python rq_worker.py
timer_worker: python timer_worker.py
$ heroku ps:scale rq_worker=1 timer_worker=1
Scaling dynos... !
 !    Cannot run more than 2 Free size dynos.

Aus diesem Grund habe ich leider die Methode gewählt, denselben Quellcode nur in Procfile zu ändern und als zwei Apps bereitzustellen.

Procfile für LINE BOT


web: gunicorn app:app
rq_worker: python rq_worker.py

Procfile für Timer


timer_worker: python timer_worker.py

In diesem Fall müssen die beiden Apps eine Verbindung zum gleichen Redis-Server herstellen. Daher müssen Sie die von einer App erstellte RedisToGo-Add-On-Umgebungsvariable REDISTOGO_URL auf die Umgebungsvariable der anderen App setzen.

Bonus

Der LINE BOT, den ich dieses Mal erstellt habe, verarbeitet nicht viel für die Eingabe, sodass andere Fehler als Zahlen auftreten. s_timer2.PNG

Übrigens habe ich auch einen LINE BOT erstellt, der die Eingabe morphologisch analysiert und ein Durcheinander verursacht (Quellcode: github). s_kemo.PNG

Recommended Posts

Asynchrone Verarbeitung mit LINE BOT: RQ (Redis Queue) in Python
Asynchrone Verarbeitung mit Linebot in der Jobwarteschlange
Verarbeitung in Python beenden
Asynchrone Verarbeitung (Threading) in Python
Verwenden des Python-Modus in der Verarbeitung
Führen Sie den in Python (Flask) implementierten LINE Bot "ohne Verwendung von Heroku" aus.
Implementieren Sie die Ranking-Verarbeitung mit Bindungen in Python mithilfe von Redis Sorted Set
Entwicklung eines Slack Bot mit Python mit chat.postMessage
Implementierung der asynchronen Verarbeitung in Django (Sellerie, Redis)
Asynchrone Verarbeitung in Python: Asyncio-Reverse-Referenz
Dateiverarbeitung in Python
Multithread-Verarbeitung in Python
Erstellen Sie mit Selenium einen Datenerfassungsbot in Python
[Python] Verwenden der Linien-API [1. Erstellung des Beauty-Bots]
UTF8-Textverarbeitung mit Python
Fizzbuzz in Python (in einer Zeile)
Versuchen Sie LINE Notify mit Python
Stapel und Warteschlange in Python
Implementieren Sie Redis Mutex in Python
Redis Rohrauskleidung in Python
Bildverarbeitungssammlung in Python
Sellerie asynchrone Verarbeitung in Flask
Online-Übertragung mit Python
Übersetzt mit Googletrans in Python
Befehlszeilenargumentverarbeitung (Python docopt)
Segfo Python in einer Zeile
GUI-Programmierung in Python mit Appjar
[Python] Erstelle deinen eigenen LINE-Bot
Vorsichtsmaßnahmen bei der Verwendung von Pit mit Python
100 Sprachverarbeitung Knock Kapitel 1 in Python
Versuchen Sie es mit LevelDB mit Python (plyvel)
Mal sehen, wie man Eingaben in Python verwendet
Gesamtleistung in Python (mit Funktools)
Ich habe die Warteschlange in Python geschrieben
Handschriftliche Zeichenerkennung mit KNN in Python
Ich habe Line Benachrichtigung in Python versucht
Versuchen Sie es mit LeapMotion mit Python
[Einführung] Fügen Sie Zeilenumbrüche in Python 3 ein
Implementiert in 1 Minute! LINE Benachrichtigen in Python
Suche nach Tiefenpriorität mit Stack in Python
Bei Verwendung regulärer Ausdrücke in Python
Ich habe versucht, asynchrone Verarbeitung mit Asyncio
Erstellen Sie mit Django einen LINE-Bot
GUI-Erstellung in Python mit tkinter 2
Mausbedienung mit Windows-API in Python
Hinweise zur Verwendung von cChardet und python3-chardet in Python 3.3.1.
Ali-Buch in Python: Selbstimplementierung der Prioritätswarteschlange
CGI Server (1) Python Edition in einer Zeile
Versuchen Sie es mit der Wunderlist-API in Python
GUI-Erstellung in Python mit tkinter Teil 1
Periodische Ausführungsverarbeitung bei Verwendung von tkinter [Python3]
[Python] Beschleunigung der Verarbeitung mit Cache-Tools
Holen Sie sich Suica Balance in Python (mit libpafe)
Übung, dies in Python zu verwenden (schlecht)
Hash-Passwörter langsam mit bcrypt in Python
Verwenden von venv in der Windows + Docker-Umgebung [Python]
Warteschlangen- und Python-Implementierungsmodul "deque"
Gefaltetes Liniendiagramm und Skalierungslinie in Python
[FX] Hit oanda-API mit Python mit Docker
Tweet mit der Twitter-API in Python
[Python] [Windows] Serielle Kommunikation in Python über DLL