dimanche 9 mars 2025

Introduction HikariCP pour les développeurs

La gestion de pool de connexions en bases de données

La gestion de pool de connexions est une technique essentielle pour optimiser les performances des applications qui utilisent des bases de données. Voici une explication de son utilité et des coûts associés à la création de connexions:

Pourquoi utiliser un pool de connexions?

Les connexions aux bases de données sont coûteuses à établir pour plusieurs raisons:

  1. Temps d'établissement - Chaque nouvelle connexion nécessite:

    • Une authentification (vérification des identifiants)
    • Une négociation du protocole
    • Une allocation de ressources côté serveur
  2. Ressources consommées:

    • Mémoire: Chaque connexion maintient des buffers et des structures de données en mémoire
    • Descripteurs de fichiers (sockets) : Ressource limitée au niveau du système d'exploitation
    • Threads/processus côté serveur: La base de données doit dédier des ressources de calcul

Comment fonctionne un pool de connexions?

Un pool maintient un ensemble de connexions ouvertes qui sont réutilisées par l'application:

  • Les connexions sont créées à l'avance ou au fur et à mesure des besoins
  • Quand une opération de base de données est nécessaire, l'application emprunte une connexion du pool
  • Une fois l'opération terminée, la connexion est rendue au pool plutôt que d'être fermée
  • Si toutes les connexions sont utilisées, l'application peut attendre qu'une se libère ou créer une nouvelle connexion (selon la configuration)

Bénéfices en termes de performance

  • Réduction du temps de latence : Élimination du temps d'établissement des connexions
  • Économie des ressources: Réutilisation plutôt que création/destruction constante
  • Meilleure scalabilité : Gestion du nombre maximal de connexions simultanées
  • Distribution de charge : Partage efficace des ressources disponibles

Coûts de création d'une connexion

En termes concrets, voici ce que coûte la création d'une nouvelle connexion:

  • CPU : Traitement cryptographique pour l'authentification, initialisation des structures
  • Mémoire : 2-10 Mo par connexion selon le SGBD et sa configuration
  • E/S réseau : Plusieurs allers-retours réseau pour établir la connexion
  • Temps : Typiquement entre 10-100ms selon la charge du serveur et le réseau

Sans pool de connexions, une application web traitant 1000 requêtes simultanées pourrait tenter de créer 1000 connexions distinctes, consommant potentiellement plusieurs Go de RAM et surchargeant le serveur de base de données.

Un pool bien configuré pourrait gérer ces mêmes 1000 requêtes avec seulement 10-20 connexions réutilisées, réduisant considérablement la consommation de ressources.

Librairies Maven pour la gestion de pool de connexions en Java

Voici les principales librairies de gestion de pool de connexions disponibles via Maven pour les applications Java :

HikariCP

Une des plus populaires et performantes actuellement :

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version>
</dependency>

HikariCP est réputée pour sa légèreté et ses performances exceptionnelles.

Apache DBCP2

Solution mature de la fondation Apache :

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.9.0</version>
</dependency>

Tomcat JDBC Connection Pool

Développée pour Tomcat mais utilisable indépendamment :

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>10.1.12</version>
</dependency>

C3P0

Une solution éprouvée bien que plus ancienne :

<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.5</version>
</dependency>

Vibur DBCP

Pool de connexions à haute performance :

<dependency>
    <groupId>org.vibur</groupId>
    <artifactId>vibur-dbcp</artifactId>
    <version>25.0</version>
</dependency>

Spring Boot DataSource

Si vous utilisez Spring Boot, le pool de connexions est intégré :

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>3.1.2</version>
</dependency>

Spring Boot utilise HikariCP par défaut depuis la version 2.0.

Note importante

Dans les projets modernes, HikariCP est généralement le premier choix en raison de ses performances supérieures et de sa simplicité de configuration. C'est d'ailleurs la raison pour laquelle Spring Boot l'a adopté comme solution par défaut.

HikariCP - Un pool de connexions haute performance pour Java

HikariCP est une bibliothèque Java qui implémente un pool de connexions JDBC extrêmement rapide et léger. Créée par Brett Wooldridge, elle est devenue la référence en matière de gestion de connexions aux bases de données dans l'écosystème Java.

Caractéristiques principales

  • Performance exceptionnelle : Souvent considérée comme la solution de pool de connexions la plus rapide disponible pour Java
  • Faible empreinte mémoire : Conçue pour être légère et utiliser un minimum de ressources
  • Simplicité : Configuration minimale requise pour démarrer
  • Fiabilité : Gestion robuste des erreurs et récupération automatique
  • Métriques intégrées : Surveillance des performances via JMX

Pourquoi HikariCP est si populaire

  1. Optimisations poussées :
    • Utilisation optimisée des structures de données Java
    • Réduction des contentions grâce à des algorithmes spécifiques
    • Élimination des opérations inutiles présentes dans d'autres pools
  2. Adoption généralisée :
    • Intégré par défaut dans Spring Boot depuis la version 2.0
    • Utilisé par de nombreux frameworks et projets d'entreprise
  3. Configurable mais simple :
    • Fonctionne bien avec les paramètres par défaut
    • Paramètres clairs pour les ajustements avancés

Le nom "Hikari" vient du japonais et signifie "lumière" ou "éclat", ce qui reflète bien la philosophie de cette bibliothèque : être rapide et légère.

Paramètres de configuration de HikariCP avec leurs valeurs par défaut

Voici les principaux paramètres de configuration de HikariCP avec leurs valeurs par défaut :

Paramètres essentiels

  • dataSourceClassName ou jdbcUrl : null (l'un des deux est requis)
  • username : null (requis)
  • password : null (requis)

Paramètres de dimensionnement du pool

  • maximumPoolSize : 10 (nombre maximum de connexions dans le pool)
  • minimumIdle : égal à maximumPoolSize (nombre minimum de connexions inactives)
  • connectionTimeout : 30000 ms (30 secondes, temps d'attente maximum pour une connexion)
  • idleTimeout : 600000 ms (10 minutes, temps maximum d'inactivité d'une connexion)
  • maxLifetime : 1800000 ms (30 minutes, durée de vie maximale d'une connexion)
  • keepaliveTime : 0 ms (désactivé par défaut, intervalle pour tester les connexions inactives)

Paramètres de validation et test

  • connectionTestQuery : null (requête SQL pour valider les connexions, auto-détectée par défaut)
  • validationTimeout : 5000 ms (5 secondes, temps maximum pour tester une connexion)
  • initializationFailTimeout : 1 (temps en ms pour réessayer l'initialisation du pool)
  • isolateInternalQueries : false (isolation des requêtes internes)

Paramètres de performances

  • autoCommit : true (comportement auto-commit des connexions)
  • catalog : driver default (catalogue par défaut pour les connexions)
  • schema : driver default (schéma par défaut pour les connexions)
  • leakDetectionThreshold : 0 (désactivé, temps en ms pour détecter les fuites de connexions)

Paramètres de nom et logging

  • poolName : auto-généré ("HikariPool-#") (nom du pool pour le logging et JMX)
  • registerMbeans : false (enregistrement des MBeans pour monitoring)
  • allowPoolSuspension : false (possibilité de suspendre le pool)

Paramètres de transactions

  • transactionIsolation : null (niveau d'isolation des transactions)
  • readOnly : false (connexions en lecture seule)

Ces paramètres peuvent être configurés soit par programmation via HikariConfig, soit via un fichier de propriétés ou en utilisant les propriétés de Spring Boot si vous utilisez ce framework.

Pour les applications à forte charge, il est souvent recommandé d'ajuster au moins les paramètres maximumPoolSize, connectionTimeout et maxLifetime en fonction des caractéristiques spécifiques de votre application et de votre base de données.


Connexions actives vs connexions inactives dans HikariCP

Connexion active

Une connexion est considérée comme active lorsque :

  • Elle a été empruntée du pool via dataSource.getConnection()
  • Elle est actuellement utilisée par le code applicatif pour exécuter des opérations de base de données
  • Elle n'a pas encore été retournée au pool (pas de connection.close() appelé)

En termes concrets, une connexion active est une connexion qui est "entre les mains" du code applicatif et qui n'est donc pas disponible pour d'autres parties de l'application.

Connexion inactive

Une connexion est considérée comme inactive lorsque :

  • Elle est établie avec la base de données et fonctionnelle
  • Elle est présente dans le pool et prête à être utilisée
  • Elle n'est pas actuellement utilisée par le code applicatif (elle est au repos dans le pool)
  • Elle a été retournée au pool après utilisation via connection.close()

Les connexions inactives sont celles qui sont disponibles immédiatement pour être fournies quand un appel à getConnection() est effectué.

Dans le contexte des paramètres de HikariCP

  • minimumIdle : Nombre minimum de connexions inactives à maintenir dans le pool
  • maximumPoolSize : Nombre total maximum de connexions (actives + inactives)
  • idleTimeout : S'applique uniquement aux connexions inactives qui excèdent minimumIdle
  • maxLifetime : S'applique à toutes les connexions, qu'elles soient actives ou inactives

Exemple pratique

Dans un pool avec maximumPoolSize=20 et minimumIdle=5 :

  • Si 8 connexions sont empruntées (actives), 12 sont inactives dans le pool
  • Si l'application reste peu chargée pendant un temps dépassant idleTimeout, HikariCP peut réduire les connexions inactives jusqu'à 5 (minimumIdle)
  • Lors d'un pic d'activité, si 18 connexions sont empruntées (actives), il reste 2 connexions inactives
  • Si une connexion reste empruntée (active) au-delà de maxLifetime, elle sera marquée pour fermeture dès qu'elle sera retournée au pool

Le suivi de l'état actif/inactif des connexions est une part essentielle de la stratégie de HikariCP pour optimiser les performances et l'utilisation des ressources.

Le cycle de vie des connexions avec HikariCP

Voici une explication détaillée du processus de création et d'utilisation des connexions, du démarrage de l'application jusqu'à l'exécution des requêtes SQL :

1. Initialisation au démarrage de l'application

  • Création du HikariDataSource :

    • L'application instancie un objet HikariConfig avec les paramètres souhaités
    • Un HikariDataSource est créé avec cette configuration
    • Le pool commence son initialisation
  • Remplissage initial du pool :

    • Si minimumIdle > 0, HikariCP commence à établir des connexions
    • Des connexions sont créées jusqu'à atteindre minimumIdle (par défaut égal à maximumPoolSize)
    • Chaque connexion établie passe par le processus complet d'authentification à la base de données

2. Gestion des connexions au repos

  • État d'attente :
    • Les connexions établies restent actives dans le pool
    • Des vérifications périodiques (keepaliveTime si activé) maintiennent les connexions valides
    • Les connexions qui dépassent maxLifetime sont fermées et remplacées, même si elles sont inactives

3. Demande d'une connexion par le code applicatif

  • Appel à getConnection() :

    • L'application demande une connexion via dataSource.getConnection() : dataSource est du type : HikariDataSource
    • HikariCP vérifie d'abord s'il existe une connexion disponible dans le pool
  • Scénarios possibles :

    • Connexion disponible : Une connexion inactive est récupérée du pool et retournée immédiatement
    • Pool plein et actif : Si toutes les connexions sont utilisées mais maximumPoolSize n'est pas atteint, une nouvelle connexion est créée
    • Pool saturé : Si toutes les connexions sont utilisées et maximumPoolSize est atteint, l'application attend qu'une connexion se libère (jusqu'à connectionTimeout) : Si l'exécution de requête dépasse connectionTimeout ,  cela pourra bien engendre un problème de pool de connexion. Plus une requête s'exécute rapidement, plus la connexion est libérée et retournée dans le pool de connexion pour être reetulisée par les requêtes en attente

4. Validation de la connexion

  • Vérification avant utilisation :
    • HikariCP peut tester la validité de la connexion avant de la fournir
    • Si connectionTestQuery est spécifié, cette requête est exécutée pour vérifier que la connexion fonctionne
    • Sans connectionTestQuery, HikariCP utilise la méthode isValid() du JDBC

5. Exécution de la requête SQL

  • Utilisation de la connexion :
    • L'application utilise la connexion pour créer des Statement, PreparedStatement, etc.
    • Les requêtes SQL sont exécutées via ces objets
    • La connexion reste "empruntée" au pool pendant toute l'utilisation

6. Retour de la connexion au pool

  • Libération de la connexion :

    • L'application appelle connection.close()
    • Avec HikariCP, cet appel ne ferme pas réellement la connexion mais la retourne au pool
    • La connexion est marquée comme disponible pour d'autres requêtes
  • Maintenance du pool :

    • Si la connexion a dépassé maxLifetime, elle sera fermée définitivement puis remplacée
    • Si le nombre de connexions inactives dépasse minimumIdle, les connexions excédentaires peuvent être fermées après idleTimeout

Ce cycle se répète pour chaque requête SQL, avec l'avantage que les connexions sont réutilisées plutôt que recréées à chaque fois, ce qui permet d'économiser considérablement les ressources et d'améliorer les performances. Un bon résumé du processus que j'ai lu sur un article publié sur medium :


  1. When a connection is requested to be acquired, the connection pool looks for free connections.
  2. If the pool finds a free connection, it will handle it to the client (no time wasted to open tcp sockets and connection).
  3. If the pool doesn’t have a free connection, it will try to grow to its maximum allowed size (which is configurable).
  4. If the pool has already reached its maximum size, it will retry several times to acquire a connection before throwing an exception if it doesn’t find one.
  5. When the client closes the connection, it is released and returned to the pool without closing the underlying physical connection (big performance gain).

The connection pool does not return the physical connection to the client; instead, it offers a proxy or a handle. When a connection is in use, the pool changes its state to allocated to prevent two concurrent threads from using the same database connection. When the client calls the method to close the connection, the proxy notifies the pool to change the connection state to unallocated so it can be reused again.

Minimum-idle dans HikariCP : utilité et garantie

À quoi sert minimum-idle ?

Le paramètre minimum-idle définit le nombre minimum de connexions inactives que HikariCP doit maintenir dans le pool lorsque l'application est peu sollicitée. Il a plusieurs utilités importantes :

  1. Réduction du temps de latence pour les pics soudains :

    • Garantit qu'un certain nombre de connexions sont toujours prêtes à l'emploi
    • Évite d'avoir à créer de nouvelles connexions (coûteuses) lors d'une augmentation subite du trafic
  2. Équilibre entre ressources et réactivité :

    • Permet d'économiser des ressources en période de faible activité (moins que maximumPoolSize)
    • Maintient un niveau de préparation acceptable pour répondre rapidement aux requêtes
  3. Stabilisation des performances :

    • Réduit les variations de temps de réponse entre périodes calmes et actives
    • Particulièrement utile pour les applications avec un trafic irrégulier

Comment ce nombre est garanti

HikariCP utilise un mécanisme actif pour garantir que le nombre de connexions inactives ne descend pas sous le seuil de minimum-idle :

  1. Thread de maintenance dédié :

    • Un thread séparé surveille en permanence l'état du pool
    • Ce thread s'exécute périodiquement pour vérifier le nombre de connexions inactives
  2. Processus d'ajout de connexions :

    • Si le nombre de connexions inactives tombe en dessous de minimum-idle :
      • Le thread de maintenance crée de nouvelles connexions
      • Ces connexions sont ajoutées au pool à l'état inactif
      • Le processus continue jusqu'à ce que le seuil minimum-idle soit atteint
  3. Mécanisme de remplacement :

    • Si une connexion inactive est invalidée (par exemple, dépassement de maxLifetime)
    • Le thread de maintenance crée automatiquement une connexion de remplacement
  4. Comportement après échec de connexion :

    • Si une tentative de création de connexion échoue, HikariCP réessaie automatiquement
    • Un backoff exponentiel est appliqué pour éviter de surcharger la base de données

Si minimum-idle est défini à une valeur inférieure à maximumPoolSize (la valeur par défaut est égale à maximumPoolSize), HikariCP peut réduire le nombre de connexions pendant les périodes d'inactivité, pour ensuite augmenter ce nombre quand l'activité reprend, tout en garantissant qu'il y aura toujours au moins minimum-idle connexions disponibles immédiatement.

Différence entre idleTimeout et maxLifetime dans HikariCP

Ces deux paramètres contrôlent le cycle de vie des connexions dans le pool, mais à des fins différentes :

idleTimeout

  • Définition : Durée maximale (en millisecondes) pendant laquelle une connexion peut rester inactive dans le pool avant d'être fermée.
  • Valeur par défaut : 600 000 ms (10 minutes)
  • Objectif : Libérer les ressources inutilisées en période de faible charge
  • Comportement : S'applique uniquement quand le nombre de connexions est supérieur à minimumIdle

maxLifetime

  • Définition : Durée de vie maximale (en millisecondes) d'une connexion dans le pool, qu'elle soit active ou inactive.
  • Valeur par défaut : 1 800 000 ms (30 minutes)
  • Objectif : Éviter les problèmes liés aux connexions trop anciennes (fuites de mémoire, déconnexions côté serveur)
  • Comportement : S'applique à toutes les connexions, indépendamment de leur état d'utilisation

Lien entre les deux paramètres

  1. Hiérarchie d'application :

    • maxLifetime est toujours prioritaire sur idleTimeout
    • Une connexion sera fermée si elle atteint sa durée de vie maximale, même si elle n'a pas atteint son temps d'inactivité
  2. Complémentarité :

    • idleTimeout gère l'efficacité des ressources en période de faible charge
    • maxLifetime gère la stabilité et la sécurité du pool sur la durée
  3. Recommandations pratiques :

    • maxLifetime devrait toujours être inférieur au timeout de la base de données
    • idleTimeout devrait être configuré en fonction des patterns d'utilisation de l'application

Par exemple, si une connexion est inactive depuis 8 minutes et que idleTimeout est de 10 minutes, mais que cette connexion a une durée de vie totale de 29 minutes avec maxLifetime à 30 minutes, c'est maxLifetime qui déclenchera sa fermeture en premier.

Ces deux paramètres travaillent ensemble pour maintenir un pool de connexions sain, en équilibrant la disponibilité immédiate des connexions, l'utilisation des ressources et la fiabilité du système.

Un bon exemple est expliqué ici :

For example, let’s assume the value of maximum-pool-size is 8 and minimum-idle is 4. The Spring Boot application needs to perform database operations for 6 concurrent threads. Thus, the Spring Boot application establishes 6 actual connections with the database. When all the database-related tasks are performed for the 6 threads, there will be 6 idle connections in the pool. Now, HikariCP will check what is the value of the minimum-idle property and try to adjust the number of idle connections in the pool. In this example, the value of minimum-idle is 4, so HikariCP will remove 2 idle connections from the pool to make the number of idle connections equal to 4. But before removing the required number of idle connections from the pool, HikariCP will keep those extra connections in the pool till the time given in the idle-timeout. A connection will never be retired as idle before this timeout. A value of 0 means that idle connections are never removed from the pool. The minimum allowed value is 10000 milliseconds (10 seconds). The default value is 600000 milliseconds (10 minutes).

PS : Fermeture de connexion physique et non physique

L'appel à la méthode connection.close() dans le contexte d'un pool de connexions comme HikariCP ne ferme pas réellement la connexion physique à la base de données.

Voici ce qui se passe réellement lorsque vous appelez connection.close() :

  1. La connexion n'est pas fermée physiquement - HikariCP intercepte cet appel et, au lieu de fermer la connexion TCP/IP avec la base de données, il :

    • Remet à zéro l'état de la connexion (rollback des transactions non validées, fermeture des statements ouverts)
    • Marque la connexion comme "inactive" ou "disponible"
    • Replace la connexion dans le pool pour qu'elle puisse être réutilisée
  2. C'est un "retour au pool" - C'est pour cette raison qu'on dit souvent que l'on "retourne" la connexion au pool plutôt que de la "fermer"

  3. Cas où la connexion peut être vraiment fermée :

    • Si la connexion a dépassé son maxLifetime
    • Si un problème a été détecté sur la connexion
    • Si le pool est en train d'être fermé (shutdown)

C'est justement ce mécanisme qui permet au pool de connexions d'être efficace : les connexions physiques coûteuses à établir sont maintenues ouvertes et réutilisées, tandis que le code applicatif peut continuer à utiliser l'API JDBC standard avec connection.close() sans avoir à se préoccuper de la gestion du pool.

Impact des connexions inactives sur les performances et ressources

Les connexions inactives dans un pool comme HikariCP ont plusieurs impacts sur les performances et la consommation de ressources :

Consommation de ressources

  1. Mémoire côté application :

    • Chaque connexion inactive consomme de la mémoire (généralement 0,5 à 2 Mo par connexion)
    • Structures internes, buffers, métadonnées de session
  2. Ressources côté serveur de base de données :

    • Chaque connexion, même inactive, maintient un processus/thread sur le serveur
    • Consommation de mémoire pour les buffers, caches de requêtes, etc.
    • Utilisation de descripteurs de fichiers et sockets réseau
  3. Trafic réseau de maintenance :

    • Paquets keep-alive pour maintenir les connexions TCP ouvertes
    • Requêtes de validation si keepaliveTime est configuré

Impact sur les performances

  1. Avantages :

    • Disponibilité immédiate pour traiter des pics de charge
    • Élimination du temps d'établissement des connexions (souvent 10-100ms)
    • Stabilité des temps de réponse (moins de variations)
  2. Inconvénients :

    • Saturation possible des ressources serveur avec trop de connexions
    • Risque de dépassement des limites du serveur de base de données
    • Contention potentielle sur les ressources partagées

Équilibre optimal

Le paramétrage idéal dépend de plusieurs facteurs :

  • Charge de l'application : Nombre et fréquence des requêtes
  • Capacité du serveur de base de données : Nombre maximal de connexions supportées
  • Pattern d'utilisation : Stable vs pics de charge importants

Un trop grand nombre de connexions inactives peut diminuer les performances globales du système en consommant inutilement des ressources, tandis qu'un nombre trop faible peut entraîner des latences lors des pics de charge.

Recommandations pratiques

  • Configurez minimumIdle inférieur à maximumPoolSize pour les applications à trafic variable
  • Surveillez les métriques de votre pool (taux d'utilisation, temps d'attente)
  • Pour les petites applications, commencez avec des valeurs modestes (5-10 connexions maximum)
  • Pour les applications à forte charge, faites des tests de charge pour déterminer les valeurs optimales

L'objectif est d'avoir juste assez de connexions inactives pour gérer les variations normales de charge, sans gaspiller de ressources.

vendredi 26 mars 2021

Kubernetes: Tips for CKAD exam by CNCF

 

Après avoir suivi quelques formations et de pratique de Kubernetes dans le cadre de mon travail, j’ai décidé de passer le certification CKAD de la CNCF afin de valider mes compétences.





Avant d’utiliser Vim, il faut le paramétrer afin d'éditer au mieux les fichiers YAML.

On édite le fichier  .vimrc :

vi ~/.vimrc :


Vous pouvez créer de déploiement depuis le manifest d'un pod. Il suffit de copier depuis la partie metatdata du pod et copier dans : deploy.spec.template.metadata

Dans cet exemple, il suffit de tapper : début de ligne du pod, fin de ligne du pod s, /^/ le nombre d'espaces pour le bon formatage : 17,53s/^/     /



Vous pouvez suivre la formation Udemy qui m'a été très utile pour mes préparatifs :

https://www.udemy.com/course/certified-kubernetes-application-developer/

Pour vous entrainer :

  •  https://killer.sh/
  • https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552
  • https://github.com/bmuschko/ckad-crash-course/tree/master/exercises
  • https://github.com/dgkanatsios/CKAD-exercises

Quelques commandes très utiles :

  • kubectl explain
  • kubectl api-resources

Mes liens favoris : Vous pouvez créer de bookmark  et installer ce plugin chrome permettant d'effectuer de recherches dans vos bookmarks (en tapant bm puis entrer dans la barre de recherche)  :

https://chrome.google.com/webstore/detail/bookmark-search/hhmokalkpaiacdofbcddkogifepbaijk

Les URLs :

A lire absolument si vous voulez comprendre en profondeur ! : Kubernetes in Action écrit par Marko Luksa aux éditions Manning.

https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/

https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-command

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod

https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/#concepts

https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#define-a-container-environment-variable-with-data-from-a-single-configmap

https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables

https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume

https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment

https://kubernetes.io/docs/concepts/workloads/controllers/job/#running-an-example-job

https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#example

https://kubernetes.io/docs/concepts/services-networking/service/#nodeport

https://kubernetes.io/docs/concepts/services-networking/network-policies/#networkpolicy-resource

https://kubernetes.io/docs/concepts/services-networking/ingress/

https://kubernetes.io/fr/docs/reference/kubectl/cheatsheet/

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

https://kubernetes.io/docs/concepts/services-networking/service/

https://kubernetes.io/docs/concepts/storage/storage-classes/

https://kubernetes.io/docs/concepts/storage/persistent-volumes/

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims

https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/

https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/

https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/

https://kubernetes.io/fr/docs/tasks/access-application-cluster/list-all-running-container-images/

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

https://kubernetes.io/fr/docs/tasks/configure-pod-container/configure-service-account/

https://kubernetes.io/docs/reference/access-authn-authz/rbac/

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/

https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/

https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/

https://kubernetes.io/docs/concepts/services-networking/network-policies/

https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

https://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#scale

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#rollout

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#exec

https://kubernetes.io/docs/concepts/workloads/pods/

https://kubernetes.io/fr/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

https://kubernetes.io/docs/tasks/job/coarse-parallel-processing-work-queue/

https://kubernetes.io/docs/concepts/workloads/controllers/job/

https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/

https://kubernetes.io/fr/docs/tasks/configure-pod-container/assign-pods-nodes/

https://kubernetes.io/fr/docs/concepts/storage/volumes/

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-configmap-em-

https://kubernetes.io/docs/tutorials/configuration/configure-redis-using-configmap/

https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/

https://kubernetes.io/docs/tutorials/stateful-application/cassandra/

https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/

https://kodekloud.com/courses/kubernetes-certification-course-labs/lectures/12039471

https://github.com/kubernetes/website/blob/master/content/en/examples/windows/emptydir-pod.yaml

https://kubernetes.io/blog/2016/07/autoscaling-in-kubernetes/

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/

https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

https://github.com/kubernetes/website/blob/master/content/en/examples/application/wordpress/wordpress-deployment.yaml

https://github.com/kubernetes/website/tree/master/content/en/examples/pods

https://github.com/kubernetes/website/blob/master/content/en/examples/application/job/rabbitmq/job.yaml

https://kubernetes.io/docs/concepts/cluster-administration/logging/

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/

https://kubernetes.io/docs/tutorials/services/source-ip/

https://kubernetes.io/docs/tutorials/stateless-application/guestbook/

https://github.com/kubernetes/website/blob/master/content/en/examples/service/networking/nginx-secure-app.yaml

https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#job-v1-batch

https://kubernetes.io/docs/concepts/storage/volumes/

vendredi 31 mai 2019

Scala implicit

Notion implicit en scala

La notion implicit de scala permet de faire : 
  • de passer automatiquement de paramètre à une méthode/fonction
  • de la conversion automatique;
  • d'ajouter de comportement dynamiquement à une classe.

Paramètre implicit


Un paramètre implicit injecté dynamiquement. La méthode sendMail dispose d'un paramètre from implicit. 


Lors qu’un paramètre d’une méthode/fonction est défini comme implicite, il n’est plus nécessaire de le spécifier lors de l’appel : le compilateur se charge de le déduire à partir du contexte.

À noter que, dans la signature d’une méthode, le mot clé implicit ne sert pas à déclarer un paramètre mais une liste de paramètres. Tous les paramètres implicites doivent être définis dans « la même paire de parenthèse ». Tous les paramètres suivant le mot clé seront donc des implicites  (dans l'exemple ci-dessus, body et from sont implicits)


On pourra bien appeler sendMail avec le paramètre from explicitement :



 ou déclarer  le paramètre from implicit de 3 manières : 

  • val 

  • def



  • object class si le paramètre est une structure complexe.


Il faudra noter :
  • la correspondance entre le paramètre implicite de la méthode sendMail et la variable est indépendante de leurs noms. Le compilateur utilise le type commun String pour lier from et sender,
  • deux variables implicites de même type dans la même portée provoquent une erreur de compilation, à la première utilisation. Dans notre exemple, on ne pourra pas avoir deux variables implicits de types String,
  • Pour pouvoir appeler la méthode sans le paramètre implicit depuis un autre fichier, il faudra faire import de l'object dans lequel le paramètre implicit est défini.

Conversion automatique


Cela consiste à définir une méthode de conversion implicit d'un type A à un type B. Le compilateur se charge d'appeler et effectuer automatiquement la conversion si nécessaire. Imaginons qu'on dispose d'une méthode show prenant en paramètre un type String :


Pour pouvoir appeler cette méthode avec les paramètres : Int, Double ou Float ou tout autre type, il faudra définir de méthodes implicit permettant de convertir Int en String, Double en String et Float en String :



Ajout d'un comportement dynamiquement à une classe


C'est une fonctionnalité proche de l'extension C#. Elle permet d'ajouter dynamiquement une nouvelle méthode à une classe existante. Prenons l'exemple du type String. On voulait ajouter une nouvelle méthode isPalindrome permettant de savoir si un String est un palindrome ou une autre méthode isQuestion pour savoir si une chaine de caractère est une question. Cela revient à faire :



Il suffit de définir une classe implicit avec un constructeur prenant en paramètre un String et définir les deux méthodes isPalindrome, isQuestion dans cette classe.


Une fois cette classe définie, il suffit de faire un import de RicheType pour pouvoir appeler les méthodes isPalindrome, isQuestion sur le type String


On pourra effectuer la même chose pour d'autres types notamment de type custom Person ...







mercredi 29 mai 2019

Scala : Structural types, rename import, type alias

Renommer import

On dispose d'import static en Java. Scala nous offre la possibilité de renommer les classes ainsi que les méthodes statiques importées. Un exemple vaut mieux qu'un long discours ...

Renommer une classe importée




Renommer une méthode statique importée

Type alias

Un type alias permet de renommer un type existant permettant ainsi d'éviter les ambiguïtés ...Dans cet exemple, on dispose d'une classe CommandLine qu'on pourrait définir ainsi :



Grâce aux alias, on peut avoir un code plus clair et parlant !!


Ici, on a renommé les types Int et Flot en Quantity et Price mieux parlant ...

Structural Types

L'idée de Structural Types est de pouvoir exprimer un type non pas en le déclarant comme une interface, une classe ou un Trait, mais plutôt en affirmant que le type doit posséder un comportement particulier (une méthode, fonction ...). Structural Type nous rappelle de duck typing utilisé dans plusieurs langages de programmation, tels que  Ruby. Le principe de duck typing est simple :
If it walks like a duck and quacks like a duck, it must be a duck (si ça marche comme un canard et si ça cancane comme un canard, alors ça doit être un canard)

Du coup, connaître le type même d'une valeur n'a aucune importance, il faut avant tout s'assurer qu'on peut lui appliquer les traitements souhaités.

Dans cet exemple, on définit une méthode doTalk qui prend en paramètre tout type ayant une méthode talk définie qu'il y ait ou non une relation d'héritage ou une interface commune entre les types. Cette méthode talk doit être sans paramètre et retourner un type String



Les deux classes Cat et Dog ont la méthode talk définie et peuvent donc être passées comme paramètre à la méthode doTalk. Par contre la classe Fake n'ayant pas la méthode talk définie
ne peut être passée à la méthode doTalk.



Il est également possible de définir un type alias et faire référence à cet alias comme paramètre de la méthode doTalk comme dans l'exemple ci-dessus :


   

lundi 27 mai 2019

Scala : Object-private and Package scope

Object-private scope : private[this]


En Scala comme en Java, l'accessibilité private donne le droit d'accès à un attribut privé d'une autre instance au sein de la même classe. Clarifions par un exemple... Dans l'exemple ci-dessus, la méthode m peut bien accéder à l'attribut value de l'objet Counter malgré que cet attribut soit déclaré privé. Ce comportement est normal car on est toujours au sein de la classe Counter


Comment peut-on empêcher qu'un attribut privé ne soit accessible que par  l'instance courante de l'objet ? Cela revient à générer une erreur de compilation à la ligne 12  other.value 

Scala nous offre une restriction supplémentaire qu'on appelle object-private scope. Il suffit de déclarer l'attribut comme private[this]. Le mot clé this indique que l'attribut n'est accessible que par l'instance courante. On remarque une erreur de compilation lorsque l'attribut value est déclaré  private[this]



Package scope

L'accessibilité private[nomPackage] donne le droit d'accès à une méthode ou un attribut depuis le package nomPackage et ses sous packages. Dans l'exemple ci-dessus, la méthode doX est déclarée comme private[scala] et donc accessible depuis le package scala contrairement à la méthode privée doY accessible uniquement au sein de la classe Foo



Dans le package other, ni doX ni doY n'est accessible depuis la classe Quux


case class vs case object



Case class


Une case classe est définie avec le mot clé case


Elle peut être instanciée sans le mot clé new. Cela est possible car scala génère automatiquement une classe qu’on appelle object companion ayant le même nom (Person) contenant deux méthodes :
§  apply : qui construit un objet via les paramètres de construction et
§  unapply : qui de-construit l’objet qu’on appelle également extracteur (extraction des attributs via l’objet)

Lors de l’appelle d’instanciation de Person(…) ; on fait appel à la méthode Person.apply.

Les cases classes sont serializables par défaut avec les méthodes toString, copy, equals (sur les attributs), hashCode implémentées …




Par défaut les attributs sont immutables (val) et publiques. Il est possible d’avoir des attributs mutables avec le mot clé var ou réduire la visibilité ..


Case object


Les cases objects sont équivalentes de cases classes n’ayant pas d’attributs de construction ; elles sont singletons et serializables avec une implémentation hashCode (à la différence des objects companions). Une case object permet par exemple de créer des enums, des messages Akka …