CommunityCodierung & Entwicklunggithub.com

SystemTce/dify-skills

Eine umfassende Anleitung zur Leistungsoptimierung von Dify-Workflows und -Plugins.

Was ist dify-skills?

Diese Skill bietet eine umfassende Anleitung zur Leistungsoptimierung von Dify-Workflows und -Plugins. Sie deckt Kernbereiche wie Graphstrukturoptimierung, LLM-Kostenkontrolle, Worker-Pool-Tuning, Variablenpool-Optimierung, parallele Verarbeitung und Leistungsüberwachung ab. Entwickler können damit messbare Verbesserungen erzielen, z. B. eine Reduzierung der Ausführungszeit um 40-60 % durch parallele Verzweigungen und eine Senkung der LLM-API-Aufrufe um 30-50 % durch Caching. Die Skill enthält fünf reale Optimierungsbeispiele mit Vorher-Nachher-Vergleichen sowie eine schnelle Diagnose-Checkliste für fünf Dimensionen. Sie ist für alle Dify-Benutzer geeignet, die Leistungsengpässe beheben und ihre Workflows effizienter gestalten möchten.

Funktioniert mit✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/SystemTce/dify-skills/tree/main/03-performance

Installed? Explore more Codierung & Entwicklung skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Dify Leistungsoptimierung SKILL

Übersicht

Diese SKILL bietet eine umfassende Anleitung zur Leistungsoptimierung von Dify-Workflows und -Plugins. Sie deckt Kernthemen wie Graphstrukturoptimierung, LLM-Kostenkontrolle, Worker-Pool-Tuning, Variablenpool-Optimierung, parallele Verarbeitung und Leistungsüberwachung ab.

Anwendungsszenarien

Verwenden Sie diese SKILL, wenn Sie auf folgende Situationen stoßen:

  • ⏱️ Die Workflow-Ausführungszeit ist zu lang und erfordert eine Leistungsoptimierung
  • 💰 Die LLM-API-Kosten sind zu hoch und der Token-Verbrauch muss gesenkt werden
  • 🚀 Die Fähigkeit zur gleichzeitigen Verarbeitung ist unzureichend und der Durchsatz muss erhöht werden
  • 📊 Die Systemressourcenauslastung ist niedrig und die Konfiguration muss optimiert werden
  • 📈 Leistungsengpässe bei der Verarbeitung großer Datenmengen
  • 🔍 Es ist eine Leistungsdiagnose und -überwachung erforderlich

Kernwerte

  • Quantifizierbare Optimierungseffekte: Parallele Verzweigungen reduzieren die Zeit um 40–60 %, LLM-Caching reduziert API-Aufrufe um 30–50 %
  • Praxisnahe Beispiele: 5 reale Optimierungsfälle mit Vorher-Nachher-Vergleichen
  • Umfassende Optimierungsstrategien: Deckt Workflows, LLMs, Plugins, Überwachung und alle Ebenen ab
  • Schnelle Diagnosetools: Eine Leistungsdiagnose-Checkliste für 5 Dimensionen

Schnelle Diagnose-Checkliste

Verwenden Sie die folgende Checkliste, um Leistungsprobleme schnell zu identifizieren, bevor Sie mit der Optimierung beginnen:

📊 Graphstruktur-Diagnose

  • Gibt es zu viele serielle Abhängigkeiten?
  • Können parallele Verzweigungen verwendet werden? (v0.8.0+)
  • Gibt es unnötige Knoten und Verbindungen?
  • Übersteigt die Anzahl der Knoten 50?
  • Wird ein geeignetes Entwurfsmuster verwendet?

🤖 LLM-Nutzungsdiagnose

  • Ist die Modellauswahl geeignet? (Leichte Aufgaben mit leichten Modellen)
  • Ist der Prompt zu lang? (Kann er gekürzt werden?)
  • Ist das LLM-Antwort-Caching aktiviert?
  • Werden strukturierte Ausgaben verwendet? (JSON Schema)
  • Liegt der Token-Verbrauch im Budget?

⚙️ Worker-Pool-Diagnose

  • Ist die Anzahl der Worker angemessen konfiguriert? (2–8 Threads)
  • Ist die Warteschlangentiefe zu groß?
  • Gibt es eine Verschwendung durch untätige Worker?
  • Ist die Skalierungsstrategie sinnvoll?

💾 Variablenpool-Diagnose

  • Werden große Objekte im Variablenpool gespeichert?
  • Werden Variablen rechtzeitig bereinigt?
  • Werden Referenzen anstelle von Kopien verwendet?
  • Ist der Variablenbereich sinnvoll?

🔄 Parallelverarbeitungsdiagnose

  • Ist parallel_nums für Iteratoren konfiguriert?
  • Werden Streaming-Antworten verwendet?
  • Sind asynchrone Aufgaben angemessen konfiguriert?
  • Gibt es blockierende Operationen?

Teil 1: Graphstrukturoptimierung

1.1 Reduzierung serieller Abhängigkeiten

Problem: Zu viele serielle Abhängigkeiten führen zu linearem Wachstum der Workflow-Ausführungszeit.

Optimierungsstrategie:

  1. Identifizieren Sie parallelisierbare Knoten: Analysieren Sie die Abhängigkeiten zwischen Knoten, um Knoten zu finden, die parallel ausgeführt werden können
  2. Verwenden Sie parallele Verzweigungen: Dify v0.8.0+ unterstützt die Funktion für parallele Verzweigungen
  3. Strukturieren Sie den Workflow um: Wandeln Sie serielle Abläufe in ein Parallel-+Aggregations-Muster um

Beispiel:

# Vor Optimierung: Serielle Ausführung (Gesamtzeit = 3 + 2 + 4 = 9 Sekunden)
Start → API-Aufruf1(3s) → API-Aufruf2(2s) → API-Aufruf3(4s) → Ende

# Nach Optimierung: Parallele Ausführung (Gesamtzeit = max(3,2,4) = 4 Sekunden)
Start → [API-Aufruf1(3s), API-Aufruf2(2s), API-Aufruf3(4s)] → Variablenaggregation → Ende

Optimierungseffekt: Ausführungszeit um 40–60 % reduziert

1.2 Parallele Verzweigungsfunktion (v0.8.0+)

Dify v0.8.0 führt eine Funktion für parallele Verzweigungen ein, die es mehreren Zweigen ermöglicht, gleichzeitig ausgeführt zu werden.

Verwendung:

  1. Erstellen Sie im Workflow-Editor mehrere Zweige
  2. Stellen Sie sicher, dass keine Datenabhängigkeiten zwischen den Zweigen bestehen
  3. Verwenden Sie einen Variablenaggregator, um die Ergebnisse zu sammeln

Anwendungsszenarien:

  • Gleichzeitige Aufrufe mehrerer HTTP-Request-Knoten
  • Gleichzeitige Ausführung mehrerer Tool-Knoten
  • Parallele Verarbeitung von Wissensdatenbankabfragen + API-Aufrufen
  • Parallele Inferenz mit mehreren Modellen (Modellvergleichsszenarien)

Konfigurationsbeispiel:

# Konfiguration paralleler Verzweigungen
parallel_branches:
  - branch_1:
      nodes: [http_request_1, code_1]
  - branch_2:
      nodes: [http_request_2, code_2]
  - branch_3:
      nodes: [tool_1, llm_1]

1.3 Vermeidung unnötiger Knoten

Häufige Probleme:

  • Redundante Datenkonvertierungsknoten
  • Unnötige Zwischenvariablenknoten
  • Übermäßige Bedingungsknoten

Optimierungsvorschläge:

  • Führen Sie ähnliche Verarbeitungslogik zusammen
  • Verwenden Sie Code-Knoten anstelle mehrerer einfacher Knoten
  • Vereinfachen Sie die Logik von Bedingungsabfragen

1.4 Entwurfsmuster für Graphstrukturen

Wählen Sie basierend auf dem Aufgabentyp ein geeignetes Entwurfsmuster:

  1. Sequenz-Pipeline: Start → LLM → Ende (einfache Aufgaben)
  2. Bedingte Verzweigung: Start → LLM → If-Else → Mehrere Pfade (Entscheidungsaufgaben)
  3. Iterative Verarbeitung: Start → Code → Iteration → LLM (Batch-Aufgaben)
  4. Wissensabfrage: Start → Knowledge-Retrieval → LLM (RAG-Anwendungen)
  5. Multi-Quellen-Aggregation: Mehrere Tool/HTTP → Variable-Aggregator → LLM (Datenaggregation)

Ausführliche Dokumentation: Siehe workflow-optimization/graph-structure.md


Teil 2: LLM-Optimierungsstrategien

2.1 Modellauswahlstrategie

Die Auswahl des richtigen Modells ist der Schlüssel zur Kostenoptimierung.

Modellauswahlmatrix:

AufgabentypEmpfohlenes ModellToken-KostenAnwendungsszenario
Einfache KlassifikationQwen-Turbo, Gemini FlashNiedrigTextklassifikation, Stimmungsanalyse
TextgenerierungGPT-3.5-turbo, Qwen-PlusMittelInhaltsgenerierung, Zusammenfassungen
Komplexes DenkenGPT-4, Claude OpusHochKomplexe Analysen, Entscheidungen
Lokale BereitstellungOllama (Llama 3, Qwen)Null API-KostenDatenschutzsensible Szenarien

Kostenvergleich:

  • GPT-4: 0,03 $/1K Tokens (Eingabe) + 0,06 $/1K Tokens (Ausgabe)
  • GPT-3.5-turbo: 0,0015 $/1K Tokens (Eingabe) + 0,002 $/1K Tokens (Ausgabe)
  • Qwen-Turbo: ¥0,0008 /1K Tokens (ca. 20-facher Kostenunterschied)

Optimierungsvorschläge:

  • Leichte Aufgaben mit leichten Modellen (Qwen/Gemini)
  • Komplexe Aufgaben mit leistungsstarken Modellen (GPT-4/Claude)
  • Erwägen Sie die Verwendung lokaler Modelle (Ollama) zur Kostensenkung

2.2 Prompt-Optimierungstipps

Prompt kürzen:

# Vor Optimierung (150 Tokens)
"""
Du bist ein professioneller Kundendienstmitarbeiter. Bitte lies die folgende Kundenfrage sorgfältig durch und gib basierend auf unserer Produktwissensdatenbank eine detaillierte, genaue und freundliche Antwort. Beachte bei der Antwort die folgenden Punkte:
1. Bewahre einen professionellen und höflichen Ton
2. Biete konkrete Lösungen an
3. Wenn du dir unsicher bist, gib dies an
4. Zitiere relevante Produktdokumente

Kundenfrage: {query}
"""

# Nach Optimierung (50 Tokens)
"""
Beantworte als Kundendienstmitarbeiter die Kundenfrage basierend auf der Wissensdatenbank, bleibe professionell und höflich.

Frage: {query}
"""

Token-Ersparnis: 66 % (150 → 50 Tokens)

Weitere Optimierungstipps:

  • Entfernen Sie redundante Erklärungen und Beispiele
  • Verwenden Sie prägnante Anweisungen
  • Vermeiden Sie sich wiederholende Kontexte
  • Verwenden Sie strukturierte Ausgaben, um Parsing-Kosten zu senken

2.3 Caching-Strategie

LLM-Antwort-Caching:

Verwenden Sie Redis, um LLM-Antworten zu cachen und wiederholte Aufrufe zu vermeiden.

Implementierung:

import hashlib
import redis

# Verbindung zu Redis herstellen
r = redis.Redis(host='localhost', port=6379, db=0)

def get_llm_response_with_cache(prompt, model="gpt-3.5-turbo"):
    # Cache-Schlüssel generieren
    cache_key = f"llm:{model}:{hashlib.md5(prompt.encode()).hexdigest()}"

    # Cache prüfen
    cached = r.get(cache_key)
    if cached:
        return cached.decode('utf-8')

    # LLM aufrufen
    response = call_llm_api(prompt, model)

    # Cache speichern (TTL: 1 Stunde)
    r.setex(cache_key, 3600, response)

    return response

Caching-Strategie:

  • LLM-Antwort-Caching: Gleicher Prompt gibt zwischengespeichertes Ergebnis zurück
  • Wissensdatenbank-Abfrage-Caching: Gleiche Abfrage gibt zwischengespeicherte Vektoren zurück
  • Knotenergebnis-Caching: Vermeidet wiederholte Ausführung desselben Knotens

Optimierungseffekt: API-Aufrufe um 30–50 % reduziert

2.4 Strukturierte Ausgabe

Verwenden Sie JSON Schema, um die Stabilität der LLM-Ausgabe zu gewährleisten und Parsing-Fehler sowie Wiederholungen zu reduzieren.

Konfigurationsbeispiel:

{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["Technisch", "Vertrieb", "Nachverkauf"]
    },
    "priority": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "summary": {
      "type": "string",
      "maxLength": 100
    }
  },
  "required": ["category", "priority", "summary"]
}

Optimierungseffekt:

  • Reduziert die Anzahl der Ausgabe-Tokens
  • Vermeidet Parsing-Fehler und Wiederholungen
  • Verbessert die Verarbeitungseffizienz nachgelagerter Knoten

Ausführliche Dokumentation: Siehe llm-optimization/


Teil 3: Worker-Pool-Tuning

3.1 Dynamischer Worker-Thread-Pool

Dify verwendet einen dynamischen Worker-Pool zur parallelen Ausführung von Knoten. Die Standardkonfiguration liegt bei 2–8 Worker-Threads.

Worker-Pool-Architektur:

GraphEngine
├── ReadyQueue (Warteschlange bereiter Knoten)
├── EventQueue (Ereigniswarteschlange)
├── Dispatcher (Ereignisverteiler)
└── WorkerPool (2–8 Worker-Threads)
    ├── Worker 1
    ├── Worker 2
    ├── ...
    └── Worker N

3.2 Konfigurationsparameter

Wichtige Konfigurationen:

ParameterStandardwertBeschreibungOptimierungsvorschlag
min_workers2Minimale Anzahl an WorkernEntsprechend der minimalen Parallelitätsanforderung einstellen
max_workers8Maximale Anzahl an WorkernEntsprechend der Anzahl der CPU-Kerne einstellen
queue_depth_threshold10Schwellenwert für die SkalierungEntsprechend der durchschnittlichen Warteschlangentiefe anpassen
idle_timeout60sLeerlauf-Timeout für WorkerEntsprechend der Aufgabenfrequenz anpassen

Skalierungsstrategie:

# Skalierungsbedingung
if queue_depth > queue_depth_threshold and workers < max_workers:
    add_worker()

# Verkleinerungsbedingung
if worker_idle_time > idle_timeout and workers > min_workers:
    remove_worker()

3.3 Leistungsbenchmarks

Testszenario: Workflow mit 100 Knoten

Anzahl WorkerAusführungszeitDurchsatzCPU-Auslastung
245s2,2 Knoten/s40%
425s4,0 Knoten/s70%
815s6,7 Knoten/s95%

Optimierungseffekt: Erhöhung der Worker-Anzahl von 2 auf 8, Durchsatz um das 3-fache gesteigert

3.4 Optimierungsvorschläge

  1. max_workers basierend auf CPU-Kernen einstellen: Üblicherweise das 1- bis 2-fache der Anzahl der CPU-Kerne
  2. Überwachen Sie die Warteschlangentiefe: Wenn die Warteschlangentiefe kontinuierlich hoch ist, erhöhen Sie max_workers
  3. Übermäßige Skalierung vermeiden: Zu viele Worker verursachen Kontextwechsel-Overhead
  4. Verwenden Sie asynchrone E/A: Für E/A-intensive Aufgaben verwenden Sie asynchrone Verarbeitung, um die Effizienz zu steigern

Ausführliche Dokumentation: Siehe workflow-optimization/parallel-execution.md


Teil 4: Variablenpool-Optimierung

4.1 Vermeidung der Speicherung großer Objekte

Problem: Das Speichern großer Objekte (z. B. große Dateien, langer Text) im Variablenpool verbraucht viel Arbeitsspeicher.

Optimierungsstrategie:

# ❌ Nicht empfohlen: Große Objekte speichern
variables = {
    "large_file": open("large_file.pdf", "rb").read(),  # 10 MB
    "long_text": "..." * 100000  # 1 MB
}

# ✅ Empfohlen: Referenzen speichern
variables = {
    "file_path": "/pfad/zu/large_file.pdf",
    "text_summary": summarize(long_text)  # Nur Zusammenfassung speichern
}

4.2 Verwendung von Referenzen anstelle von Kopien

Problem: Das Kopieren von Variablen erhöht den Speicherverbrauch und die Verarbeitungszeit.

Optimierungsstrategie:

# ❌ Nicht empfohlen: Variablen kopieren
result = process_data(data.copy())

# ✅ Empfohlen: Referenzen verwenden
result = process_data(data)  # Bei schreibgeschützten Operationen Referenzen verwenden

4.3 Rechtzeitige Bereinigung von Variablen

Problem: Nicht mehr verwendete Variablen belegen Speicher.

Optimierungsstrategie:

# In Code-Knoten nicht mehr verwendete Variablen bereinigen
def main(args):
    # Daten verarbeiten
    large_data = process_large_data(args["input"])
    result = extract_result(large_data)

    # Großes Objekt bereinigen
    del large_data

    return {"result": result}

4.4 Variablenbereichsverwaltung

Variablentypen:

  • Systemvariablen: sys.query, sys.files, sys.conversation_id
  • Knotenvariablen: {{#node_id.output#}}
  • Umgebungsvariablen: Konfiguration und Schlüsselverwaltung
  • Iterationsvariablen: Aktuelles Element und Index in Schleifen

Optimierungsvorschläge:

  • Verwenden Sie den kleinstmöglichen Bereich
  • Vermeiden Sie globale Variablenverschmutzung
  • Geben Sie temporäre Variablen rechtzeitig frei

Ausführliche Dokumentation: Siehe workflow-optimization/variable-pool.md


Teil 5: Parallele Verarbeitung und Streaming-Antworten

5.1 Parallele Iteratorenverarbeitung

Verwenden Sie den Parameter parallel_nums von Iteratoren, um Array-Daten parallel zu verarbeiten.

Konfigurationsbeispiel:

iteration_node:
  type: iteration
  inputs:
    items: "{{#code_node.output.items#}}"
  config:
    parallel_nums: 5  # 5 Elemente parallel verarbeiten

Leistungsvergleich:

DatenmengeSerielle VerarbeitungParallele Verarbeitung (5)Verbesserung
10 Elemente20s5s4x
50 Elemente100s25s4x
100 Elemente200s50s4x

5.2 Streaming-Antworten

Verwenden Sie Streaming-Antworten, um die Benutzererfahrung zu verbessern und die Time-to-First-Byte (TTFB) zu reduzieren.

Implementierung:

# API-Aufruf mit aktiviertem Streaming
response = requests.post(
    "https://api.dify.ai/v1/workflows/run",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"inputs": {...}, "response_mode": "streaming"},
    stream=True
)

for line in response.iter_lines():
    if line:
        event = json.loads(line)
        print(event["data"])

Optimierungseffekt:

  • TTFB um 80 % reduziert
  • Vom Benutzer wahrgenommene Antwortzeit um 50 % reduziert

5.3 Asynchrone Aufgabenverarbeitung

Verwenden Sie Celery zur asynchronen Verarbeitung langlaufender Aufgaben.

Architektur:

API-Server → Celery Queue → Worker Pool → Aufgabenausführung

Anwendungsszenarien:

  • Verarbeitung großer Dateien
  • Batch-Datenimport
  • Langlaufende API-Aufrufe
  • Geplante Aufgaben

5.4 Optimierung der ereignisgesteuerten Architektur

Dify verwendet eine ereignisgesteuerte Architektur, bei der die Knotenausführung einen Ereignisstrom erzeugt.

Optimierungsstrategie:

  • Verwenden Sie eine nicht blockierende Ereignisverarbeitung
  • Verarbeiten Sie Ereigniswarteschlangen in Batches
  • Optimieren Sie die Ereignisverteilungslogik

Ausführliche Dokumentation: Siehe workflow-optimization/parallel-execution.md


Teil 6: Leistungsoptimierungsbeispiele

Beispiel 1: Datenbankabfrageoptimierung (N+1-Problem)

Anwendungsszenario:

  • Im Workflow müssen mehrere zusammenhängende Daten abgefragt werden
  • Es gibt zyklische Datenbankabfragen
  • Die Ausführungszeit wächst linear mit der Datenmenge

Problemmerkmale:

  • Anzahl der Abfragen = 1 + N (N = Anzahl der Datensätze)
  • Datenbankverbindungen werden häufig auf- und abgebaut
  • Ausführungszeit zu lang

Zustand vor der Optimierung:

# Benutzerliste abfragen
users = query("SELECT * FROM users LIMIT 100")

# Für jeden Benutzer Bestellungen abfragen (N+1-Problem)
for user in users:
    orders = query(f"SELECT * FROM orders WHERE user_id = {user.id}")
    user.orders = orders
  • Anzahl der Abfragen: 101 (1 + 100)
  • Ausführungszeit: 10,5 s
  • Datenbanklast: Hoch

Optimierungslösung:

# Alle Daten auf einmal abfragen
users = query("SELECT * FROM users LIMIT 100")
user_ids = [user.id for user in users]

# Bestellungen in Batches abfragen
orders = query(f"SELECT * FROM orders WHERE user_id IN ({','.join(map(str, user_ids))})")

# Daten im Speicher verknüpfen
orders_by_user = {}
for order in orders:
    if order.user_id not in orders_by_user:
        orders_by_user[order.user_id] = []
    orders_by_user[order.user_id].append(order)

for user in users:
    user.orders = orders_by_user.get(user.id, [])

Ergebnis nach der Optimierung:

  • Anzahl der Abfragen: 2 (98 % weniger)
  • Ausführungszeit: 2,1 s (80 % weniger)
  • Datenbanklast: Niedrig

Erwartete Vorteile:

  • Kurzfristig: 80 % weniger Ausführungszeit, geringere Datenbanklast
  • Langfristig: Unterstützung größerer Datenmengen, verbesserte Skalierbarkeit des Systems
  • ROI: 2 Stunden Entwicklungsaufwand, monatliche Einsparung von 30 % der Serverkosten

Beispiel 2: Optimierung der Darstellung großer Knotenmengen (100+ Knoten)

Anwendungsszenario:

  • Workflow enthält 100+ Knoten
  • Frontend-Darstellung ruckelt
  • Editor reagiert träge

Problemmerkmale:

  • Seitenladezeit > 5 s
  • Deutliche Verzögerung beim Ziehen von Knoten
  • Hohe Speichernutzung des Browsers

Zustand vor der Optimierung:

  • Anzahl der Knoten: 150
  • Seitenladezeit: 8,5 s
  • Speichernutzung: 500 MB
  • Benutzererfahrung: Starkes Ruckeln

Optimierungslösung:

  1. Virtuelles Scrollen: Nur Knoten im sichtbaren Bereich rendern
  2. Lazy Loading von Knoten: Knotendetails bei Bedarf laden
  3. Canvas Optimierung: Canvas anstelle von DOM für die Darstellung verwenden
  4. Zustandsverwaltung optimieren: Unnötiges erneutes Rendern reduzieren

Ergebnis nach der Optimierung:

  • Seitenladezeit: 2,1 s (75 % weniger)
  • Speichernutzung: 150 MB (70 % weniger)
  • Benutzererfahrung: Flüssig

Erwartete Vorteile:

  • Kurzfristig: Deutlich verbesserte Benutzererfahrung
  • Langfristig: Unterstützung komplexerer Workflow-Designs
  • ROI: 1 Woche Entwicklungsaufwand, 40 % höhere Benutzerzufriedenheit

Beispiel 3: Optimierung der Löschleistung von Workflow-Logs

Anwendungsszenario:

  • Regelmäßige Bereinigung alter Logs erforderlich
  • Große Logdatenmengen (Millionen)
  • Löschvorgänge dauern lange

Problemmerkmale:

  • Löschvorgänge blockieren die Datenbank
  • Beeinträchtigung des normalen Betriebs
  • Unvorhersehbare Ausführungszeit

Zustand vor der Optimierung:

  • Anzahl der Logs: 5 Millionen
  • Löschzeit: 45 Minuten
  • Datenbanksperre: Lange Tabellensperre
  • Geschäftsauswirkung: Schwerwiegend

Optimierungslösung:

# Vor Optimierung: Einmaliges Löschen
DELETE FROM workflow_logs WHERE created_at < '2024-01-01';

# Nach Optimierung: Batchweises Löschen
batch_size = 10000
while True:
    deleted = DELETE FROM workflow_logs
              WHERE created_at < '2024-01-01'
              LIMIT batch_size

    if deleted < batch_size:
        break

    # Kurze Pause, um die Datenbanksperre freizugeben
    sleep(0.1)

Ergebnis nach der Optimierung:

  • Löschzeit: 50 Minuten (leicht erhöht, blockiert aber nicht den Betrieb)
  • Datenbanksperre: Kurze Sperre (0,1 s)
  • Geschäftsauswirkung: Keine

Erwartete Vorteile:

  • Kurzfristig: Geschäftsbetrieb nicht beeinträchtigt
  • Langfristig: Höhere Datenbankstabilität
  • ROI: 4 Stunden Entwicklungsaufwand, Vermeidung von Betriebsunterbrechungen

Beispiel 4: Integration von TiDB verteiltem Speicher

Anwendungsszenario:

  • Große Wissensdatenbank (TB-Bereich)
  • Leistungsengpässe bei Single-Node PostgreSQL
  • Horizontale Skalierung erforderlich

Problemmerkmale:

  • Abfrageantwortzeit > 5 s
  • Datenbank-CPU-Auslastung > 90 %
  • Keine weitere Skalierung möglich

Zustand vor der Optimierung:

  • Datenbank: PostgreSQL Single-Node
  • Datenmenge: 2 TB
  • Abfrageantwortzeit: 8,5 s
  • Skalierbarkeit: Eingeschränkt

Optimierungslösung:

  1. Migration zu TiDB: Verteilte SQL-Datenbank
  2. Vektorindex-Optimierung: Verwendung von TiDB Vector zur Beschleunigung der Suche
  3. Lese-Schreib-Trennung: Leseanfragen auf mehrere Replikate verteilen
  4. Partitionierte Tabellen: Partitionierung nach Zeit zur Verbesserung der Abfrageeffizienz

Ergebnis nach der Optimierung:

  • Abfrageantwortzeit: 1,2 s (86 % weniger)
  • Datenbank-CPU: 40 % (50 % weniger)
  • Skalierbarkeit: Unterstützt 10-fache Datenmenge

Erwartete Vorteile:

  • Kurzfristig: Deutlich verbesserte Abfrageleistung
  • Langfristig: Unterstützung schnellen Geschäftswachstums
  • ROI: 2 Wochen Migrationsaufwand, Unterstützung 10-fachen Geschäftswachstums

Beispiel 5: Hochverfügbarkeitsbereitstellung mit Higress AI Gateway

Anwendungsszenario:

  • Hochverfügbarkeit in der Produktion erforderlich
  • Lastverteilung für mehrere LLM-Modelle
  • Failover-Fähigkeit erforderlich

Problemmerkmale:

  • Single Point of Failure-Risiko
  • LLM-API-Aufrufe instabil
  • Unfähigkeit, Traffic-Spitzen zu bewältigen

Zustand vor der Optimierung:

  • Architektur: Single-Instance Dify
  • Verfügbarkeit: 95 %
  • Wiederherstellungszeit nach Fehler: 10 Minuten
  • Traffic-Spitzen: Nicht handhabbar

Optimierungslösung:

# Higress AI Gateway Konfiguration
apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: dify-gateway
spec:
  replicas: 3  # 3 Instanzen
  loadBalancer:
    algorithm: round-robin
  healthCheck:
    enabled: true
    interval: 10s
  failover:
    enabled: true
    maxRetries: 3

Architektur:

Benutzeranfragen → Higress Gateway → [Dify Instanz 1, Dify Instanz 2, Dify Instanz 3]
                ↓
          Lastverteilung + Failover

Ergebnis nach der Optimierung:

  • Verfügbarkeit: 99,9 %
  • Wiederherstellungszeit nach Fehler: < 1 Sekunde (automatischer Wechsel)
  • Traffic-Spitzen: Unterstützt 10-fachen Traffic

Erwartete Vorteile:

  • Kurzfristig: Deutlich verbesserte Systemstabilität
  • Langfristig: Unterstützung geschäftskritischer Anwendungen
  • ROI: 3 Tage Bereitstellungsaufwand, Vermeidung von Betriebsunterbrechungen

Teil 7: Leistungstests und Überwachung

7.1 Leistungskennzahlen

Workflow-Ausführungsmetriken:

MetrikZielwertBeschreibung
Durchschnittliche Ausführungszeit< 2 sVollständige Workflow-Ausführungszeit
P95-Ausführungszeit< 5 sAusführungszeit für 95 % der Anfragen
P99-Ausführungszeit< 10 sAusführungszeit für 99 % der Anfragen
Knotenerfolgsrate> 99 %Anteil erfolgreicher Knotenausführungen
API-Aufruferfolgsrate> 99,5 %Erfolgsrate externer API-Aufrufe
Gleichzeitige Verarbeitungskapazität> 100 QPSAnfragen pro Sekunde

Ressourcennutzungsmetriken:

MetrikZielwertBeschreibung
CPU-Auslastung< 70 %Durchschnittliche CPU-Auslastung
Speicherauslastung< 80 %Durchschnittliche Speicherauslastung
Datenbankverbindungen< 80 %Verbindungspool-Auslastung
Redis-Speicher< 70 %Redis-Speicherauslastung

Kostenmetriken:

MetrikZielwertBeschreibung
Token-Nutzungskosten< BudgetLLM-API-Kosten
Infrastrukturkosten< BudgetServer-, Datenbankkosten
Kosten/BenutzerKontinuierlich sinkendKosten pro Benutzer

7.2 Überwachungstools

LLMOps-Überwachung:

# Dify integrierte Überwachung
from dify import Monitor

monitor = Monitor()

# Workflow-Ausführung aufzeichnen
monitor.log_workflow_execution(
    workflow_id="xxx",
    execution_time=2.5,
    node_count=10,
    token_usage=1500,
    cost=0.003
)

# Statistiken abfragen
stats = monitor.get_workflow_stats(
    workflow_id="xxx",
    time_range="7d"
)

Ausführungsverfolgung:

  • Workflow-Ausführungsverlauf
  • Statistik der Knotenausführungsschritte
  • LLM-Nutzungsstatistiken
  • Fehlerprotokolle und Wiederholungsaufzeichnungen

Ressourcenüberwachung:

# Prometheus + Grafana
# Überwachung von CPU, Speicher, Netzwerk, Festplatte

# Beispielabfrage
rate(dify_workflow_execution_total[5m])  # Workflow-Ausführungsrate
histogram_quantile(0.95, dify_workflow_duration_seconds)  # P95-Ausführungszeit

7.3 Methoden für Leistungstests

Lasttests:

# Lasttests mit Locust
from locust import HttpUser, task, between

class DifyUser(HttpUser):
    wait_time = between(1, 3)

    @task
    def run_workflow(self):
        self.client.post(
            "/v1/workflows/run",
            headers={"Authorization": f"Bearer {self.api_key}"},
            json={"inputs": {"query": "Testfrage"}}
        )

# Test ausführen
# locust -f load_test.py --users 100 --spawn-rate 10

Belastungstests:

# Mit Apache Bench
ab -n 1000 -c 50 -H "Authorization: Bearer xxx" \
   -p request.json \
   https://api.dify.ai/v1/workflows/run

Benchmarks:

# Leistungsbenchmarks
import time

def benchmark_workflow(workflow_id, iterations=100):
    times = []
    for i in range(iterations):
        start = time.time()
        run_workflow(workflow_id)
        end = time.time()
        times.append(end - start)

    return {
        "avg": sum(times) / len(times),
        "p50": sorted(times)[len(times) // 2],
        "p95": sorted(times)[int(len(times) * 0.95)],
        "p99": sorted(times)[int(len(times) * 0.99)]
    }

7.4 Leistungsanalysetools

Python Profiler:

import cProfile
import pstats

# Workflow profilieren
cProfile.run('run_workflow("workflow_id")', 'profile_output')

# Ergebnisse analysieren
p = pstats.Stats('profile_output')
p.sort_stats('cumulative').print_stats(20)

Ausführungs-Tracing:

# Leistungsmetriken sammeln
from opentelemetry import trace

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("workflow-execution") as span:
    span.set_attribute("workflow.id", workflow_id)
    span.set_attribute("node.count", node_count)

    # Workflow ausführen
    result = execute_workflow(workflow_id)

    span.set_attribute("execution.time", result.time)
    span.set_attribute("token.usage", result.tokens)

Wichtige Überwachungsmetriken:

MetrikBedeutungWarnschwelle
dify_workflow_duration_secondsWorkflow-Ausführungszeit> 10 s
dify_node_execution_totalAnzahl der Knotenausführungen-
dify_llm_token_usage_totalLLM-Token-Verbrauch> Budget
dify_queue_depthWarteschlangentiefe> 100
dify_worker_countAnzahl der Worker< min_workers

Zusammenfassung

Diese SKILL bietet einen umfassenden Leitfaden zur Leistungsoptimierung von Dify-Workflows. Die Optimierung sollte bei der Graphstruktur beginnen und schrittweise auf LLM, Worker-Pool, Variablenpool und andere Bereiche ausgeweitet werden. Es wird empfohlen, zuerst die Schnelle Diagnose-Checkliste zu verwenden, um Probleme zu lokalisieren, dann gezielte Optimierungen durchzuführen und schließlich die Testergebnisse zu überwachen und zu validieren.

Nächste Schritte

  1. Führen Sie die Schnelle Diagnose-Checkliste durch
  2. Priorisieren Sie die Optimierung basierend auf der Checkliste
  3. Optimieren Sie gemäß der Optimierungsstrategie in den Teilen 1–5
  4. Validieren Sie die Ergebnisse mit Leistungstests und Überwachung
  5. Wiederholen Sie bei Bedarf den Optimierungsprozess

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

Verwandte Skills