Docling-Parallelität
Zwei Einstellungen bestimmen, wie viele Dokumente gleichzeitig von Docling konvertiert werden: QANSWER_CELERY_DOCLING_POOL und QANSWER_CELERY_DOCLING_CONCURRENCY. Diese Seite erklärt, wie Sie sie anhand der Anzahl Ihrer Python-Backend-Replikate und Docling-Worker-Replikate wählen.
Wie ein Dokument zu Docling gelangt
Jedes indexierte PDF- oder Office-Dokument durchläuft drei Stufen:
- Jedes Python-Backend-Replikat führt einen Celery-Worker aus, der die Queue docling_extraction_queue abarbeitet. Diese beiden Einstellungen konfigurieren diesen Worker.
- Der Docling-API-Server (docling, QANSWER_DOCLING_ENDPOINT) nimmt jede Anfrage entgegen und legt sie in eine Redis-Warteschlange (RQ).
- Die Docling-Worker-Replikate (docling-worker) holen die Aufträge aus dieser Warteschlange und konvertieren sie. Jedes Replikat führt einen RQ-Worker aus, der jeweils einen Auftrag bearbeitet, und zählt daher als ein Konverter.
Eine Celery-Aufgabe ist eine blockierende HTTP-Anfrage an den API-Server für einen Stapel von Seiten. Ein Stapel umfasst 8 Seiten, sofern Sie QANSWER_INDEXING_PAGE_BATCH_SIZE nicht setzen (leer: Standardwert des Backends).
Was die Einstellungen steuern
- QANSWER_CELERY_DOCLING_POOL ist der Celery-Pool-Typ. Der Standard des Bundles ist prefork.
- QANSWER_CELERY_DOCLING_CONCURRENCY ist die Anzahl der Slots in diesem Pool. Das Bundle verwendet standardmäßig 2.
Mit prefork halten N Slots N Konvertierungen pro Backend-Replik gleichzeitig in Bearbeitung. Die Gesamtzahl der Anfragen an Docling ist daher die Zahl der Backend-Repliken mal die Parallelität.
Die Regel
Zielen Sie auf etwa zwei laufende Anfragen pro Docling-Worker: eine wird konvertiert, eine wartet, sodass ein Konverter zwischen zwei Aufträgen nie leer läuft. Bei QANSWER_SCALING_PYTHON_REPLICAS_NUMBER Backend-Replikaten und QANSWER_SCALING_DOCLING_WORKER_REPLICAS_NUMBER Docling-Workern ergibt sich:
concurrency = max(1, round(2 × docling workers ÷ backend replicas))Auf die nächste ganze Zahl runden, mindestens 1: Mit weniger Docling-Workern als Backend-Repliken bleiben Sie bei 1 pro Backend.
Gängige Konfigurationen
| Backend-Replikate | Docling-Worker | Parallelität | Laufende Anfragen | Ziel |
|---|---|---|---|---|
| 1 | 1 | 2 | 2 | 2 |
| 1 | 2 | 4 | 4 | 4 |
| 2 | 2 | 2 | 4 | 4 |
| 2 | 4 | 4 | 8 | 8 |
| 3 | 2 | 1 | 3 | 4 |
| 3 | 4 | 3 | 9 | 8 |
| 3 | 6 | 4 | 12 | 12 |
| 4 | 2 | 1 | 4 | 4 |
Die Standardwerte des Bundles (2 Backend-Replikate, 2 Docling-Worker) entsprechen der dritten Zeile.
Praxisbeispiel
Sie betreiben 3 Backend-Replikate und 4 Docling-Worker. Das Ziel sind 2 x 4 = 8 laufende Anfragen, und 8 / 3 = 2,67 ergibt gerundet eine Parallelität von 3. Tragen Sie Folgendes in .env.override ein:
QANSWER_SCALING_PYTHON_REPLICAS_NUMBER=3
QANSWER_SCALING_DOCLING_WORKER_REPLICAS_NUMBER=4
QANSWER_CELERY_DOCLING_POOL=prefork
QANSWER_CELERY_DOCLING_CONCURRENCY=3Damit sind 3 x 3 = 9 Anfragen gegen 4 Konverter in Bearbeitung: nahe am Ziel von 8.
Warum nicht höher
Anfragen über das hinaus, was die Konverter abarbeiten können, werden nicht schneller: Sie warten in der Warteschlange von Docling. Diese Warteschlange kennt keine Prioritäten, daher wartet jede zusätzliche Anfrage eines großen Uploads vor den Dokumenten anderer Benutzer. QAnswer verteilt die Stapel jedes Benutzers auf die Prioritätsstufen seines Celery-Brokers, was nur hilft, solange die Stapel noch auf der QAnswer-Seite warten.
Wenn eine Konvertierung fehlschlägt
Schlägt eine Docling-Anfrage fehl oder läuft in ein Timeout, schreibt das Backend eine Warnung ("Docling serve conversion failed, falling back to vanilla parser") und konvertiert diesen Stapel stattdessen mit seinem einfachen Parser (Tesseract-OCR, wenn OCR angefordert war). Die Grenzen sind:
- Der Docling-API-Server wartet höchstens 200 Sekunden (DOCLING_SERVE_MAX_SYNC_WAIT) auf eine synchrone Konvertierung, und das Backend weist Docling an, einen Stapel nach 180 Sekunden abzubrechen.
- Ein Docling-Auftrag wird nach 300 Sekunden gestoppt (DOCLING_SERVE_ENG_RQ_JOB_TIMEOUT), unabhängig davon, was die auslösende Anfrage gerade tut.
In der Praxis ist die Ursache meist ein Docling-Worker oder der API-Server, der wegen Speichermangels beendet wird, wodurch alle seine laufenden Anfragen fehlschlagen: In einem unserer Läufe schickte ein einziger Neustart des API-Servers 121 von 255 Stapeln zum einfachen Parser. In den Messungen oben fiel kein Stapel auf den einfachen Parser zurück, auch nicht mit 4 pro Backend.
Arbeitsspeicher
- Docling-Worker: QANSWER_DOCLING_WORKER_MEMORY_LIMIT, standardmäßig 8G.
- Docling-Worker wachsen mit der Zeit (in unseren Läufen von 3 auf 8 GiB an einem Tag, docling-serve Issue 366). Bleibt ein Worker bei fünf Prüfungen in Folge über QANSWER_DOCLING_WORKER_RECYCLE_MB (standardmäßig 6144), schlägt seine Gesundheitsprüfung fehl und autoheal startet ihn geordnet neu, nachdem der laufende Auftrag beendet ist. Halten Sie diese Schwelle um mehr als die Spitze eines Auftrags unter dem Speicherlimit.
- Docling-API-Server: QANSWER_DOCLING_APISERVER_MEMORY_LIMIT, standardmäßig 4G. Er braucht mehr Speicher, je mehr Anfragen gleichzeitig laufen: Mit 1 GiB wurde er bei vier gleichzeitigen Anfragen beendet.
- Python-Backend: QANSWER_PYTHON_BACKEND_MEMORY_LIMIT, standardmäßig 20G.
Mit prefork ist jeder Slot ein eigener Prozess im Backend-Container, eine höhere Parallelität zählt also auf das Backend-Limit. In den Messungen oben blieb das Backend mit bis zu 4 Slots unter 9,5 GiB seiner 20 GiB.
Änderung anwenden
Setzen Sie die Variablen in der Datei .env.override im Bundle-Verzeichnis (legen Sie sie an, falls sie fehlt). Sie wird nach .env und .env.specs geladen, hat also Vorrang, und wird nicht eingecheckt. Die Replikatzahlen stehen in .env.specs und lassen sich auf dieselbe Weise überschreiben.
# .env.override
QANSWER_CELERY_DOCLING_POOL=prefork
QANSWER_CELERY_DOCLING_CONCURRENCY=2Führen Sie anschließend das Deployment-Skript erneut aus, das die Dienste mit geänderter Konfiguration neu erstellt:
./deploy-scripts/up.shErgebnis prüfen
Wenn Sie das Monitoring-Bundle betreiben, zeigen zwei Grafana-Dashboards, ob die Konfiguration funktioniert:
- Celery Monitoring - Flower Metrics: Das Panel Currently Executing Tasks (by worker type) zeigt, wie viele Docling-Extraktionsaufgaben gleichzeitig laufen; bei einem großen Upload sollte es sich der Zahl der Backend-Replikate mal Parallelität nähern.
- Docling Serve - OTel Observability: Active Requests (Concurrency) und Request Duration Percentiles zeigen die Last auf dem API-Server, Error Rate Over Time (4xx / 5xx) zeigt fehlgeschlagene Anfragen, und die Container-Health-Panels zeigen Speicher und Neustarts der Worker.
Sehen Sie sich während der Indexierung einer großen Datei an, wie ausgelastet die Docling-Worker sind. Deutlich unter 80 % bedeutet Spielraum für mehr Parallelität; ab etwa 80 % erzeugt mehr Parallelität nur zusätzliche Wartezeit.
Suchen Sie in den Backend-Logs nach "falling back to vanilla parser". Vereinzelte Zeilen sind normal; ein stetiger Strom bedeutet meist, dass Docling-Container neu starten.