## Introduction

Apache NiFi est une plateforme flexible pour créer des pipelines de déplacement et de transformation de données. Cette flexibilité peut masquer les goulots d'étranglement de performance jusqu'à la première pointe de charge en production. Ce guide montre comment optimiser NiFi avec un workflow sûr et mesurable, reproductible dans différents environnements. Vous apprendrez à inventorier votre environnement, choisir des changements ciblés, valider les résultats et récupérer rapidement. Les exemples utilisent des chiffres hypothétiques pour que vous puissiez les adapter en confiance à vos propres flux.

Vous verrez des étapes concrètes pour le dimensionnement de la JVM et des repositories, la stratégie de backpressure, la concurrence des processeurs, le batching et la validation. Tout au long, nous nous concentrons sur des résultats observables : âge des files d'attente, latence de bout en bout, débit et stabilité. Les conseils s'appliquent que vous intégriez Kafka, HDFS, S3, des bases de données, Spark ou Airflow.

## Inventaire de la version et de l'environnement

Avant de changer quoi que ce soit, capturez une ligne de base. Cela guide les attentes et simplifie le rollback.

Enregistrez ces faits :

- Version de NiFi et version de Java : exemple : NiFi 1.20.x sur Java 11.

- Topologie : standalone ou cluster, nombre de nœuds, rôles des nœuds.

- Matériel par nœud : cœurs CPU, RAM, types de disques et points de montage pour les repositories content, flowfile et provenance.

- Réseau : vitesse NIC, latence inter-nœuds, bande passante vers Kafka/HDFS/Bases de données.

- Paramètres OS pertinents pour l'I/O (type de système de fichiers, drapeaux noatime), configuration du swap et limites de fichiers ouverts.

- Caractéristiques du flux : taille moyenne et p95 des FlowFiles, enregistrements par FlowFile, burstiness (requêtes/seconde), volume crête vs régime permanent.

- Systèmes externes : partitions et réplication des topics Kafka, latence HDFS/S3, taille du pool de connexions base de données.

Capturez une ligne de base de 15 à 60 minutes sous charge typique :

- Résumé du cluster : CPU %, load average, heap used vs committed, temps de pause GC.

- Graphes d'exécution par processeur (5 min et 1 h) : Tasks/Time, octets lus/écrits, état backpressure.

- Métriques de files d'attente : nombre en file, taille en file, âge de file (âge du plus ancien FlowFile).

- Échantillon de provenance de données : latence de bout en bout (ingestion vers sink) et temps par saut.

Astuce : conservez des captures d'écran ou exportez l'historique de statut en JSON pour comparer avant/après sans deviner.

## Chemin de configuration sûr

Utilisez un petit nombre de changements contrôlés, validez, et conservez ou annulez. Le workflow ci-dessous s'échelonne d'un pilote sur portable à un cluster multi-nœuds.

### 1. Commencez par un pilote étroit

- Choisissez un chemin de flux, par exemple : Kafka -> MergeRecord -> PutHDFS.

- Définissez une métrique de succès : réduire la latence p95 de bout en bout de 12 s à ≤ 5 s, ou augmenter le débit soutenu de 10 MB/s à 30 MB/s sans backpressure.

- Choisissez un plafond d'utilisation des ressources pendant le pilote : CPU ≤ 80% soutenu, pauses GC heap ≤ 200 ms p95.

### 2. Dimensionnez correctement la mémoire et le GC de la JVM NiFi

- Objectif : éviter le thrashing GC et la pression heap.

- Exemple construit pour conf/bootstrap.conf :

# conf/bootstrap.conf (exemple construit)
java.arg.2=-Xms8g
java.arg.3=-Xmx8g
java.arg.4=-XX:+UseG1GC 

- Faites Xms == Xmx pour réduire la fragmentation. Préférez G1GC sur Java 11+ pour les charges de travail à latence mixte.

- Résultat attendu : pauses GC plus courtes et moins fréquentes ; utilisation heap stable sous charge constante.

### 3. Placez les repositories sur des disques rapides

- Séparez les volumes physiques quand possible : content repo sur les SSD les plus rapides, provenance repo sur SSD, flowfile repo peut partager des disques rapides si nécessaire.

- Exemple construit pour conf/nifi.properties :

 nifi.content.repository.directory.default=/data/nifi/content
nifi.provenance.repository.directory.default=/data/nifi/provenance
nifi.flowfile.repository.directory=/data/nifi/flowfile
nifi.provenance.repository.max.storage.size=200 GB
nifi.provenance.repository.max.storage.time=24 hours 

- Résultat attendu : attente I/O repository réduite, moins d'arrêts pendant les grosses écritures, requêtes provenance plus rapides.

### 4. Ajustez la concurrence et l'ordonnancement des processeurs

- Pour les processeurs CPU-bound (ex: traitement Record, transformations JSON/Jolt), augmentez Concurrent Tasks graduellement jusqu'à ce que le CPU approche votre plafond cible.

- Pour les processeurs I/O-bound (ex: PutHDFS, PutDatabaseRecord, PutKafka), préférez une concurrence plus élevée jusqu'à la limite du système externe (ex: connexions DB, partitions Kafka). Respectez le backpressure et les quotas distants.

- Utilisez Run Schedule (ms) pour regrouper naturellement les sources bavardes (ex: réglez Run Schedule à 200-500 ms sur les processeurs d'ingestion pour créer des micro-batches).

- Résultat attendu : débit plus élevé sans croissance des files ; CPU stable et pas d'augmentation de pénalisation ou de yields.

### 5. Backpressure et conception des files d'attente

- Réglez le nombre d'objets et la taille de données du backpressure par connexion pour correspondre à la capacité du working set.

- Exemple construit : nombre d'objets 50 000 et taille de données 10 GB entre MergeRecord et PutHDFS pour un cluster de 3 nœuds avec 64 GB RAM chacun.

- Utilisez des Prioritizers quand la latence compte : réglez Prioritizer sur Newest First sur les chemins chauds qui doivent vider les données récentes rapidement pendant les pointes.

- Résultat attendu : les files se limitent de façon prévisible, évitant la croissance du heap ; les processeurs amont yield plutôt que de provoquer des échecs en cascade.

### 6. Tailles de batch et paramètres I/O

- Kafka : réglez batch size et acks selon les objectifs de latence. Augmentez Concurrent Tasks sur PutKafka jusqu'au nombre de partitions. Alignez linger/batch settings avec les objectifs de débit si supporté par la version du processeur.

- HDFS/S3 : augmentez la taille de buffer et les seuils multipart pour les gros fichiers ; pour nombreux petits fichiers utilisez MergeRecord avant PutHDFS/PutS3Object pour réduire la surcharge namenode/listing objets.

- Bases de données : dimensionnez les pools de connexions DBCP pour gérer les écrivains de pointe. Limitez Concurrent Tasks à la taille du pool pour prévenir les timeouts.

- Résultat attendu : moins d'appels système par événement, débit amélioré, latence aval stable.

### 7. Site-to-Site et Remote Process Groups

- Pour les sauts inter-cluster, augmentez Batch Count/Size/Duration pour amortir les handshakes. Gardez la durée de batch modeste (100-500 ms) pour éviter d'ajouter de la latence.

### 8. Ajustez la provenance pour vos requêtes

- Si la pression d'écriture est forte, réduisez le temps ou la taille de rétention. Si vous interrogez souvent la provenance, gardez les données récentes sur les disques les plus rapides.

- Résultat attendu : les requêtes répondent vite ; le repository n'étrangle pas les écrivains d'événements.

### Exemples pratiques construits

### A) Nombreux petits événements JSON vers HDFS (priorité débit)

- Scénario : FlowFiles 50 KB en moyenne depuis Kafka ; objectif 3x débit.

- Étapes :

- MergeRecord avant PutHDFS : cible 50-100 enregistrements par FlowFile.

- Réglez PutHDFS Concurrent Tasks pour correspondre à la cible de concurrence DataNode HDFS (exemple construit : 8 par nœud).

- Augmentez le backpressure entre MergeRecord et PutHDFS à 50 000 objets, 10 GB pour permettre la formation de batches.

- Gardez Run Schedule par défaut (0 ms) pour MergeRecord pour vider les files vite.

- Attendu : surcharge namenode réduite, MB/s soutenu plus élevé, CPU stable à 60-75%.

### B) Miroir de gros fichiers vers S3 (priorité latence)

- Scénario : fichiers 2-5 GB depuis SFTP poussés vers S3 ; objectif p95 sous 90 s.

- Étapes :

- Utilisez FetchSFTP + PutS3Object avec seuils multipart activés ; augmentez les timeouts socket et requête.

- Réglez PutS3Object Concurrent Tasks bas (exemple construit : 2-4) pour éviter de saturer l'uplink ; augmentez la taille de partie multipart à 64-128 MB.

- Réglez le Prioritizer de file sur Oldest First pour faire avancer les gros fichiers.

- Attendu : moins de retentatives, uploads multipart plus fluides, latence p95 baisse sans pics de bande passante.

### C) Ingestion HTTP vers base de données (tolérance aux rafales)

- Scénario : rafales HTTP 2-3x au-dessus du régime permanent pendant 5 minutes ; DB peut committer 3k lignes/s en régime, 5k en court terme.

- Étapes :

- Configurez le backpressure avant PutDatabaseRecord à 20 000 objets et 4 GB.

- Limitez PutDatabaseRecord Concurrent Tasks à la taille du pool de connexions (exemple construit : 6).

- Réglez Run Schedule à 100-250 ms et taille de batch Record à 500-2 000 lignes pour l'efficacité des commits.

- Attendu : rafales absorbées en file sans timeouts ; arriéré vidé en 10-15 minutes.

### Référence rapide de dimensionnement des ressources (lignes directrices construites)

 Trait de charge CPU suggéré/nœud Heap/nœud Repos et disques Notes 
 Nombreux petits fichiers, TPS élevé 8-16 cœurs 8-16 GB SSD pour content+provenance Insistez sur MergeRecord et batching 
 Gros fichiers, streaming 8-12 cœurs 8-16 GB SSD rapide pour content Insistez sur réseau et tuning multipart 
 ETL mixte avec transformations Record 16-32 cœurs 16-32 GB SSD séparés pour tous repos CPU-bound ; augmentez Concurrent Tasks prudemment 
 Requêtes provenance lourdes 12-24 cœurs 16-32 GB SSD rapide pour provenance Réduisez rétention si écrivains bloquent 
 Rafale entrée, sinks lents 8-16 cœurs 16-24 GB SSDs ; limites de file généreuses Dimensionnement backpressure critique 

## Validation et diagnostics

 Changez seulement quelques paramètres à la fois et vérifiez l'impact avec des contrôles observables.

### Quoi mesurer et où

<div class="my-stack-md overflow-x-auto">
<table class="w-full min-w-[42rem] border-collapse text-left">
<thead><tr><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Métrique</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Où regarder</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Attendu si sain</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Action si hors cible</th></tr></thead>
<tbody><tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Latence p95 bout en bout</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Requêtes Data Provenance</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Au but ou en dessous</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Tracez sauts lents ; augmentez concurrence ou taille batch sur goulot</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">ge de file (plus ancien)</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Infobulle file et Historique statut</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Stable ou baisse après changement</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si monte, aval est goulot ; réduisez taux amont ou augmentez concurrence aval</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">État backpressure</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Indicateurs de connexion</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Rarement engagé en régime permanent</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si souvent engagé, ajustez limites ou batchez plus tôt</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">CPU et load average</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Métriques OS nœud, Diagnostics système NiFi</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">50-80% soutenu, pics courts</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si &gt;90% soutenu, réduisez tâches concurrentes ou optimisez processeurs</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Heap utilisé et pauses GC</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Diagnostics système NiFi</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Heap utilisé stable, pauses courtes</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si pauses longues, baissez concurrence ou augmentez heap, vérifiez tailles FlowFile</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Attente I/O repo</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">OS iostat / métriques disque</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Faible attente I/O sous charge</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si forte, déplacez repos sur SSD ou réduisez rétention provenance</td></tr></tbody>
</table>
</div>

### Comment valider les changements

- Utilisez un test de charge fixe pendant 5-15 minutes. Gardez les données source constantes pendant l'itération.

- Comparez l'historique de statut (5 min, 1 h) avant vs après : concentrez-vous sur Bytes in/out, Tasks/Time et tailles de files.

- Lancez une requête provenance pour un échantillon de FlowFiles et calculez min/médiane/p95 pour sauts et bout en bout.

- Pour configurations cluster, vérifiez le déséquilibre nœuds : grandes différences en comptes en file ou CPU suggèrent du hot-spotting.

### Exemples de résultats attendus

- Après activation de MergeRecord dans le scénario petits fichiers, attendez Bytes Out par minute à augmenter 2-4x, âge de file à baisser, et temps d'écriture HDFS par FlowFile à diminuer. CPU peut monter mais doit stabiliser sous votre plafond.

- Après réduction de PutDatabaseRecord concurrence pour correspondre à la taille du pool, attendez les erreurs de timeout à disparaître, avec âge de file légèrement plus haut pendant rafales mais vidage plus rapide après.

### Si les résultats sont inconclusifs

- Revenez au point de contrôle précédent et essayez un autre levier (ex: réduisez concurrence, augmentez taille batch, ou déplacez un repo). Évitez d'empiler des changements non liés.

- Si améliorations sont mitigées, séparez le chemin de flux : isolez le goulot suspecté avec un funnel et mesurez chaque branche.

## Modes d'échec et récupération

L'optimisation comporte toujours des risques. Utilisez le tableau ci-dessous pour reconnaître les symptômes tôt et récupérer en sécurité.

<div class="my-stack-md overflow-x-auto">
<table class="w-full min-w-[42rem] border-collapse text-left">
<thead><tr><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Symptôme</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Cause probable</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">À essayer</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Déclencheur rollback</th></tr></thead>
<tbody><tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Pauses GC fréquentes, UI lente</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Trop de tâches concurrentes, grosses files</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Baissez concurrence, augmentez heap modestement, réduisez limites files</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si p95 pause GC &gt; 500 ms pendant 5+ min</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Backpressure toujours actif</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Débit aval insuffisant</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Augmentez concurrence aval ou taille batch ; priorisez file</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si timeouts ou retentatives amont apparaissent</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Arrêts écriture repository</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Disques lents, rétention provenance trop grande</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Déplacez repos sur SSD, baissez taille/temps rétention</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si utilisation content/provenance atteint 90%</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Utilisation nœuds inégale</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Déséquilibre partitions, hot-spot processeur stateful</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Alignez ingestion avec partitions ; utilisez connexions load-balanced</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si un nœud &gt;2x autres pendant 10+ min</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Nombreux FlowFiles pénalisés</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Erreurs externes transitoires, retentatives trop agressives</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Augmentez durée pénalisation ; ajoutez retry-with-backoff</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si compte pénalités croît et latence pique</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Timeouts DB/Kafka</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Concurrence dépasse limites externes</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Plafonnez tâches concurrentes à pool/nombre partitions</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Si taux erreur &gt; 1% soutenu</td></tr></tbody>
</table>
</div>

### Étapes de rollback sûres

- Pause et vidage du chemin

- Arrêtez d'abord les processeurs amont pour empêcher nouvelle entrée.

- Laissez les files vider à une taille sûre ou utilisez patterns List/Fetch pour contrôler l'ingestion pendant le rollback.

- Restaurez les paramètres précédents

- Revenez aux tâches concurrentes, seuils backpressure et tailles de batch des dernières valeurs connues bonnes.

- Restaurez les paramètres JVM dans bootstrap.conf et redémarrez un seul nœud pour valider avant déploiement cluster-wide.

- Validez la stabilité

- Confirmez CPU, heap et âge de file reviennent à la ligne de base.

- Vérifiez les logs pour messages de récupération repository et assurez-vous qu'ils complètent vite.

- Reprenez et surveillez

- Démarrez les processeurs dans l'ordre aval vers amont.

- Surveillez backpressure et bulletins d'erreur 10-15 minutes avant de déclarer le succès.

## Check-list opérationnelle

Utilisez cette check-list pour rendre le travail de performance NiFi prévisible et reproductible.

### Avant l'optimisation

- Capturez version, topologie et inventaire matériel.

- Ligne de base : CPU, heap, GC, I/O repo, âge de file, latence provenance.

- Définissez un ou deux critères de succès mesurables et plafonds de sécurité.

### Pendant l'optimisation

- Changez un petit nombre de paramètres liés seulement.

- Préférez changements de concurrence et batch avant d'ajouter des nœuds.

- Gardez les processeurs touchant des systèmes externes dans les limites connues de pool/partitions.

- Ajustez le backpressure judicieusement pour protéger heap et repos.

### Après chaque changement

- Lancez un test de charge constant 5-15 minutes.

- Enregistrez les deltas d'historique de statut et latence provenance.

- Vérifiez bulletins d'erreur et comptes de pénalisation.

### Si quelque chose se dégrade

- Arrêtez amont, videz, rétablissez paramètres, validez sur un nœud, puis déployez.

### Soin hebdomadaire/bihebdomadaire

- Revoyez l'utilisation du stockage provenance et temps de requête.

- Vérifiez le déséquilibre entre nœuds et rééquilibrez si nécessaire.

- Revisitez les limites backpressure selon les nouveaux volumes de données.

### Planification trimestrielle

- Réévaluez le placement des repositories selon la croissance des données.

- Alignez partitions Kafka, tailles de pools DB et concurrence NiFi.

- Testez les temps de basculement et récupération pour grosses files.

## Conclusion

L'optimisation des performances NiFi est plus efficace quand vous commencez petit, mesurez sans relâche, et faites un changement à la fois. Inventoriez votre environnement, dimensionnez correctement la mémoire et les repositories, définissez un backpressure adapté à votre working set, et alignez la concurrence des processeurs avec les limites CPU et des systèmes externes. Validez chaque ajustement avec l'historique de statut et la provenance, et gardez le rollback simple en utilisant des points de contrôle clairs. Appliquez ce workflow à un chemin de flux, puis étendez aux chemins voisins jusqu'à ce que tout le pipeline atteigne vos objectifs de latence et débit. Avec les exemples et check-listes de ce guide, vous pouvez augmenter le débit, réduire la latence, et garder la récupération prévisible à travers les intégrations Kafka, HDFS, Spark, Airflow et autres pipelines de données.