Mises à niveau sans temps d'arrêt
bext -server prend en charge les mises à niveau binaires gracieuses sans interruption de connexion. Le processus en cours d'exécution confie ses sockets d'écoute à un nouveau processus, draine les requêtes en cours et se termine, le tout sans une seule requête ayant échoué.
Démarrage rapide#
# 1. Install the new binary (atomic replace)
curl -fsSL https://bext.dev/install | sh
# 2. Trigger zero-downtime upgrade
bext upgrade
C'est ça. L'ancien processus termine de répondre à toutes les demandes en cours tandis que le nouveau processus commence immédiatement à accepter de nouvelles connexions sur le même port.
Comment ça marche#
La mise à niveau utilise l'héritage FD du socket — la même technique que nginx utilise pour les mises à niveau binaires.
Operator Old process New process
│ │ │
├── bext upgrade ──────────►│ │
│ (sends SIGUSR2) │ │
│ ├── fork+exec ────────────►│
│ │ BEXT_UPGRADE_FDS=3,4 │
│ │ BEXT_UPGRADE_OLD_PID=X │
│ │ ├── bind inherited FDs
│ │ ├── start accepting
│ │◄── SIGQUIT ──────────────┤ (ready)
│ ├── stop accepting │
│ ├── drain 30s │
│ ├── exit(0) │
│ × │
Pas à pas#
- SIGUSR2 est envoyé au serveur bext en cours d'exécution (via
bext upgradeoukill -USR2) - Le processus en cours d'exécution forge et d'exécution le nouveau binaire sur son propre chemin
- Les descripteurs de fichiers de socket d'écoute sont transmis via la variable d'environnement
BEXT_UPGRADE_FDS - Le nouveau processus se lie aux FD hérités de — pas de conflit de port, pas de
EADDRINUSE - Une fois le nouveau processus prêt, il envoie SIGQUIT à l'ancien processus
- L'ancien processus cesse d'accepter les nouvelles connexions et draine les requêtes en vol (délai d'expiration de 30 s)
- L'ancien processus se termine proprement
Au cours des étapes 4 à 6, , les deux processus répondent simultanément aux requêtes — il n'y a jamais un moment où aucun processus n'écoute.
Référence CLI#
bext upgrade#
Envoie SIGUSR2 au processus serveur bext en cours d'exécution.
# Basic: re-exec current binary (e.g., after curl install)
bext upgrade
# Replace binary first, then upgrade
bext upgrade --binary /path/to/new-bext-server
# Specify PID file location
bext upgrade --pid-file /run/bext.pid
Indicateurs :
| Drapeau | Défaut | Description |
|---|---|---|
--binary |
(aucun) | Chemin vers le nouveau binaire. Remplace atomiquement le binaire en cours d'exécution avant d'envoyer SIGUSR2. |
--pid-file |
Détection automatique | Chemin d'accès au fichier PID. Recherche /run/bext.pid, /run/nginx.pid, /tmp/bext.pid. |
Signal manuel#
Si vous préférez le contrôle manuel :
# Find the PID
cat /run/bext.pid
# Send upgrade signal
kill -USR2 $(cat /run/bext.pid)
Intégration Systemd#
La mise à niveau de bext fonctionne de manière transparente avec systemd. Le fichier de service ne nécessite aucune modification : bext upgrade gère tout :
# /etc/systemd/system/bext.service
[Unit]
Description=bext application server
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/bext-server run
ExecReload=/usr/local/bin/bext-server upgrade
Restart=on-failure
PIDFile=/run/bext.pid
[Install]
WantedBy=multi-user.target
Avec cette configuration, systemctl reload bext déclenche une mise à niveau sans temps d'arrêt.
Variables d'environnement#
Ceux-ci sont définis automatiquement lors de la mise à niveau ; vous n'avez pas besoin de les définir manuellement.
| Variable | Description |
|---|---|
BEXT_UPGRADE_FDS |
Liste séparée par des virgules des descripteurs de fichiers de socket hérités |
BEXT_UPGRADE_OLD_PID |
PID du processus parent à signaler lorsqu'il est prêt |
Référence des signaux#
| Signal | Effet |
|---|---|
SIGUSR2 |
Démarrer la mise à niveau sans temps d'arrêt (fork+exec nouveau binaire) |
SIGQUIT |
Arrêt progressif avec vidange de 30 s (envoyé par un nouveau processus) |
SIGHUP |
Rechargez à chaud le bundle V8 et effacez les caches (pas de changement binaire) |
SIGTERM |
Arrêt immédiat |
Délai de vidange#
L’ancien processus attendait 30 secondes pour que les demandes en cours soient terminées. Les demandes qui prennent plus de temps sont terminées. Ce délai d'attente couvre :
- Rendus SSR de longue durée
- Connexions WebSocket (gracieusement fermées)
- Flux d'événements SSE (événement final + clôture)
- Demandes de travail PHP en attente
Comportement du cache lors de la mise à niveau#
Lors de la mise à niveau, le nouveau processus démarre avec les caches froids (ISR, locataire, compression). Cela signifie:
- Les premières requêtes après la mise à niveau peuvent être plus lentes (manque de cache → rendu → remplissage du cache)
- Le mécanisme ISR périmé pendant la revalidation garantit que les utilisateurs voient toujours le contenu mis en cache pendant que les caches sont chauds
- Le cache du locataire est rempli à la première demande par nom d'hôte
- Le cache de compression se remplit en quelques secondes sous charge
Si vous utilisez le cache Redis L2 activé, le contenu mis en cache survit à la mise à niveau puisque Redis est externe.
Automatisation des mises à niveau#
Mise à jour automatique basée sur Cron#
# /etc/cron.d/bext-upgrade
0 3 * * * root curl -fsSL https://bext.dev/install | sh && bext upgrade
Pipeline CI/CD#
# .github/workflows/upgrade.yml
- name: Upgrade bext
run: |
ssh deploy@server 'curl -fsSL https://bext.dev/install | sh && bext upgrade'
Déclenché par un webhook#
Utilisez le webhook git déployer de bext pour déclencher les mises à niveau lors du push :
# bext.config.toml
[git_deploy]
enabled = true
secret = "your-webhook-secret"
on_push = "curl -fsSL https://bext.dev/install | sh && bext upgrade"
Dépannage#
Échec de la mise à niveau : "Impossible de résoudre son propre binaire"#
Le processus ne parvient pas à trouver son propre chemin exécutable. Cela se produit dans certains environnements conteneurisés. Définissez explicitement le chemin binaire :
bext upgrade --binary /usr/local/bin/bext-server
Échec de la mise à niveau : « échec de la génération d'un nouveau processus »#
Vérifiez les autorisations des fichiers sur le binaire :
ls -la $(which bext-server)
# Should be: -rwxr-xr-x
L'ancien processus ne s'est pas terminé après 30 s#
Le délai d'attente de vidange a expiré alors que les demandes étaient toujours en cours. Vérifiez :
- Requêtes de très longue durée (augmenter le délai d'attente si nécessaire)
- Connexions WebSocket qui ne se sont pas fermées
- Processus de travail PHP bloqués
Conflit de port au démarrage#
Si vous voyez EADDRINUSE lors de la mise à niveau, l'héritage FD a échoué. Cela peut arriver si :
- Le binaire a été compilé sans le module de mise à niveau
- La variable d'environnement
BEXT_UPGRADE_FDSa été perdue (vérifiez votre superviseur de processus)
Si vous utilisez le cache Redis L2 activé, le cache rempli survit à la mise à niveau binaire : seuls les caches L1 et de compression en cours démarrent à froid. Sous un trafic modéré, les caches se réchauffent en quelques secondes.
En rapport#
- Mise à l'échelle — arrêt progressif, délai d'expiration de vidange et comportement du cache Redis L2
- Invalidation et redémarrages — surfaces par site et par cache pour le plus petit rayon d'explosion
- Déploiement : générateurs —
bext systemd genavec--socket-activationpour le chemin de mise à niveau systemd - Surveillance : point de terminaison de vérification de l'état utilisé par les équilibreurs de charge lors des redémarrages progressifs
- Dépannage — problèmes courants après la mise à niveau