Aller au contenu principal

Déployer des workers Mastra

Exécutez les workers Mastra comme processus distincts afin de dimensionner indépendamment de l’API l’orchestration, la planification et les tâches d’arrière-plan. Ce guide décrit un déploiement entièrement séparé avec Docker Compose ou Kubernetes.

info

Ce guide couvre la séparation des workers dans leurs propres conteneurs. Si vous avez seulement besoin que les workers s’exécutent dans le même processus que l’API, consultez Workers. Aucune configuration supplémentaire n’est nécessaire.

Avant de commencer
Lien direct vers Avant de commencer

Vous aurez besoin de :

attention

Le PubSub en mémoire par défaut ne peut pas transmettre des événements entre processus. Vous devez configurer un backend PubSub distribué avant de séparer les workers dans des conteneurs distincts.

Configurer l’infrastructure partagée
Lien direct vers Configurer l’infrastructure partagée

Dirigez l’instance Mastra vers un backend PubSub distribué et une base de données partagée. Utilisez des variables d’environnement afin que la même image s’exécute dans chaque conteneur.

src/mastra/index.ts
import { Mastra } from '@mastra/core/mastra'
import { RedisStreamsPubSub } from '@mastra/redis-streams'
import { PostgresStore } from '@mastra/pg'

export const mastra = new Mastra({
storage: new PostgresStore({
connectionString: process.env.DATABASE_URL!,
}),
pubsub: new RedisStreamsPubSub({
url: process.env.REDIS_URL!,
}),
})

Tout backend de stockage pris en charge convient. Remplacez l’adaptateur de stockage par celui de votre base de données préférée.

Déployer
Lien direct vers Déployer

  1. Compilez votre application Mastra. La sortie s’exécute dans chaque conteneur.

    mastra build

    Cette opération produit un répertoire .mastra/output/ autonome. Consultez Déployer un serveur Mastra pour les détails sur la sortie de compilation.

  2. Créez un Dockerfile qui copie la sortie précompilée et installe les dépendances de production :

    app/Dockerfile
    FROM node:22-alpine

    WORKDIR /app

    COPY .mastra/output/package.json .mastra/output/.npmrc* ./
    RUN npm install --omit=dev

    COPY .mastra/output/ .

    EXPOSE 4111
    CMD ["node", "index.mjs"]
  3. Définissez la topologie entièrement séparée. Cette configuration exécute six services : une base de données, un backend PubSub, le serveur API et trois workers. Chaque worker exécute la même image avec une valeur MASTRA_WORKERS différente pour contrôler le worker qui démarre.

    L’API définit MASTRA_WORKERS: "false" pour désactiver tout traitement d’événements. Le worker d’orchestration définit MASTRA_STEP_EXECUTION_URL pour diriger les requêtes d’exécution d’étapes vers l’URL interne de l’API. Consultez l’URL d’exécution d’étapes pour plus de détails.

    Tous les services partagent un MASTRA_WORKER_AUTH_TOKEN. Les workers incluent ce jeton dans leurs requêtes à l’API afin qu’elle puisse vérifier que l’appelant est un service interne de confiance. Consultez l’authentification des workers pour plus de détails.

    docker-compose.yml
    services:
    postgres:
    image: postgres:16-alpine
    environment:
    POSTGRES_USER: mastra
    POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    POSTGRES_DB: mastra
    ports:
    - '5432:5432'
    volumes:
    - pgdata:/var/lib/postgresql/data
    healthcheck:
    test: ['CMD-SHELL', 'pg_isready -U mastra']
    interval: 5s
    timeout: 3s
    retries: 5

    redis:
    image: redis:7-alpine
    ports:
    - '6379:6379'
    healthcheck:
    test: ['CMD', 'redis-cli', 'ping']
    interval: 5s
    timeout: 3s
    retries: 5

    api:
    build: ./app
    ports:
    - '4111:4111'
    environment:
    DATABASE_URL: postgres://mastra:${POSTGRES_PASSWORD}@postgres:5432/mastra
    REDIS_URL: redis://redis:6379
    MASTRA_WORKERS: 'false'
    MASTRA_WORKER_AUTH_TOKEN: ${MASTRA_WORKER_AUTH_TOKEN}
    depends_on:
    postgres:
    condition: service_healthy
    redis:
    condition: service_healthy
    healthcheck:
    test: ['CMD', 'wget', '-qO-', 'http://localhost:4111/api/agents']
    interval: 5s
    timeout: 3s
    retries: 5

    orchestration-worker:
    build: ./app
    environment:
    DATABASE_URL: postgres://mastra:${POSTGRES_PASSWORD}@postgres:5432/mastra
    REDIS_URL: redis://redis:6379
    MASTRA_WORKERS: orchestration
    MASTRA_STEP_EXECUTION_URL: http://api:4111/api
    MASTRA_WORKER_AUTH_TOKEN: ${MASTRA_WORKER_AUTH_TOKEN}
    depends_on:
    api:
    condition: service_healthy

    scheduler-worker:
    build: ./app
    environment:
    DATABASE_URL: postgres://mastra:${POSTGRES_PASSWORD}@postgres:5432/mastra
    REDIS_URL: redis://redis:6379
    MASTRA_WORKERS: scheduler
    MASTRA_WORKER_AUTH_TOKEN: ${MASTRA_WORKER_AUTH_TOKEN}
    depends_on:
    api:
    condition: service_healthy

    background-task-worker:
    build: ./app
    environment:
    DATABASE_URL: postgres://mastra:${POSTGRES_PASSWORD}@postgres:5432/mastra
    REDIS_URL: redis://redis:6379
    MASTRA_WORKERS: backgroundTasks
    MASTRA_WORKER_AUTH_TOKEN: ${MASTRA_WORKER_AUTH_TOKEN}
    depends_on:
    api:
    condition: service_healthy

    volumes:
    pgdata:

    Créez un fichier .env à côté de votre docker-compose.yml :

    .env
    POSTGRES_PASSWORD=your-secure-password
    MASTRA_WORKER_AUTH_TOKEN=your-shared-secret-token
    remarque

    N’oubliez pas de définir les autres variables d’environnement nécessaires à votre application, par exemple la clé API de votre fournisseur de modèles.

  4. Vérifiez que la pile est en cours d’exécution et que l’API répond :

    docker compose up -d
    docker compose ps
    curl http://localhost:4111/api/agents

URL d’exécution d’étapes
Lien direct vers URL d’exécution d’étapes

Dans un déploiement entièrement séparé, le worker d’orchestration s’exécute dans un conteneur distinct de l’API. Lorsqu’il traite un événement de Workflow, il délègue l’exécution des étapes à l’API via HTTP.

Définissez MASTRA_STEP_EXECUTION_URL sur l’URL interne de l’API, avec le préfixe /api :

MASTRA_STEP_EXECUTION_URL=http://api:4111/api

Le worker d’orchestration envoie une requête POST à ${MASTRA_STEP_EXECUTION_URL}/workflows/:workflowId/runs/:runId/steps/execute pour chaque étape. L’API résout le Workflow et exécute l’étape localement.

Sans cette variable, le worker d’orchestration tente d’exécuter les étapes dans le processus. Cela fonctionne lorsque le worker s’exécute avec l’API, mais échoue dans les déploiements séparés, où il n’a pas accès au runtime Mastra complet.

Mise à l’échelle
Lien direct vers Mise à l’échelle

Les workers d’orchestration et de tâches d’arrière-plan peuvent être mis à l’échelle horizontalement en toute sécurité. Les groupes de consommateurs PubSub distribuent les événements entre les instances : chaque événement n’est donc traité qu’une fois.

docker compose up -d --scale orchestration-worker=3
docker compose up -d --scale background-task-worker=2

L’API peut également être mise à l’échelle horizontalement derrière un équilibreur de charge.

Ne mettez pas à l’échelle le worker planificateur. Exécutez exactement une instance. Plusieurs planificateurs qui interrogent le même stockage déclenchent des événements dupliqués pour une même planification.

Récupération après incident
Lien direct vers Récupération après incident

Les workers se remettent d’un incident, car le backend PubSub distribué conserve les événements non acquittés :

  • Worker d’orchestration : les événements en attente restent dans le backend PubSub. Au redémarrage, le worker reprend là où il s’était arrêté.
  • Worker planificateur : aucun événement n’est manqué de façon permanente. Au redémarrage, le planificateur calcule l’heure du prochain déclenchement à partir de l’heure actuelle, et non de l’endroit où il s’était arrêté.
  • API durant l’exécution d’une étape : la requête HTTP du worker d’orchestration échoue. L’événement est rejeté puis renvoyé à la tentative suivante.
attention

Si l’API se bloque alors qu’une étape est déjà en cours d’exécution, par exemple au milieu d’une veille, le travail de cette étape est perdu. L’exécution de Workflow peut rester bloquée dans l’état running. Mastra ne dispose pas encore d’une récupération automatique fondée sur un délai d’attente pour ce scénario.