Zum Hauptinhalt springen

Integration von A-Parser mit Redis: Fortgeschrittene API

Vergleich mit HTTP API

A-Parser Redis API wurde entwickelt, um die Methoden oneRequest und bulkRequest durch eine performantere Implementierung zu ersetzen und zusätzliche Einsatzszenarien zu unterstützen:

  • Als Server für Abfragen und Ergebnisse fungiert Redis
  • Möglichkeit, Ergebnisse asynchron oder im blockierenden Modus abzurufen
  • Möglichkeit, mehrere Instanzen von A-Parser (sowohl auf demselben als auch auf verschiedenen Servern) anzubinden, um Abfragen über einen zentralen Einstiegspunkt zu verarbeiten
  • Möglichkeit, die Anzahl der Threads für die Abfrageverarbeitung festzulegen und Betriebsprotokolle einzusehen
  • Möglichkeit, Timeouts für Operationen zu konfigurieren
  • Automatisches Expire für nicht abgerufene Ergebnisse

Thema der Diskussion im Forum

Vorläufige Konfiguration

Im Gegensatz zur A-Parser HTTP API muss für die Nutzung der Redis API vorab eine Aufgabe mit dem Parser API::Server::RedisAPI::Server::Redis konfiguriert und gestartet werden:

  • Redis-Server installieren und starten (lokal oder remote)
  • Erstellen Sie ein Einstellungs-Preset für den Parser API::Server::RedisAPI::Server::Redis und geben Sie Folgendes an:
    • Redis Host - Adresse des Redis-Servers, standardmäßig 127.0.0.1
    • Redis Port - Port des Redis-Servers, standardmäßig 6379
    • Redis Queue Key - Name des Schlüssels für den Datenaustausch mit A-Parser, standardmäßig aparser_redis_api; Sie können separate Warteschlangen erstellen und diese mit verschiedenen Aufgaben oder verschiedenen Kopien von A-Parser verarbeiten
    • Result Expire(TTL) - Lebensdauer des Ergebnisses in Sekunden, dient der automatischen Kontrolle und Löschung nicht abgerufener Ergebnisse, standardmäßig 3600 Sekunden (1 Stunde)
  • Fügen Sie eine Aufgabe mit dem Parser API::Server::RedisAPI::Server::Redis hinzu
    • Als Abfragen muss {num:1:N} angegeben werden, wobei N der im Task angegebenen Thread-Anzahl entsprechen muss
    • Sie können auch die Protokollierungsoption aktivieren, sodass das Log für jede Abfrage eingesehen werden kann

Beispiel für die Aufgabenkonfiguration mit API::Server::RedisAPI::Server::Redis

Erhalt einer API-Anfrage

A-Parser zusammen mit Redis über docker-compose starten

Bei dieser Startmethode kann als Adresse des Redis-Servers (Redis Host) anstelle der IP der Servicename angegeben werden, in den folgenden Beispielen ist dies redis

Falls A-Parser zuvor nicht über docker-compose gestartet wurde

  1. Laden Sie die Distribution herunter und entpacken Sie diese (den Einmal-Link müssen Sie vorab im Mitgliederbereich abrufen, wie hier beschrieben):
curl -O https://a-parser.com/members/onetime/ce42f308eaa577b5/aparser.tar.gz
tar zxf aparser.tar.gz
rm -f aparser.tar.gz
  1. Erstellen Sie die Datei docker-compose.yml mit folgendem Inhalt:

    • Basis-Variante ohne Passwort und ohne Port-Freigabe, Redis ist nur innerhalb des Docker-Netzwerks erreichbar
    version: '3'

    services:
    a-parser:
    image: aparser/runtime:latest
    command: ./aparser
    restart: always
    volumes:
    - ./aparser:/app
    ports:
    - 9091:9091

    redis:
    image: redis:latest
    restart: always
    • Variante mit Passwort und Port-Freigabe, Redis ist von außen erreichbar, daher wird dringend empfohlen, ein Passwort zu verwenden
    version: '3'

    services:
    a-parser:
    image: aparser/runtime:latest
    command: ./aparser
    restart: always
    volumes:
    - ./aparser:/app
    ports:
    - 9091:9091

    redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass HIER_PASSWORT_FUER_REDIS
    ports:
    - 6379:6379

    Ersetzen Sie HIER_PASSWORT_FUER_REDIS durch ein Passwort Ihrer Wahl, das für die Authentifizierung bei Redis verwendet wird.

  2. Starten Sie die Container:

docker compose up -d

Falls A-Parser bereits über docker-compose gestartet wurde

  1. Bearbeiten Sie die Datei docker-compose.yml, indem Sie am Ende folgenden Inhalt hinzufügen:

    • Basis-Variante ohne Passwort und ohne Port-Freigabe, Redis ist nur innerhalb des Docker-Netzwerks erreichbar
      redis:
    image: redis:latest
    restart: always
    • Variante mit Passwort und Port-Freigabe, Redis ist von außen erreichbar, daher wird dringend empfohlen, ein Passwort zu verwenden
      redis:
    image: redis:latest
    restart: always
    command: redis-server --requirepass HIER_PASSWORT_FUER_REDIS
    ports:
    - 6379:6379

    Ersetzen Sie HIER_PASSWORT_FUER_REDIS durch ein Passwort Ihrer Wahl, das für die Authentifizierung bei Redis verwendet wird.

  2. Starten Sie die Container:

docker compose up -d
Hinweis

Wenn A-Parser bereits läuft und sich seine Konfiguration nicht geändert hat, wird er nicht neu gestartet; Docker fügt Redis einfach hinzu und startet es.

Ausführung von Abfragen

Die Funktionsweise der Redis API basiert auf Redis Lists (Listen). Operationen auf Listen ermöglichen es, eine unbegrenzte Anzahl von Abfragen in die Warteschlange zu stellen (begrenzt durch den Arbeitsspeicher) sowie Ergebnisse im blockierenden Modus mit Timeout (blpop) oder im asynchronen Modus (lpop) zu erhalten.

  • Alle Einstellungen außer useproxy, proxyChecker und proxybannedcleanup werden aus dem Preset des aufgerufenen Parsers + overrideOpts übernommen
  • Die Einstellungen useproxy, proxyChecker und proxybannedcleanup werden aus dem Preset API::Server::RedisAPI::Server::Redis + overrideOpts übernommen

Eine Abfrage wird mit dem Redis-Befehl lpush hinzugefügt. Jede Abfrage besteht aus einem Array [queryId, parser, preset, query, overrideOpts, apiOpts], das mittels JSON serialisiert wurde:

  • parser, preset, query entsprechen den Parametern der API-Abfrage oneRequest
  • queryId - wird zusammen mit der Abfrage generiert; wir empfehlen die Verwendung einer fortlaufenden Nummer aus Ihrer Datenbank oder eines guten Zufallswerts. Über diese ID kann das Ergebnis abgerufen werden.
  • overrideOpts - Überschreiben der Einstellungen für das Parser-Preset
  • apiOpts - zusätzliche Parameter für die API-Verarbeitung
Hinweis

Bei Abfragen über Redis wird der Schritt der Ergebnisformatierung übersprungen, da das gesamte Ergebnis als JSON für die weitere programmgesteuerte Verarbeitung übertragen wird.

redis-cli

Beispiel für die Ausführung von Abfragen; zum Testen kann redis-cli verwendet werden:

127.0.0.1:6379> lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru"]'
(integer) 1
127.0.0.1:6379> blpop aparser_redis_api:some_unique_id 0
1) "aparser_redis_api:some_unique_id"
2) "{\"data\":\"<!DOCTYPE html><html.....

Verschiedene Anwendungsfälle

Asynchrone Prüfung auf Vorhandensein eines Ergebnisses

lpop aparser_redis_api:some_unique_id

Gibt das Ergebnis zurück, wenn es bereits verarbeitet wurde, oder nil, wenn die Abfrage noch in Bearbeitung ist.

Blockierendes Abrufen des Ergebnisses

blpop aparser_redis_api:some_unique_id 0

Diese Abfrage wird blockiert, bis das Ergebnis vorliegt. Sie können auch ein maximales Timeout für den Erhalt des Ergebnisses angeben, nach dessen Ablauf der Befehl nil zurückgibt.

Speichern von Ergebnissen in einer zentralen Warteschlange

Standardmäßig speichert A-Parser das Ergebnis für jede Abfrage unter einem eigenen eindeutigen Schlüssel aparser_redis_api:query_id, was eine mehrthreadige Verarbeitung ermöglicht, indem Abfragen gesendet und Ergebnisse separat für jeden Thread empfangen werden.

In einigen Fällen ist es notwendig, Ergebnisse in einem einzigen Thread zu verarbeiten, sobald sie eingehen. In diesem Fall ist es bequemer, die Ergebnisse in einer zentralen Ergebniswarteschlange zu speichern (der Schlüssel muss sich vom Schlüssel für die Abfragen unterscheiden).

Dazu muss der Schlüssel output_queue in den apiOpts angegeben werden:

lpush aparser_redis_api '["some_unique_id", "Net::HTTP", "default", "https://ya.ru", {}, {"output_queue": "aparser_results"}]'

Abrufen des Ergebnisses aus der allgemeinen Warteschlange:

127.0.0.1:6379> blpop aparser_results 0
1) "aparser_results"
2) "{\"queryId\":\"some_unique_id\",\"results\":{\"data\":\"<!DOCTYPE html><html class=...

Beispiel für eine Implementierung (Fallbeispiel SpySERP)

Angenommen, wir erstellen einen SaaS-Dienst, der Domainparameter bewertet. Der Einfachheit halber prüfen wir das Registrierungsdatum der Domain.

Unser Dienst besteht aus zwei Seiten:

  • /index.php - Landingpage mit einem Eingabeformular für die Domain
  • /results.php?domain=google.com - Seite mit den Ergebnissen des Dienstes

Um die Benutzererfahrung zu verbessern, möchten wir, dass die Seiten unseres Dienstes sofort geladen werden und der Warteprozess auf Daten natürlich wirkt und ein Loader angezeigt wird.

Bei einer Anfrage an results.php führen wir zuerst eine Abfrage an die A-Parser Redis API aus und generieren eine eindeutige request_id:

​lpush aparser_redis_api '["request-1", "Net::Whois", "default", "google.com", {}, {}]'

Danach können wir die Seite für den Benutzer ausgeben und einen Loader im Datenanzeigebereich einblenden. Da keine Verzögerungen auftreten, wird die Antwortzeit des Servers nur durch die Verbindungsgeschwindigkeit zu Redis begrenzt (normalerweise innerhalb von 10 ms).

A-Parser beginnt mit der Verarbeitung der Abfrage, noch bevor der Browser des Benutzers den ersten Inhalt erhält. Sobald der Browser alle erforderlichen Ressourcen und Skripte geladen hat, können wir das Ergebnis anzeigen. Dazu senden wir eine AJAX-Anfrage zum Abrufen der Daten:

/get-results.php?request_id=request-1

Das Skript get-results.php führt eine blockierende Anfrage an Redis mit einem Timeout von 15 Sekunden aus:

blpop aparser_redis_api:request-1 15

Und gibt die Antwort zurück, sobald sie von A-Parser empfangen wurde. Wenn wir aufgrund des Timeouts ein Null-Ergebnis erhalten, können wir dem Benutzer einen Fehler beim Datenabruf anzeigen.

Indem wir die Anfrage an A-Parser bereits beim ersten Öffnen der Seite (/results.php) senden, verkürzen wir die erforderliche Wartezeit auf Daten für den Benutzer (/get-results.php) um die Zeit, die der Browser des Benutzers für das Warten auf den Inhalt, das Laden der Skripte und das Ausführen der AJAX-Anfrage benötigt.