**Motivations:** - Réduction drastique de la consommation mémoire lors des ancrages - Élimination du chargement de 173k+ UTXOs à chaque requête - Stabilisation de la mémoire système sous charge élevée (50+ ancrages/minute) **Root causes:** - api-anchorage chargeait tous les UTXOs (173k+) via listunspent RPC à chaque ancrage - Filtrage et tri de 173k+ objets en mémoire pour sélectionner un seul UTXO - Croissance mémoire de ~16 MB toutes les 12 secondes avec 50 ancrages/minute - Saturation mémoire système en quelques minutes **Correctifs:** - Création du module database.js pour gérer la base de données SQLite partagée - Remplacement de listunspent RPC par requête SQL directe avec LIMIT 1 - Sélection directe d'un UTXO depuis la DB au lieu de charger/filtrer 173k+ objets - Marquage des UTXOs comme dépensés dans la DB après utilisation - Fermeture propre de la base de données lors de l'arrêt **Evolutions:** - Utilisation de la base de données SQLite partagée avec signet-dashboard - Réduction mémoire de 99.999% (173k+ objets → 1 objet par requête) - Amélioration des performances (requête SQL indexée vs filtrage en mémoire) - Optimisation mémoire de signet-dashboard (chargement UTXOs seulement si nécessaire) - Monitoring de lockedUtxos dans api-anchorage pour détecter les fuites - Nettoyage des intervalles frontend pour éviter les fuites mémoire **Pages affectées:** - api-anchorage/src/database.js (nouveau) - api-anchorage/src/bitcoin-rpc.js - api-anchorage/src/server.js - api-anchorage/package.json - signet-dashboard/src/bitcoin-rpc.js - signet-dashboard/public/app.js - features/optimisation-memoire-applications.md (nouveau) - features/api-anchorage-optimisation-base-donnees.md (nouveau)
9.3 KiB
Optimisation api-anchorage pour réduire la charge sur bitcoind
Date: 2026-01-27 Auteur: Équipe 4NK
Objectif
Réduire la charge RPC de api-anchorage sur bitcoind sans modifier le code de l'application, uniquement via des optimisations de configuration et d'infrastructure.
Analyse de la consommation RPC
Appels RPC identifiés
1. Health Check (/health)
- Fréquence: À chaque requête GET
/health - Appels RPC:
getNetworkInfo()getBlockchainInfo()
- Impact: 2 appels RPC par health check
2. Création de transaction d'ancrage (POST /api/anchor/document)
- Appels RPC par transaction:
getNewAddress()- 9 fois (1 anchor + 7 provisioning + 1 change)getBalance()- 1 foislistunspent- 1 fois (via fetch direct)createrawtransaction- 1 foissignrawtransactionwithwallet- 1 foissendrawtransaction- 1 foisgetTransaction()- 1 foisgetBlockchainInfo()- 1 foisgetRawTransaction()- plusieurs fois (pour calculer les frais, 1 par input)
- Total: ~15-20 appels RPC par transaction d'ancrage
3. Vérification d'ancrage (POST /api/anchor/verify)
- Appels RPC:
getBlockchainInfo()- 1 foisgetBlockHash()- 100 fois (recherche dans les 100 derniers blocs)getBlock()- 100 fois (un par bloc)getRawTransaction()- plusieurs centaines (une par transaction dans chaque bloc)
- Impact: Très élevé si beaucoup de transactions par bloc
Optimisations possibles (sans modifier le code)
1. Cache HTTP pour le health check
Problème: Le health check fait 2 appels RPC à chaque requête.
Solution: Mettre en cache la réponse du health check côté nginx.
Configuration nginx (sur le proxy):
location /health {
proxy_pass http://192.168.1.103:3010/health;
proxy_cache_valid 200 30s; # Cache 30 secondes
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
}
Impact: Réduction de 95%+ des appels RPC pour le health check si appelé fréquemment.
2. Augmenter le timeout RPC
Configuration actuelle: BITCOIN_RPC_TIMEOUT=30000 (30 secondes)
Recommandation: Augmenter à 60000ms (60 secondes) pour éviter les timeouts lors de pics de charge.
Fichier: .env
BITCOIN_RPC_TIMEOUT=60000
Impact: Réduction des erreurs et reconnexions lors de pics de charge.
3. Optimiser la configuration bitcoind RPC
Configuration bitcoin.conf:
# Augmenter le nombre de threads RPC
rpcthreads=16
# Augmenter la taille du cache RPC
rpcmaxconnections=128
# Timeout RPC plus long
rpcservertimeout=60
# Désactiver les fonctionnalités non utilisées
disablewallet=0 # Nécessaire pour api-anchorage
txindex=1 # Nécessaire pour les vérifications
Impact: Meilleure gestion des requêtes concurrentes, réduction de la latence.
4. Limiter la fréquence des health checks externes
Problème: Si un monitoring externe appelle /health très fréquemment (toutes les 5-10 secondes), cela génère beaucoup d'appels RPC.
Solution:
- Configurer le monitoring pour appeler
/healthtoutes les 30-60 secondes au lieu de 5-10 secondes - Utiliser le cache nginx (voir point 1) pour les appels plus fréquents
Impact: Réduction proportionnelle des appels RPC.
5. Pool de connexions HTTP keep-alive
Problème: La bibliothèque bitcoin-core peut créer de nouvelles connexions pour chaque requête.
Solution: Vérifier que bitcoind accepte les connexions keep-alive (par défaut activé).
Vérification:
# Vérifier que bitcoind accepte keep-alive
docker exec bitcoin-signet-instance bitcoin-cli -signet getnetworkinfo | grep -i keep
Impact: Réduction de la surcharge de connexions TCP.
6. Limiter les requêtes concurrentes
Problème: Si plusieurs requêtes d'ancrage arrivent simultanément, elles font toutes des appels RPC en parallèle.
Solution: Mettre en place un rate limiting côté nginx pour limiter le nombre de requêtes simultanées.
Configuration nginx:
limit_req_zone $binary_remote_addr zone=anchor_api:10m rate=10r/s;
location /api/anchor {
limit_req zone=anchor_api burst=5 nodelay;
proxy_pass http://192.168.1.103:3010;
}
Impact: Réduction de la charge lors de pics de trafic, meilleure stabilité.
7. Optimiser la recherche dans verifyAnchor
Problème: verifyAnchor recherche dans les 100 derniers blocs, ce qui génère des centaines d'appels RPC.
Note: Cette optimisation nécessiterait une modification du code pour réduire le nombre de blocs recherchés ou utiliser un index. Non applicable sans modification du code.
Alternative: Limiter l'accès à l'endpoint /api/anchor/verify via rate limiting strict.
Configuration nginx:
limit_req_zone $binary_remote_addr zone=verify_api:10m rate=1r/s;
location /api/anchor/verify {
limit_req zone=verify_api burst=2 nodelay;
proxy_pass http://192.168.1.103:3010;
}
Impact: Réduction drastique des appels RPC pour la vérification.
8. Monitoring et alertes
Solution: Mettre en place un monitoring des appels RPC pour identifier les pics de charge.
Métriques à surveiller:
- Nombre d'appels RPC par seconde
- Latence des appels RPC
- Taux d'erreur RPC
- Utilisation CPU/mémoire de bitcoind
Impact: Identification proactive des problèmes de performance.
Recommandations prioritaires
Priorité haute (impact immédiat)
- Cache HTTP pour
/health- Impact immédiat si le health check est appelé fréquemment - Rate limiting pour
/api/anchor/verify- Réduction drastique des appels RPC coûteux - Augmenter
BITCOIN_RPC_TIMEOUT- Réduction des erreurs et reconnexions
Priorité moyenne
- Optimiser la configuration bitcoind RPC - Amélioration générale des performances
- Rate limiting général pour
/api/anchor- Protection contre les pics de trafic
Priorité basse
- Monitoring des appels RPC - Visibilité et optimisation future
- Limiter la fréquence des health checks externes - Si applicable
Modalités de déploiement
1. Cache HTTP pour health check
Fichier: Configuration nginx sur le proxy (192.168.1.100)
Étapes:
- Identifier le fichier de configuration nginx pour
certificator.4nkweb.com - Ajouter la configuration de cache pour
/health - Tester avec
curl -I https://certificator.4nkweb.com/health - Vérifier le header
X-Cache-Status
2. Augmenter le timeout RPC
Fichier: /home/ncantu/Bureau/code/bitcoin/api-anchorage/.env
Modification:
BITCOIN_RPC_TIMEOUT=60000
Redémarrage:
systemctl restart anchorage-api.service
3. Rate limiting nginx
Fichier: Configuration nginx sur le proxy
Étapes:
- Ajouter les zones de rate limiting
- Appliquer aux endpoints appropriés
- Tester avec des requêtes multiples
- Ajuster les limites selon les besoins
4. Optimisation bitcoind
Fichier: Configuration bitcoin dans le conteneur Docker
Étapes:
- Identifier le fichier
bitcoin.confdu conteneur - Ajouter les paramètres d'optimisation
- Redémarrer le conteneur bitcoin-signet-instance
- Vérifier les performances
Modalités d'analyse
Métriques à surveiller
Avant optimisation:
# Compter les appels RPC par minute
docker exec bitcoin-signet-instance bitcoin-cli -signet getrpcinfo
# Surveiller la charge CPU de bitcoind
top -p $(pgrep -f bitcoind)
# Surveiller les logs d'api-anchorage
journalctl -u anchorage-api.service -f
Après optimisation:
- Comparer le nombre d'appels RPC
- Comparer la latence des requêtes
- Comparer l'utilisation CPU/mémoire de bitcoind
- Vérifier le taux de cache hit pour
/health
Tests de charge
Test 1: Health check fréquent
# Avant cache
for i in {1..100}; do curl -s https://certificator.4nkweb.com/health > /dev/null; done
# Après cache (vérifier X-Cache-Status: HIT)
for i in {1..100}; do curl -sI https://certificator.4nkweb.com/health | grep X-Cache-Status; done
Test 2: Vérification d'ancrage
# Tester avec rate limiting
for i in {1..10}; do
curl -X POST https://certificator.4nkweb.com/api/anchor/verify \
-H "Content-Type: application/json" \
-d '{"hash":"0000000000000000000000000000000000000000000000000000000000000000"}' \
-w "\nTime: %{time_total}s\n"
done
Impact attendu
Réduction des appels RPC
- Health check: 95%+ de réduction si appelé fréquemment (avec cache)
- Verify anchor: 90%+ de réduction (avec rate limiting à 1 req/s)
- Create anchor: 10-20% de réduction (avec rate limiting et timeout optimisé)
Amélioration des performances
- Latence RPC: Réduction de 20-30% avec configuration bitcoind optimisée
- Stabilité: Réduction des erreurs de timeout et reconnexions
- Charge CPU bitcoind: Réduction de 30-50% lors de pics de trafic
Limitations
Ces optimisations ne peuvent pas résoudre:
- Le nombre élevé d'appels
getNewAddress()danscreateAnchorTransaction(9 appels par transaction) - La recherche exhaustive dans
verifyAnchor(100 blocs × transactions par bloc) - Les appels
getRawTransaction()multiples pour le calcul des frais
Pour ces optimisations, une modification du code serait nécessaire.