route haute performance Analyse source FastThreadLocal Netty (rapide et sécurisé)

avant-propos

Netty haute performance comme cadre pour un grand nombre des classes JDK sont mis en pot et l'optimisation, par exemple la classe de fil, Netty utilisé pour créer FastThreadLocalRunnable toutes DefaultThreadFactory Runnable ont été emballés. fins d'emballage exécutent différentes méthodes, voir le code:

 public void run () { try { runnable.run (); } Enfin { FastThreadLocal.removeAll (); } }

Vous pouvez voir, plus d'une ligne FastThreadLocal.removeAll (), nous le savons tous, JDK est livré avec l'environnement de la piscine de fil ThreadLocal, il y a le risque de fuites de mémoire, il est clair, Netty Pour éviter ce bug, reconditionner, et ce le nom du fil de package appelé FastThreadLocalRunnable, la sémantique est claire: ThreadLocal rapide! Ce qui veut dire vient avec le JDK me lent? Ensuite, nous examinons aujourd'hui est rapide à la fin où? Sur les fuites de mémoire ThreadLocal n'est pas clair ou pas clair sur ThreadLoca être le lieu d'analyse de code source de programmation concurrente ThreadLocal.

1. Comment utiliser?

cas de test

Les résultats d'exploitation

2. La résolution de la méthode de construction

constructeur

Constructeurs définit deux variables. index et cleanerFlagIndex, et ces deux variables sont int finale de. Et par tous

 Procédé InternalThreadLocalMap.nextVariableIndex () à partir de.

Procédé InternalThreadLocalMap.nextVariableIndex ()

variables nextIndex

Ce procédé est obtenu par un atome d'auto-excitation variable int. En d'autres termes, cleanerFlagIndex grand indice de taux variable 1, le rôle de ces deux variables que nous verrons plus loin comment les utiliser. Ici, pour l'instant n'est pas la table.

3. Procédé de résolution d'ensemble

set () Méthode

Les étapes sont les suivantes:

  • Déterminer si la valeur de la valeur de consigne est la valeur par défaut, si elle est, est appelée méthode Remove.
  • Sinon, obtenir InternalThreadLocalMap canal thread courant. La valeur remplace alors l'objet index FastThreadLocal correspondant à la nouvelle valeur. L'ancienne valeur définie à la valeur par défaut.
  • Une petite méthode set, mais l'intérieur est très complexe, évacuation de non combattants le plus tôt possible s'il vous plaît!

    En fait, ici nous avons appelé quatre méthodes:

  • InternalThreadLocalMap.get ();
  • setKnownNotUnset (threadLocalMap, valeur);
  • registerCleaner (threadLocalMap);
  • supprimer ();
  • Laissez-nous lentement dit-il.

    1. InternalThreadLocalMap.get ();

    Code est la suivante:

     InternalThreadLocalMap public static get () { fil de thread = Thread.currentThread (); si (fil instanceof FastThreadLocalThread) { retour (fil (FastThreadLocalThread)) fastGet; } Else { retourner slowGet (); } }

    La première est une méthode statique InternalThreadLocalMap, la logique de la méthode est simple, surtout appeler de différentes manières selon que le thread courant est FastThreadLocalThread Netty, est un moyen rapide, un (pas un fil est de lent Netty) lent. Ha ha ha, Netty nom de l'auteur est vraiment forte. Ensuite, nous regardons ce qui approche fastGet?

     private static InternalThreadLocalMap fastGet (filetage FastThreadLocalThread) { InternalThreadLocalMap threadLocalMap = thread.threadLocalMap (); if (threadLocalMap == NULL) { thread.setThreadLocalMap (threadLocalMap = new InternalThreadLocalMap ()); } retourner threadLocalMap; }

    La logique est simple, obtenir InternalThreadLocalMap thread courant, sinon, créer un. Nous regardons son constructeur.

     public static final Object UNSET = new Object (); InternalThreadLocalMap privé () { Super (newIndexedVariableTable ()); } Object private static newIndexedVariableTable () { tableau d'objets = new Object ; Arrays.fill (tableau, UNSET); réseau de retour; } UnpaddedInternalThreadLocalMap (Object ) {indexedVariables this.indexedVariables = indexedVariables; }

    Les trois méthodes sont associés Landlord ensemble, et facile à voir, tout d'abord, le constructeur de la classe parent UnpaddedInternalThreadLocalMap InternalThreadLocalMap appel, et le passage d'un tableau, le tableau 32 est la taille par défaut, qui est rempli objet vide 32 références.

    Cette méthode slowGet est ce qui ressemble? Code est la suivante:

     static final ThreadLocal < InternalThreadLocalMap >  slowThreadLocalMap = new ThreadLocal < InternalThreadLocalMap > (); private static InternalThreadLocalMap slowGet () { ThreadLocal < InternalThreadLocalMap >  slowThreadLocalMap = UnpaddedInternalThreadLocalMap.slowThreadLocalMap; InternalThreadLocalMap ret = slowThreadLocalMap.get (); if (ret == NULL) { ret = new InternalThreadLocalMap (); slowThreadLocalMap.set (RET); } retourner ret; }

    Le code est très simple, nous analysons: le premier à utiliser le JDK ThreadLocal pour obtenir un InternalThreadLocalMap Netty, sinon créer un et définir ce InternalThreadLocalMap au JDK ThreadLocal, puis revenir à cette InternalThreadLocalMap. Comme on peut le voir ici, afin d'améliorer les performances, ou éviter d'utiliser threadLocalMap, son chemin est Quxianjiuguo du JDK Netty: Set InternalThreadLocalMap Netty dans le JDK ThreadLocal alors, ce InternalThreadLocalMap mis FastThreadLcoal Netty.

    Eh bien, nous sommes méthode InternalThreadLocalMap.get () pour lire, principalement pour obtenir InternalThreadLocalMap thread courant, sinon, créez un, le maintien de la carte interne est un tableau, et différent JDK, JDK

     Carte est maintenue en utilisant une méthode de sonde linéaire, vu de la structure de données sous-jacentes, le JDK a été perdu, leur vitesse de lecture varient considérablement, surtout si grande quantité de données, la vitesse de la structure de données reste Netty inchangé, tandis que l'utilisation de la méthode de détection de JDK, la vitesse diminue.

    2. setKnownNotUnset (threadLocalMap, valeur);

    Lorsque InternalThreadLocalMap.get () retourne un InternalThreadLocalMap, cette fois appelant setKnownNotUnset (threadLocalMap, valeur), le mode de fonctionnement. Code est la suivante:

     setKnownNotUnset private boolean (InternalThreadLocalMap threadLocalMap, la valeur V) { si (threadLocalMap.setIndexedVariable (indice, valeur)) { addToVariablesToRemove (threadLocalMap, this); return true; } return false; }

    Voir le nom de méthode, est de définir une valeur, mais pas unset, qui est, cet objet est vide. Défini par threadLocalMap.setIndexedVariable (indice, valeur). Si elle retourne vrai, appelez addToVariablesToRemove (threadLocalMap, cela). Ces deux méthodes, nous examinons ensemble. Regardez le premier:

    procédé setIndexedVariable

     setIndexedVariable public boolean (index int, Object value) { Objet recherche = indexedVariables; si (index <  lookup.length) { Objet oldValue = recherche ; recherche  = Valeur; retourner oldValue == UNSET; } Else { expandIndexedVariableTableAndSet (index, valeur); return true; } }

    En premier lieu, pour obtenir la longueur de la matrice 32, si l'indice de propriété FastThreadLocal est inférieure à la longueur du tableau, la valeur est définie à l'emplacement spécifié. La valeur d'origine de la fente de cible est vide. Si l'objet d'origine est objet vide, il retourne vrai, sinon faux.

    Si non? Appel méthode expandIndexedVariableTableAndSet (indice, valeur). La vue sur la méthode. Voir le nom de méthode et définir la valeur de l'indice est de se développer.

     expandIndexedVariableTableAndSet private void (index int, Object value) { Objet oldArray = indexedVariables; oldCapacity final int = oldArray.length; int newCapacity = index; newCapacity | = newCapacity > > >  1; newCapacity | = newCapacity > > >  2; newCapacity | = newCapacity > > >  4; newCapacity | = newCapacity > > >  8; newCapacity | = newCapacity > > >  16; newCapacity ++; Objet newArray = Arrays.copyOf (oldArray, newCapacity); Arrays.fill (newArray, oldCapacity, newArray.length, UNSET); newArray  = Valeur; indexedVariables = newArray; }

    Ici, le code est très familier avec, HashMap a également le code tel, nous prenons un coup d'oeil:

    Le procédé de la HashMap tableSizeFor

    Par le code d'action est deux fois l'expansion de la capacité d'origine. Et pour faire en sorte que le résultat est une puissance de deux. Ici Netty HashMap et pratiques, l'expansion récente de la taille d'une puissance de 2, en fonction de la capacité d'origine, tel que le 32 original, il est détendu à 64, puis le remplissage de la matrice pour le nouveau contenu de la matrice d'origine, le remplissage du reste de l'objet vide puis affecté aux nouvelles indexedVariables variables membres de tableau. Il a réalisé une expansion de la capacité.

    méthode Retour setKnownNotUnset, dans quelles circonstances méthode renvoie setIndexedVariable il ture? L'expansion, l'expansion ou pas, mais l'objet inséré ne remplace pas d'autres objets, qui est, la fente d'origine est l'objet vide. En d'autres termes, seuls les objets mis à jour renvoie false.

    Autrement dit, lorsqu'un nouvel objet, il appellera méthode addToVariablesToRemove, comme le nom de la méthode, ajouter une variable puis supprimer. Nous regardons la logique de la méthode addToVariablesToRemove (threadLocalMap, cela):

     addToVariablesToRemove private static void (InternalThreadLocalMap threadLocalMap, FastThreadLocal < ? >  variable) { // Cette variable est statique finale, donc généralement 0 Object v = threadLocalMap.indexedVariable (variablesToRemoveIndex); ensemble < FastThreadLocal < ? > >  variablesToRemove; si (v == || InternalThreadLocalMap.UNSET v == NULL) { // Création d'un IdentityHashMap basé sur l'ensemble, les génériques sont FastThreadLocal variablesToRemove = Collections.newSetFromMap (nouveau IdentityHashMap < FastThreadLocal < ? > , Boolean > ()); // Définir cet indice dans ce tableau 0 Carte threadLocalMap.setIndexedVariable (variablesToRemoveIndex, variablesToRemove); } Else { // Sinon obtenir UNSET, a déclaré que c'est la deuxième opération, il peut être converti en solide ensemble variablesToRemove = (Set < FastThreadLocal < ? > > ) V; } // Le but final est de FastThreadLocal placé dans Set variablesToRemove.add (variable); }

    Le but de cette méthode est de sauver l'objet FastThreadLocal à un ensemble, la méthode statique removeAll vous devez utiliser l'ensemble, tous FTL supprimer rapidement la carte Valeur correspondante du fil. Si vous n'utilisez pas le Set, alors vous devez traverser InternalThreadLocalMap, la performance est peu élevé.

    Avoir une méthode setKnownNotUnset, nous disons que la méthode de registerCleaner.

    3. registerCleaner (threadLocalMap);

    Cette méthode peut dire un peu compliqué, s'il vous plaît Bide, voici l'essence de FTL (FastThreadLocal) de.

    Tout d'abord, que le rôle de cette méthode: L'enregistrement de cette FTL pour nettoyer un fil, lorsque l'objet de fil est gc, il est nettoyé automatiquement FTL, JDK empêcher les fuites de.

    Le get Let dans la vue de processus:

    registerCleaner private void (finale InternalThreadLocalMap threadLocalMap) { courant de filetage = Thread.currentThread (); si (FastThreadLocalThread.willCleanupFastThreadLocals (courant) || threadLocalMap.indexedVariable (cleanerFlagIndex)! = InternalThreadLocalMap.UNSET) { retour; } threadLocalMap.setIndexedVariable (cleanerFlagIndex, Boolean.TRUE); ObjectCleaner.register (courant, nouveau Runnable () { public void run () { supprimer (threadLocalMap); } }); }

    Le propriétaire a enlevé les commentaires dans le code source, le PARLONS au sujet de la bonne cette méthode:

  • Obtenez le thread courant, si le thread courant est de type FastThreadLocalThread et cleanupFastThreadLocals est vrai, il retourne vrai, retour direct. En d'autres termes, fil de pool de threads Netty qui répondent à ces conditions sont créées, seul le pool de threads défini par l'utilisateur ne répond pas.
  •  Bien sûr, il y a une condition: si l'indice de FTL + 1 valeur est objet vide sur la carte, vous êtes déjà inscrit, et aussi le retour direct, l'enregistrement ne se reproduira pas.
  • Lorsque la condition ne répond pas à ce qui précède, la valeur de la carte correspondante indice FTL + 1 position de TRUE. Selon cet arrêt, empêcher l'enregistrement en double.
  • Appel ObjectCleaner la méthode de registre, l'enregistrement d'une tâche, la tâche se contente d'appeler la méthode de suppression des objets de suppression et le contenu correspondant à la carte de FTL.
  • La question est, comment l'enregistrer? Pourquoi courant avec un fil courant de celui-ci?

    Nous sommes à la source:

    statique registre public void (objet Object, Runnable cleanupTask) { AutomaticCleanerReference référence = new AutomaticCleanerReference (objet, ObjectUtil.checkNotNull (cleanupTask, "cleanupTask")); LIVE_SET.add (référence); // Vérifiez s'il y a déjà un marche plus propre. si (CLEANER_RUNNING.compareAndSet (false, true)) { dernière discussion cleanupThread = new FastThreadLocalThread (CLEANER_TASK); cleanupThread.setPriority (Thread.MIN_PRIORITY); AccessController.doPrivileged (nouveau PrivilegedAction < vide > () { void run () {publique cleanupThread.setContextClassLoader (null); return null; } }); cleanupThread.setName (CLEANER_THREAD_NAME); cleanupThread.setDaemon (true); cleanupThread.start (); } }

    Tout d'abord créer un objet AutomaticCleanerReference auto-nettoyage inherits WeakReference, ne regardez pas à ses méthodes de construction, regardez ce qui suit, ce sera un bon exemple de mettre la construction en LIVE_SET en fait, c'est un paquet Netty ConcurrentSet, juger ensuite Effacé le fil est en cours d'exécution. Sinon, changer le statut et le succès de CAS. Pour créer un fil, la tâche est définie CLEANER_TASK, la priorité de fil est le plus bas, le chargeur de classe supérieure et inférieure est nulle, le nom est objectCleanerThread, et un fil d'arrière-plan. Puis commencez à ce fil. Exécuter CLEANER_TASK.

    Étape par étape et voir.

    constructeur première AutomaticCleanerReference comme suit:

    private static final ReferenceQueue < objet >  REFERENCE_QUEUE = new ReferenceQueue < objet > (); AutomaticCleanerReference (objet de référent, Runnable cleanupTask) { Super (référent, REFERENCE_QUEUE); this.cleanupTask = cleanupTask; } vide cleanup () { cleanupTask.run (); }

    ReferenceQueue effet que, lorsque l'objet à récupérer, sera ajouté à l'objet de file d'attente, l'objet peut être suivi. Réglage de cet objet peut être ressuscitée. En d'autres termes, lorsque l'objet de discussion est récupéré, ce sera la référence d'objet dans cette file d'attente, mis dans le faire? Lorsqu'ils sont pris hors de lui? Nous voyons quand retirés:

    Code est la suivante:

    private static final Runnable CLEANER_TASK = new Runnable () { @Override public void run () { for (;;) { while (! LIVE_SET.isEmpty ()) { référence final AutomaticCleanerReference = (AutomaticCleanerReference) REFERENCE_QUEUE.remove (REFERENCE_QUEUE_POLL_TIMEOUT_MS); si (référence! = null) { try { reference.cleanup (); } Catch (Throwable ignoré) { } LIVE_SET.remove (référence); } } CLEANER_RUNNING.set (false); si (LIVE_SET.isEmpty () ||! CLEANER_RUNNING.compareAndSet (false, true)) { break; } } } };

    Une coïncidence! ! ! ! CLEANER_TASK en utilisant ce ReferenceQueue! ! ! ! Ne vous énervez pas, nous regardons lentement à cette tâche à la fin est ce qu'il faut faire:

  • Boucle infinie, si ConcurrentSet pas vide (rappelez-vous nous allons le mettre AutomaticCleanerReference ici), essayer d'enlever les AutomaticCleanerReference de REFERENCE_QUEUE Autrement dit, nous venons de mettre l'entrée. Ceci est la pratique courante de suivi d'un GC objet. Lorsqu'un objet est parce que le GC, assurera référence de cet objet dans la file d'attente de référence spécifiée, qui est la machine virtuelle Java à faire.
  • Si ce n'est pas vide, appel de méthode Cleanup appliquée, qui est, nous passons dans une tâche, et la tâche? Telle est la tâche d'appeler la méthode de suppression de FTL. Ensuite, supprimez les références de l'ensemble.
  • Si Set est vide, il va nettoyer l'état de fil (variable atomique) est réglé sur Fasle.
  • Poursuit pour déterminer si l'ensemble vide ou non vide et FIXER le CAS est défini sur true échec de l'Etat (explication autre thread a changé cet état) est hors de la boucle, l'extrémité du fil.
  • Un peu ignorant? Ensuite, nous faisons un bon résumé Pourquoi ici:

    Quand nous sommes dans un pool de threads Netty non-thread créés à l'aide du temps de FTL, Netty enregistrera un thread de nettoyage des ordures (parce que le fil sera finalement exécuté pool de threads méthode removeAll Netty créé, non pas une fuite de mémoire), utilisé pour nettoyer ce fil cette variable FTL, du code ci-dessus, nous savons que, si vous utilisez un non-fil FTL Netty, Netty va encore aider le JDK ThreadLocal, mais seulement d'emprunter une fente, plaçant Carte Netty, Carte, puis placé dans la FTL Netty. Par conséquent, une fuite de mémoire peut se produire dans le cas de la piscine de fil. Netty Pour résoudre ce problème, chaque fois qu'un nouveau temps de FTL, sera enregistré avec l'objet et le fil FTL est lié à une référence au GC lorsque l'objet de fil est récupéré, nettoiera son chemin Plan tous FTL, pour résoudre le problème, la même chose que la résolution de bug Nio JDK.

    Eh bien, ici, l'essence de FastThreadLocal de Netty est fondamentalement tout ce que nous avons appris. FTL est non seulement rapide, mais aussi sûr. Dans la méthode de détection rapide en utilisant un réseau linéaire au lieu de la carte, fil de sécurité à chaque fois récupéré tous les FTL de nettoyage, ne vous inquiétez pas au sujet des fuites de mémoire.

    Les autres méthodes sont très simples. Nous avons lu ensemble

    4. supprimer ();

    Définir un moment où un objet vide, est d'appeler la méthode de suppression, nous prenons un coup d'il à cette méthode, le code source est comme suit:

     public final void remove () { supprimer (InternalThreadLocalMap.getIfSet ()); } public static InternalThreadLocalMap getIfSet () { fil de thread = Thread.currentThread (); si (fil instanceof FastThreadLocalThread) { retourner ((fil FastThreadLocalThread)) .threadLocalMap (); } retourner slowThreadLocalMap.get (); } finale supprimer public void (InternalThreadLocalMap threadLocalMap) { if (threadLocalMap == NULL) { retour; } // supprimer le tableau et renvoie le courant Carte indice ThreadLocal valeur correspondant Object v = threadLocalMap.removeIndexedVariable (index); // Set retiré de la position marquée sous Carte 0 tableau, et supprimer le courant ThreadLocal removeFromVariablesToRemove (threadLocalMap, this); si (v! = InternalThreadLocalMap.UNSET) { try { // par défaut ce qui ne se fait pas, l'utilisateur peut hériter FastThreadLocal redéfinir cette méthode. onRemoval ((V) v); } Catch (Exception e) { PlatformDependent.throwException (e); } } }

    Propriétaire de ces trois méthodes sont combinées, d'abord obtenir threadLocalMap le fil en cours, puis il suffit d'écrire le commentaire: FTL supprimer l'index correspondant à la carte de la valeur, puis Suppr.régl.impr carte de 0 SUBSCRIPT FTL. méthode IsSet pour prévenir les fausses couches de la justice. Enfin, si vous repassez méthode onRemoval est appelée, la méthode par défaut est vide. L'utilisateur peut remplacer la méthode onRemoval et méthode initialize.

    4. Obtenir la méthode d'analyse

    obtenir la méthode encore plus simple, comme suit:

     get () public final V { InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get (); Object v = threadLocalMap.indexedVariable (index); si (v! = InternalThreadLocalMap.UNSET) { retour (V) v; } La valeur de V = initialize (threadLocalMap); registerCleaner (threadLocalMap); La valeur de retour; }

    Enfiler obtient d'abord la carte courante, et l'indice d'acquisition ftl en fonction de la valeur, puis retourne, si l'objet est vide, c.-à-pas définie, retourne par l'initialisation, initialise le procédé retourne à la valeur de consigne dans le plan de la fente, et placé Situé dans. Enfin, essayez d'enregistrer un produit de nettoyage.

    5. supprimer toutes les méthodes d'analyse

    Cette méthode est appelée dans un bloc finally de fil par défaut de Netty. Code est la suivante:

     public static void removeAll () { InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet (); if (threadLocalMap == NULL) { retour; } try { Object v = threadLocalMap.indexedVariable (variablesToRemoveIndex); if (v! = null && v! = InternalThreadLocalMap.UNSET) { @SuppressWarnings ( "sans contrôle") ensemble < FastThreadLocal < ? > >  variablesToRemove = (Set < FastThreadLocal < ? > > ) V; FastThreadLocal < ? > VariablesToRemoveArray = variablesToRemove.toArray (nouveau FastThreadLocal ); pour (FastThreadLocal < ? >  VLE: variablesToRemoveArray) { tlv.remove (threadLocalMap); } } } Enfin { InternalThreadLocalMap.remove (); } }

    Très simple, d'abord obtenir le courant carte du fil, puis préparez-vous, Set se transforme en un tableau, boucle à travers le réseau, appelez la méthode de suppression de FTL. Enfin, la carte supprimer les attributs fil.

    résumé

    Maintenant, nous venons de résumer FastThreadLocal.

    Il est appelé rapide, car il JDK est inutile Carte en utilisant la méthode de linéaire de sondage, si vous utilisez un fil pool de threads usine Netty créé avec FTL Netty, la performance est très bonne, si vous utilisez un fil personnalisé, avec FTL, la performance sera meilleure que le JDK, attention: FTL pas de fuite de mémoire risque JDK.

    Mais ceux-ci ne sont pas sans un prix, parce que chaque FTL est un index unique, et cet indice est créé à chaque fois qu'un objet FTL sont augmentés de 2 quand vous avez beaucoup d'index, votre fil carte doit être augmentée en conséquence, il est concevable, si la masse de l'objet FTL créer ces déchets du tableau est très objectif. De toute évidence, cela est un espace pratique pour le temps.

    Habituellement, FTL sont des objets statiques, donc nous supposons qu'il y aura tant. Si elle est utilisée de manière incorrecte, il fait perdre beaucoup de mémoire.

    Mais les avantages sont évidents risques dans le test de la machine du propriétaire, FTL les performances de lecture est environ cinq fois le JDK, aussi la vitesse plus rapide écriture d'environ 20%.

    FastThreadLocal est devenu évident, rapide et sûr!

    Le sit boy anti-bus, descendez le pilote Pro glisse un morceau de papier, chaud ouvert pleurer ???
    Précédent
    Après Sun Yang a annoncé abandonner la course, au Japon, mais son tir des publicités feu
    Prochain
    Message-Driven --Spring Nuage flux
    Message: Liverpool et l'Inter Ao Liji Suite longueur totale d'environ 70 millions d'euros offre Loukakou
    Un salaire mensuel de 50000, alors quoi? En cela, il suffit à peine pour laver une voiture
    618 nouveaux Raiders de réception complète de téléphone portable: Comment vérifier le téléphone est authentique?
    Il était un examen d'entrée au collège, le Nord a gagné une bourse d'études, mais a couru vers les zones rurales: seulement pour le cur pastoral
    BBC exposer la vérité de l'exercice, vainquit le sens commun: des centaines de millions de personnes sont inutiles exercice
    28 340000 jeune couple a acheté une petite maison de jardin mobiles, amovible amovible peut ranger
    On ne peut que l'entretien régulier comme une voiture, mais aussi ne pas souffrir examen?
    Graphique Java mécanisme de collecte des ordures, très bien écrit
    Fait un modèle de 18 ans, elle a ramassé les feuilles mortes, coudre un nouvel art de haute
    CCTV laissant le couple, la vie idyllique dans la ville, la vie était comme une poétique
    passerelle API d'entrée abandonner