CommunityProgramación y desarrollogithub.com

SystemTce/dify-skills

Guía completa de optimización de rendimiento para flujos de trabajo y plugins de Dify.

¿Qué es dify-skills?

Esta habilidad proporciona una guía exhaustiva para optimizar el rendimiento de los flujos de trabajo y plugins de Dify, cubriendo temas clave como la optimización de la estructura del grafo, el control de costos de LLM, el ajuste del pool de workers, la optimización del pool de variables, el procesamiento paralelo y la monitorización del rendimiento. Su objetivo es ayudar a los desarrolladores y usuarios de Dify a identificar y resolver cuellos de botella de rendimiento, ya sea que estén lidiando con tiempos de ejecución prolongados, costos elevados de API de LLM, capacidad de concurrencia insuficiente o baja utilización de recursos del sistema. La guía ofrece estrategias de optimización con resultados cuantificables, como una reducción del 40-60% en el tiempo de ejecución mediante la ejecución paralela de ramas y una disminución del 30-50% en las llamadas de LLM a través del almacenamiento en caché. Incluye cinco casos prácticos de optimización real con comparaciones antes y después, y una lista de verificación de diagnóstico rápido de cinco dimensiones para ayudar a los usuarios a localizar problemas de manera eficiente.

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

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Dify Optimización de Rendimiento SKILL

Resumen

Este SKILL proporciona una guía completa de optimización de rendimiento para flujos de trabajo y plugins de Dify, cubriendo temas clave como la optimización de la estructura del grafo, el control de costos de LLM, el ajuste del pool de workers, la optimización del pool de variables, el procesamiento paralelo y la monitorización del rendimiento.

Escenarios de Aplicación

Debe usar este SKILL cuando se encuentre con las siguientes situaciones:

  • ⏱️ El tiempo de ejecución del flujo de trabajo es demasiado largo y necesita optimización de rendimiento
  • 💰 El costo de la API de LLM es demasiado alto y necesita reducir el consumo de tokens
  • 🚀 La capacidad de procesamiento concurrente es insuficiente y necesita aumentar el rendimiento
  • 📊 La utilización de recursos del sistema es baja y necesita optimizar la configuración
  • 📈 Cuellos de botella de rendimiento en el procesamiento de datos a gran escala
  • 🔍 Necesita realizar diagnóstico y monitorización de rendimiento

Valor Central

  • Efectos de optimización cuantificables: La ejecución de ramas paralelas reduce el tiempo en un 40-60%, el caché de LLM reduce las llamadas en un 30-50%
  • Impulsado por casos prácticos: 5 casos de optimización reales, con comparaciones antes y después
  • Estrategias de optimización integrales: Cubre todos los niveles: flujo de trabajo, LLM, plugins, monitorización, etc.
  • Herramienta de diagnóstico rápido: Lista de verificación de diagnóstico de 5 dimensiones

Lista de Verificación de Diagnóstico Rápido

Antes de comenzar la optimización, use la siguiente lista para localizar rápidamente los problemas de rendimiento:

📊 Diagnóstico de Estructura del Grafo

  • ¿Existen demasiadas dependencias en serie?
  • ¿Se pueden usar ramas paralelas? (v0.8.0+)
  • ¿Hay nodos y conexiones innecesarios?
  • ¿El número de nodos supera los 50?
  • ¿Se está utilizando el patrón de diseño adecuado?

🤖 Diagnóstico de Uso de LLM

  • ¿La selección del modelo es adecuada? (tareas ligeras con modelos ligeros)
  • ¿El prompt es demasiado largo? (¿se puede simplificar?)
  • ¿Está habilitado el caché de respuestas de LLM?
  • ¿Se está utilizando salida estructurada? (JSON Schema)
  • ¿El consumo de tokens está dentro del presupuesto?

⚙️ Diagnóstico del Pool de Workers

  • ¿La configuración de la cantidad de workers es razonable? (2-8 hilos)
  • ¿La profundidad de la cola es demasiado grande?
  • ¿Hay workers inactivos que se desperdician?
  • ¿La estrategia de escalado es razonable?

💾 Diagnóstico del Pool de Variables

  • ¿Se almacenan objetos grandes en el pool de variables?
  • ¿Las variables se limpian de manera oportuna?
  • ¿Se utiliza referencia en lugar de copia?
  • ¿El ámbito de las variables es razonable?

🔄 Diagnóstico de Procesamiento Concurrente

  • ¿El iterador tiene configurado parallel_nums?
  • ¿Se utilizan respuestas en streaming?
  • ¿Las tareas asíncronas están configuradas correctamente?
  • ¿Hay operaciones bloqueantes?

Primera Parte: Optimización de la Estructura del Grafo

1.1 Reducir Dependencias en Serie

Problema: Demasiadas dependencias en serie hacen que el tiempo de ejecución del flujo de trabajo aumente linealmente.

Estrategias de Optimización:

  1. Identificar nodos paralelizables: Analice las dependencias entre nodos para encontrar aquellos que se pueden ejecutar en paralelo
  2. Usar ramas paralelas: Dify v0.8.0+ admite la función de ramas paralelas
  3. Reestructurar el flujo de trabajo: Transforme el flujo en serie en un patrón paralelo + agregación

Ejemplo:

# Antes de optimizar: Ejecución en serie (tiempo total = 3 + 2 + 4 = 9 segundos)
Inicio → LlamadaAPI1(3s) → LlamadaAPI2(2s) → LlamadaAPI3(4s) → Fin

# Después de optimizar: Ejecución en paralelo (tiempo total = max(3,2,4) = 4 segundos)
Inicio → [LlamadaAPI1(3s), LlamadaAPI2(2s), LlamadaAPI3(4s)] → AgregadorVariables → Fin

Efecto de la optimización: Reducción del tiempo de ejecución en un 40-60%

1.2 Función de Ramas Paralelas (v0.8.0+)

Dify v0.8.0 introdujo la función de ramas paralelas, permitiendo que múltiples ramas se ejecuten simultáneamente.

Método de uso:

  1. Cree múltiples ramas en el editor de flujo de trabajo
  2. Asegúrese de que no haya dependencias de datos entre las ramas
  3. Use un agregador de variables para recopilar los resultados

Escenarios de aplicación:

  • Múltiples nodos HTTP Request en llamadas paralelas
  • Múltiples nodos Tool en ejecución paralela
  • Recuperación de Knowledge + Llamada API en paralelo
  • Inferencia paralela de múltiples modelos (escenario de comparación de modelos)

Ejemplo de configuración:

# Configuración de ramas paralelas
ramas_paralelas:
  - rama_1:
      nodos: [peticion_http_1, codigo_1]
  - rama_2:
      nodos: [peticion_http_2, codigo_2]
  - rama_3:
      nodos: [herramienta_1, llm_1]

1.3 Evitar Nodos Innecesarios

Problemas comunes:

  • Nodos redundantes de transformación de datos
  • Nodos de variables intermedias innecesarios
  • Nodos de condición excesivos

Recomendaciones de optimización:

  • Combine lógicas de procesamiento similares
  • Use nodos de código en lugar de múltiples nodos simples
  • Simplifique la lógica de las condiciones

1.4 Patrones de Diseño de Estructura del Grafo

Seleccione el patrón de diseño adecuado según el tipo de tarea:

  1. Pipeline secuencial: Inicio → LLM → Fin (tareas simples)
  2. Ramas condicionales: Inicio → LLM → Si-No → Múltiples rutas (tareas de decisión)
  3. Procesamiento iterativo: Inicio → Código → Iteración → LLM (tareas por lotes)
  4. Recuperación de conocimiento: Inicio → Recuperación-Knowledge → LLM (aplicaciones RAG)
  5. Agregación de múltiples fuentes: Múltiples Tool/HTTP → Agregador-Variables → LLM (agregación de datos)

Documentación detallada: Consulte workflow-optimization/graph-structure.md


Segunda Parte: Estrategias de Optimización de LLM

2.1 Estrategia de Selección de Modelos

Elegir el modelo adecuado es clave para la optimización de costos.

Matriz de selección de modelos:

Tipo de TareaModelo RecomendadoCosto de TokenEscenario de Aplicación
Clasificación simpleQwen-Turbo, Gemini FlashBajoClasificación de texto, análisis de sentimientos
Generación de textoGPT-3.5-turbo, Qwen-PlusMedioGeneración de contenido, resúmenes
Razonamiento complejoGPT-4, Claude OpusAltoAnálisis complejo, decisiones
Despliegue localOllama (Llama 3, Qwen)Costo de API ceroEscenarios con datos sensibles

Comparación de costos:

  • GPT-4: $0.03/1K tokens (entrada) + $0.06/1K tokens (salida)
  • GPT-3.5-turbo: $0.0015/1K tokens (entrada) + $0.002/1K tokens (salida)
  • Qwen-Turbo: ¥0.0008/1K tokens (aproximadamente 20 veces de diferencia de costo)

Recomendaciones de optimización:

  • Tareas ligeras use modelos ligeros (Qwen/Gemini)
  • Tareas complejas use modelos potentes (GPT-4/Claude)
  • Considere usar modelos locales (Ollama) para reducir costos

2.2 Técnicas de Optimización de Prompt

Simplificar el Prompt:

# Antes de optimizar (150 tokens)
"""
Eres un asistente de atención al cliente profesional. Lee cuidadosamente la siguiente pregunta del cliente y, basándote en nuestra base de conocimientos de productos,
proporciona una respuesta detallada, precisa y amigable. Ten en cuenta los siguientes puntos al responder:
1. Mantén un tono profesional y cortés
2. Proporciona soluciones específicas
3. Si no estás seguro, indícalo
4. Cita la documentación de productos relevante

Pregunta del cliente: {query}
"""

# Después de optimizar (50 tokens)
"""
Como asistente de atención al cliente, responde la pregunta del cliente basándote en la base de conocimientos, manteniendo un tono profesional y cortés.

Pregunta: {query}
"""

Ahorro de tokens: 66% (150 → 50 tokens)

Otras técnicas de optimización:

  • Eliminar explicaciones y ejemplos redundantes
  • Usar instrucciones concisas
  • Evitar contexto repetitivo
  • Usar salida estructurada para reducir costos de parseo

2.3 Estrategias de Caché

Caché de respuestas de LLM:

Use Redis para cachear las respuestas de LLM, evitando llamadas repetitivas.

Implementación:

import hashlib
import redis

# Conectar a Redis
r = redis.Redis(host='localhost', port=6379, db=0)

def obtener_respuesta_llm_con_cache(prompt, modelo="gpt-3.5-turbo"):
    # Generar clave de caché
    clave_cache = f"llm:{modelo}:{hashlib.md5(prompt.encode()).hexdigest()}"

    # Verificar caché
    cacheado = r.get(clave_cache)
    if cacheado:
        return cacheado.decode('utf-8')

    # Llamar a LLM
    respuesta = llamar_api_llm(prompt, modelo)

    # Almacenar en caché (TTL: 1 hora)
    r.setex(clave_cache, 3600, respuesta)

    return respuesta

Estrategias de caché:

  • Caché de respuestas de LLM: Mismo Prompt devuelve resultado cacheado
  • Caché de recuperación de Knowledge: Misma consulta devuelve vector cacheado
  • Caché de resultados de nodos: Evita ejecutar el mismo nodo repetidamente

Efecto de la optimización: Reducción de llamadas a API en un 30-50%

2.4 Salida Estructurada

Use JSON Schema para garantizar la estabilidad de la salida de LLM, reduciendo errores de parseo y reintentos.

Ejemplo de configuración:

{
  "type": "object",
  "properties": {
    "categoria": {
      "type": "string",
      "enum": ["Técnica", "Ventas", "Postventa"]
    },
    "prioridad": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "resumen": {
      "type": "string",
      "maxLength": 100
    }
  },
  "required": ["categoria", "prioridad", "resumen"]
}

Efecto de la optimización:

  • Reduce la cantidad de tokens de salida
  • Evita errores de parseo y reintentos
  • Mejora la eficiencia del procesamiento en nodos downstream

Documentación detallada: Consulte llm-optimization/


Tercera Parte: Ajuste del Pool de Workers

3.1 Pool de Workers Dinámico

Dify usa un pool de workers dinámico para ejecutar nodos en paralelo, con una configuración predeterminada de 2 a 8 hilos de trabajo.

Arquitectura del Pool de Workers:

GraphEngine
├── ReadyQueue (Cola de nodos listos)
├── EventQueue (Cola de eventos)
├── Dispatcher (Distribuidor de eventos)
└── WorkerPool (2-8 hilos de trabajo)
    ├── Worker 1
    ├── Worker 2
    ├── ...
    └── Worker N

3.2 Parámetros de Configuración

Configuración clave:

ParámetroValor por defectoDescripciónRecomendación de optimización
min_workers2Número mínimo de WorkersEstablecer según la concurrencia mínima requerida
max_workers8Número máximo de WorkersEstablecer según el número de núcleos de CPU
umbral_profundidad_cola10Umbral de activación de escaladoAjustar según la profundidad promedio de la cola
tiempo_espera_inactivo60sTiempo de espera de inactividad del WorkerAjustar según la frecuencia de las tareas

Estrategia de escalado:

# Condición de escalado hacia arriba
if profundidad_cola > umbral_profundidad_cola and workers < max_workers:
    agregar_worker()

# Condición de escalado hacia abajo
if tiempo_inactivo_worker > tiempo_espera_inactivo and workers > min_workers:
    eliminar_worker()

3.3 Benchmark de Rendimiento

Escenario de prueba: Flujo de trabajo con 100 nodos

Número de WorkersTiempo de ejecuciónRendimientoUso de CPU
245s2.2 nodos/s40%
425s4.0 nodos/s70%
815s6.7 nodos/s95%

Efecto de la optimización: Al aumentar los Workers de 2 a 8, el rendimiento aumenta 3x

3.4 Recomendaciones de Optimización

  1. Configure max_workers según el número de núcleos de CPU: Generalmente, se establece en 1-2 veces el número de núcleos de CPU
  2. Monitoree la profundidad de la cola: Si la profundidad de la cola es consistentemente alta, aumente max_workers
  3. Evite el escalado excesivo: Demasiados Workers pueden generar sobrecarga por cambios de contexto
  4. Use I/O asíncrono: Para tareas intensivas en I/O, use procesamiento asíncrono para mejorar la eficiencia

Documentación detallada: Consulte workflow-optimization/parallel-execution.md


Cuarta Parte: Optimización del Pool de Variables

4.1 Evitar Almacenar Objetos Grandes

Problema: Almacenar objetos grandes (como archivos grandes, texto largo) en el pool de variables consume mucha memoria.

Estrategias de optimización:

# ❌ No recomendado: Almacenar objetos grandes
variables = {
    "archivo_grande": open("archivo_grande.pdf", "rb").read(),  # 10MB
    "texto_largo": "..." * 100000  # 1MB
}

# ✅ Recomendado: Almacenar referencia
variables = {
    "ruta_archivo": "/ruta/al/archivo_grande.pdf",
    "resumen_texto": resumir(texto_largo)  # Almacenar solo el resumen
}

4.2 Usar Referencias en Lugar de Copias

Problema: Copiar variables aumenta el uso de memoria y el tiempo de procesamiento.

Estrategias de optimización:

# ❌ No recomendado: Copiar variables
resultado = procesar_datos(datos.copy())

# ✅ Recomendado: Usar referencias
resultado = procesar_datos(datos)  # Operaciones de solo lectura usan referencia

4.3 Limpiar Variables de Manera Oportuna

Problema: Las variables que ya no se usan ocupan memoria.

Estrategias de optimización:

# En un nodo de código, limpiar variables que ya no se usan
def main(args):
    # Procesar datos
    datos_grandes = procesar_datos_grandes(args["input"])
    resultado = extraer_resultado(datos_grandes)

    # Limpiar objetos grandes
    del datos_grandes

    return {"resultado": resultado}

4.4 Gestión del Ámbito de Variables

Tipos de variables:

  • Variables del sistema: sys.query, sys.files, sys.conversation_id
  • Variables de nodo: {{#node_id.output#}}
  • Variables de entorno: Configuración y gestión de claves
  • Variables de iteración: Elemento actual e índice en el bucle

Recomendaciones de optimización:

  • Use el ámbito más pequeño posible
  • Evite la contaminación de variables globales
  • Libere variables temporales a tiempo

Documentación detallada: Consulte workflow-optimization/variable-pool.md


Quinta Parte: Procesamiento Paralelo y Respuestas en Streaming

5.1 Procesamiento Paralelo con Iteradores

Use el parámetro parallel_nums del iterador para procesar datos en arrays de manera paralela.

Ejemplo de configuración:

nodo_iteracion:
  type: iteration
  inputs:
    items: "{{#codigo_nodo.output.items#}}"
  config:
    parallel_nums: 5  # Procesar 5 elementos en paralelo

Comparación de rendimiento:

Cantidad de datosProcesamiento en serieProcesamiento paralelo (5)Mejora
10 elementos20s5s4x
50 elementos100s25s4x
100 elementos200s50s4x

5.2 Respuestas en Streaming

Use respuestas en streaming para mejorar la experiencia del usuario, reduciendo el tiempo hasta el primer byte (TTFB).

Implementación:

# Llamada a API con respuestas en streaming
respuesta = requests.post(
    "https://api.dify.ai/v1/workflows/run",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"inputs": {...}, "response_mode": "streaming"},
    stream=True
)

for linea in respuesta.iter_lines():
    if linea:
        evento = json.loads(linea)
        print(evento["data"])

Efecto de la optimización:

  • TTFB reducido en un 80%
  • Tiempo de respuesta percibido por el usuario reducido en un 50%

5.3 Procesamiento de Tareas Asíncronas

Use Celery para procesar tareas de larga duración de manera asíncrona.

Arquitectura:

Servidor API → Cola Celery → Pool de Workers → Ejecución de Tareas

Escenarios de aplicación:

  • Procesamiento de archivos grandes
  • Importación de datos por lotes
  • Llamadas a API de larga duración
  • Tareas programadas

5.4 Optimización de Arquitectura Basada en Eventos

Dify adopta una arquitectura basada en eventos, donde la ejecución de nodos genera un flujo de eventos.

Estrategias de optimización:

  • Use manejo de eventos no bloqueante
  • Procese las colas de eventos por lotes
  • Optimice la lógica de distribución de eventos

Documentación detallada: Consulte workflow-optimization/parallel-execution.md


Sexta Parte: Casos de Optimización de Rendimiento

Caso 1: Optimización de Consultas de Base de Datos (Problema N+1)

Escenario de aplicación:

  • El flujo de trabajo necesita consultar múltiples datos relacionados
  • Existen consultas cíclicas a la base de datos
  • El tiempo de ejecución aumenta linealmente con la cantidad de datos

Características del problema:

  • Número de consultas = 1 + N (N es el número de registros)
  • Las conexiones a la base de datos se establecen y cierran con frecuencia
  • Tiempo de ejecución excesivo

Estado antes de la optimización:

# Consultar lista de usuarios
usuarios = consultar("SELECT * FROM users LIMIT 100")

# Consultar pedidos para cada usuario (problema N+1)
for usuario in usuarios:
    pedidos = consultar(f"SELECT * FROM orders WHERE user_id = {usuario.id}")
    usuario.orders = pedidos
  • Número de consultas: 101 (1 + 100)
  • Tiempo de ejecución: 10.5s
  • Carga de la base de datos: Alta

Plan de optimización:

# Consultar todos los datos de una sola vez
usuarios = consultar("SELECT * FROM users LIMIT 100")
ids_usuarios = [usuario.id for usuario in usuarios]

# Consultar pedidos por lote
pedidos = consultar(f"SELECT * FROM orders WHERE user_id IN ({','.join(map(str, ids_usuarios))})")

# Asociar datos en memoria
pedidos_por_usuario = {}
for pedido in pedidos:
    if pedido.user_id not in pedidos_por_usuario:
        pedidos_por_usuario[pedido.user_id] = []
    pedidos_por_usuario[pedido.user_id].append(pedido)

for usuario in usuarios:
    usuario.orders = pedidos_por_usuario.get(usuario.id, [])

Efecto después de la optimización:

  • Número de consultas: 2 (reducción del 98%)
  • Tiempo de ejecución: 2.1s (reducción del 80%)
  • Carga de la base de datos: Baja

Beneficios esperados:

  • Corto plazo: Reducción del 80% en el tiempo de ejecución, menor carga en la base de datos
  • Largo plazo: Admite escalas de datos más grandes, mejora la escalabilidad del sistema
  • ROI: Costo de desarrollo 2 horas, ahorro mensual del 30% en costos de servidor

Caso 2: Optimización de Renderizado de Nodos a Gran Escala (100+ nodos)

Escenario de aplicación:

  • El flujo de trabajo contiene 100+ nodos
  • La renderización del frontend es lenta
  • El editor responde lentamente

Características del problema:

  • Tiempo de carga de la página > 5s
  • Retraso notable al arrastrar nodos
  • Alto uso de memoria del navegador

Estado antes de la optimización:

  • Número de nodos: 150
  • Tiempo de carga de la página: 8.5s
  • Uso de memoria: 500MB
  • Experiencia de usuario: Muy lenta

Plan de optimización:

  1. Desplazamiento virtual: Renderizar solo los nodos en el área visible
  2. Carga diferida de nodos: Cargar detalles de nodos según demanda
  3. Optimización con Canvas: Usar Canvas en lugar de renderizado DOM
  4. Optimización de gestión de estado: Reducir re-renderizados innecesarios

Efecto después de la optimización:

  • Tiempo de carga de la página: 2.1s (reducción del 75%)
  • Uso de memoria: 150MB (reducción del 70%)
  • Experiencia de usuario: Fluida

Beneficios esperados:

  • Corto plazo: Mejora significativa de la experiencia de usuario
  • Largo plazo: Admite el diseño de flujos de trabajo más complejos
  • ROI: Costo de desarrollo 1 semana, aumento del 40% en la satisfacción del usuario

Caso 3: Optimización de Rendimiento en la Eliminación de Logs de Flujo de Trabajo

Escenario de aplicación:

  • Necesidad de limpiar logs históricos periódicamente
  • Gran volumen de datos de logs (millones)
  • La operación de eliminación es lenta

Características del problema:

  • La eliminación bloquea la base de datos
  • Afecta las operaciones normales
  • Tiempo de ejecución impredecible

Estado antes de la optimización:

  • Cantidad de logs: 5 millones
  • Tiempo de eliminación: 45 minutos
  • Bloqueo de base de datos: Bloqueo prolongado de tablas
  • Impacto en el negocio: Grave

Plan de optimización:

# Antes de optimizar: Eliminación única
DELETE FROM workflow_logs WHERE created_at < '2024-01-01';

# Después de optimizar: Eliminación por lotes
tamano_lote = 10000
while True:
    eliminados = DELETE FROM workflow_logs
                  WHERE created_at < '2024-01-01'
                  LIMIT tamano_lote;

    if eliminados < tamano_lote:
        break

    # Breve pausa para liberar el bloqueo de la base de datos
    sleep(0.1)

Efecto después de la optimización:

  • Tiempo de eliminación: 50 minutos (ligeramente mayor, pero no bloquea el negocio)
  • Bloqueo de base de datos: Bloqueo breve (0.1s)
  • Impacto en el negocio: Ninguno

Beneficios esperados:

  • Corto plazo: El negocio no se ve afectado
  • Largo plazo: Mejora de la estabilidad de la base de datos
  • ROI: Costo de desarrollo 4 horas, se evitan pérdidas por interrupción del negocio

Caso 4: Integración de TiDB como Base de Datos Distribuida

Escenario de aplicación:

  • Gran volumen de datos de Knowledge (a nivel de TB)
  • Cuello de botella de rendimiento con PostgreSQL en una sola máquina
  • Necesidad de capacidad de escalado horizontal

Características del problema:

  • Tiempo de respuesta de consultas > 5s
  • Uso de CPU de la base de datos > 90%
  • No se puede seguir escalando

Estado antes de la optimización:

  • Base de datos: PostgreSQL en una sola máquina
  • Volumen de datos: 2TB
  • Tiempo de respuesta de consultas: 8.5s
  • Capacidad de escalado: Limitada

Plan de optimización:

  1. Migrar a TiDB: Base de datos SQL distribuida
  2. Optimización de índices vectoriales: Usar TiDB Vector para acelerar la recuperación
  3. Separación de lecturas y escrituras: Distribuir las solicitudes de lectura a múltiples réplicas
  4. Tablas particionadas: Particionar por tiempo para mejorar la eficiencia de las consultas

Efecto después de la optimización:

  • Tiempo de respuesta de consultas: 1.2s (reducción del 86%)
  • CPU de base de datos: 40% (reducción del 50%)
  • Capacidad de escalado: Admite 10x el volumen de datos

Beneficios esperados:

  • Corto plazo: Mejora significativa del rendimiento de consultas
  • Largo plazo: Admite el rápido crecimiento del negocio
  • ROI: Costo de migración 2 semanas, admite 10x de crecimiento del negocio

Caso 5: Despliegue de Alta Disponibilidad con Higress AI Gateway

Escenario de aplicación:

  • El entorno de producción necesita alta disponibilidad
  • Balanceo de carga de múltiples modelos LLM
  • Necesidad de capacidad de conmutación por error

Características del problema:

  • Riesgo de punto único de fallo
  • Llamadas a API de LLM inestables
  • Incapacidad para manejar picos de tráfico

Estado antes de la optimización:

  • Arquitectura: Instancia única de Dify
  • Disponibilidad: 95%
  • Tiempo de recuperación de fallos: 10 minutos
  • Picos de tráfico: No se pueden manejar

Plan de optimización:

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

Arquitectura:

Usuario → Higress Gateway → [Instancia Dify 1, Instancia Dify 2, Instancia Dify 3]
                ↓
      Balanceo de carga + Conmutación por error

Efecto después de la optimización:

  • Disponibilidad: 99.9%
  • Tiempo de recuperación de fallos: < 1 segundo (conmutación automática)
  • Picos de tráfico: Admite 10x el tráfico

Beneficios esperados:

  • Corto plazo: Mejora significativa de la estabilidad del sistema
  • Largo plazo: Admite aplicaciones críticas para el negocio
  • ROI: Costo de despliegue 3 días, se evitan pérdidas por interrupción del negocio

Séptima Parte: Pruebas y Monitorización de Rendimiento

7.1 Sistema de Indicadores de Rendimiento

Indicadores de ejecución de flujo de trabajo:

IndicadorValor objetivoDescripción
Tiempo de ejecución promedio< 2sTiempo completo de ejecución del flujo de trabajo
Tiempo de ejecución P95< 5sTiempo de ejecución del 95% de las solicitudes
Tiempo de ejecución P99< 10sTiempo de ejecución del 99% de las solicitudes
Tasa de éxito de nodos> 99%Proporción de nodos ejecutados con éxito
Tasa de éxito de llamadas a API> 99.5%Tasa de éxito de llamadas a API externas
Capacidad de procesamiento concurrente> 100 QPSNúmero de solicitudes procesadas por segundo

Indicadores de uso de recursos:

IndicadorValor objetivoDescripción
Uso de CPU< 70%Uso promedio de CPU
Uso de memoria< 80%Uso promedio de memoria
Conexiones de base de datos< 80%Uso del pool de conexiones
Memoria de Redis< 70%Uso de memoria de Redis

Indicadores de costos:

IndicadorValor objetivoDescripción
Costo de uso de tokens< PresupuestoCosto de API de LLM
Costo de infraestructura< PresupuestoCosto de servidores, base de datos
Costo por usuarioEn disminución continuaCosto por usuario

7.2 Herramientas de Monitorización

Monitorización LLMOps:

# Monitorización integrada de Dify
from dify import Monitor

monitor = Monitor()

# Registrar ejecución de flujo de trabajo
monitor.log_execucion_flujo_trabajo(
    workflow_id="xxx",
    tiempo_ejecucion=2.5,
    numero_nodos=10,
    uso_tokens=1500,
    costo=0.003
)

# Consultar estadísticas
stats = monitor.obtener_estadisticas_flujo_trabajo(
    workflow_id="xxx",
    rango_tiempo="7d"
)

Seguimiento de ejecución:

  • Historial de ejecución de flujos de trabajo
  • Estadísticas de pasos de ejecución de nodos
  • Estadísticas de uso de LLM
  • Registros de errores y reintentos

Monitorización de recursos:

# Prometheus + Grafana
# Monitorizar CPU, memoria, red, disco

# Ejemplo de consulta
rate(dify_workflow_execution_total[5m])  # Tasa de ejecución de flujos de trabajo
histogram_quantile(0.95, dify_workflow_duration_seconds)  # Tiempo de ejecución P95

7.3 Métodos de Prueba de Rendimiento

Pruebas de carga:

# Usar Locust para pruebas de carga
from locust import HttpUser, task, between

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

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

# Ejecutar prueba
# locust -f load_test.py --users 100 --spawn-rate 10

Pruebas de estrés:

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

Benchmark:

# Prueba de benchmark de rendimiento
import time

def benchmark_flujo_trabajo(workflow_id, iteraciones=100):
    tiempos = []
    for i in range(iteraciones):
        inicio = time.time()
        ejecutar_flujo_trabajo(workflow_id)
        fin = time.time()
        tiempos.append(fin - inicio)

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

7.4 Herramientas de Análisis de Rendimiento

Python Profiler:

import cProfile
import pstats

# Perfilado de código
def perfil_funcion():
    profiler = cProfile.Profile()
    profiler.enable()
    # Código a perfilar
    resultado = funcion_lenta()
    profiler.disable()

    # Análisis de resultados
    stats = pstats.Stats(profiler)
    stats.sort_stats('cumtime').print_stats(10)

Documentación detallada: Consulte performance-monitoring.md


Referencias Rápidas

CategoríaDocumentaciónEnlace
Guía completaGuía de optimización de flujo de trabajoworkflow-optimization/README.md
Estructura del grafoDiseño de estructura del grafoworkflow-optimization/graph-structure.md
Ejecución en paraleloEstrategias de ejecución en paraleloworkflow-optimization/parallel-execution.md
Pool de variablesGestión del pool de variablesworkflow-optimization/variable-pool.md
Optimización de LLMEstrategias de optimización de LLMllm-optimization/
MonitorizaciónHerramientas de monitorización de rendimientoperformance-monitoring.md
MantenimientoGuía de mantenimiento de Difymaintenance-guide.md

Este SKILL se actualiza continuamente. Si tiene sugerencias de optimización, no dude en contribuir.

Individual skills in this repo

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

Skills relacionados