anchorage_layer_simple/features/api-anchorage-optimisation-bitcoind-rpc.md
ncantu 0960e43a45 Optimisation mémoire api-anchorage avec base de données SQLite
**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)
2026-01-27 21:12:22 +01:00

299 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 fois
- `listunspent` - 1 fois (via fetch direct)
- `createrawtransaction` - 1 fois
- `signrawtransactionwithwallet` - 1 fois
- `sendrawtransaction` - 1 fois
- `getTransaction()` - 1 fois
- `getBlockchainInfo()` - 1 fois
- `getRawTransaction()` - **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 fois
- `getBlockHash()` - **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):**
```nginx
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`
```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:**
```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 `/health` toutes 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:**
```bash
# 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:**
```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:**
```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)
1. **Cache HTTP pour `/health`** - Impact immédiat si le health check est appelé fréquemment
2. **Rate limiting pour `/api/anchor/verify`** - Réduction drastique des appels RPC coûteux
3. **Augmenter `BITCOIN_RPC_TIMEOUT`** - Réduction des erreurs et reconnexions
### Priorité moyenne
4. **Optimiser la configuration bitcoind RPC** - Amélioration générale des performances
5. **Rate limiting général pour `/api/anchor`** - Protection contre les pics de trafic
### Priorité basse
6. **Monitoring des appels RPC** - Visibilité et optimisation future
7. **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:**
1. Identifier le fichier de configuration nginx pour `certificator.4nkweb.com`
2. Ajouter la configuration de cache pour `/health`
3. Tester avec `curl -I https://certificator.4nkweb.com/health`
4. Vérifier le header `X-Cache-Status`
### 2. Augmenter le timeout RPC
**Fichier:** `/home/ncantu/Bureau/code/bitcoin/api-anchorage/.env`
**Modification:**
```env
BITCOIN_RPC_TIMEOUT=60000
```
**Redémarrage:**
```bash
systemctl restart anchorage-api.service
```
### 3. Rate limiting nginx
**Fichier:** Configuration nginx sur le proxy
**Étapes:**
1. Ajouter les zones de rate limiting
2. Appliquer aux endpoints appropriés
3. Tester avec des requêtes multiples
4. Ajuster les limites selon les besoins
### 4. Optimisation bitcoind
**Fichier:** Configuration bitcoin dans le conteneur Docker
**Étapes:**
1. Identifier le fichier `bitcoin.conf` du conteneur
2. Ajouter les paramètres d'optimisation
3. Redémarrer le conteneur bitcoin-signet-instance
4. Vérifier les performances
## Modalités d'analyse
### Métriques à surveiller
**Avant optimisation:**
```bash
# 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**
```bash
# 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**
```bash
# 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()` dans `createAnchorTransaction` (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.