InfiniSpan

Introducción

Infinispan es un almacén de datos clave/valor en memoria que ofrece un conjunto de características más robusto que otras herramientas del mismo nicho.

Proporciona un almacén de datos flexible en memoria que puede configurar para adaptarse a casos de uso como:

  • Mejorando el rendimiento de la aplicación con cachés locales de alta velocidad.

  • Optimización de bases de datos mediante la disminución del volumen de operaciones de escritura.

  • Proporcionando resiliencia y durabilidad para datos consistentes a través de clústeres.

Canales de Soporte

Infinispanel soporte se presenta en dos formas,https://stackoverflow.com/questions/tagged/infinispan[stackoverflow] es el primer lugar donde buscar posibles soluciones. Si eso falla, hay un servicio a medida ZULIP configuración del canal de chat que le pondrá en contacto directo con Infinispan guru’s.

Infinispan Configuración

El CacheManager es la base de la mayoría de las características que utilizaremos. Actúa como un contenedor para todas las cachés declaradas, controlando su ciclo de vida, y es responsable de la configuración global.

Infinispannaves con una forma realmente fácil de construir el CacheManager:

    @Bean
    InfinispanCacheProvider infinispanCacheProvider(final Marshaller marshaller) {
        var configuration = kubernetesStack
                ? buildClusteredConfigurationForKubernetes(marshaller)
                : buildDefaultClusteredConfiguration(marshaller);
        var cacheManager = new DefaultCacheManager(configuration);
        return new InfinispanCacheProvider(cacheManager, settings);
    }

    private GlobalConfiguration buildClusteredConfigurationForKubernetes(Marshaller marshaller) {
        return GlobalConfigurationBuilder.defaultClusteredBuilder()
                .cacheManagerName(cacheManagerName)
                .transport()
                .addProperty("stack", "kubernetes")
                .addProperty("configurationFile", "default-configs/default-jgroups-kubernetes.xml")
                .initialClusterSize(initialClusterSize)
                .initialClusterTimeout(initialClusterTimeout.getSeconds(), TimeUnit.SECONDS)
                .serialization()
                .marshaller(marshaller)
                .build();
    }

    private GlobalConfiguration buildDefaultClusteredConfiguration(Marshaller marshaller) {
        return GlobalConfigurationBuilder.defaultClusteredBuilder()
                .cacheManagerName(cacheManagerName)
                .transport()
                .initialClusterSize(initialClusterSize)
                .initialClusterTimeout(initialClusterTimeout.getSeconds(), TimeUnit.SECONDS)
                .serialization()
                .marshaller(marshaller)
                .build();
    }

Una caché se define por un nombre y una configuración. La configuración necesaria puede ser construida utilizando la clase ConfigurationBuilder, ya disponible en nuestro classpath.

El ConfigurationBuilder se proporciona con el siguiente método:

    private Cache<Object, Object> buildInfinispanCache(final String name, final InfinispanCacheSetting infinispanCacheSetting) {
        log.info("Cache {} specified timeout of {} min, max of {}", name, infinispanCacheSetting.getTimeout(),
                infinispanCacheSetting.getMaxSize());

        var configBuilder = new ConfigurationBuilder();
        var cacheMode = CacheMode.valueOf(infinispanCacheSetting.getCacheMode());

        configBuilder.clustering()
                .cacheMode(cacheMode)
                .encoding().mediaType("application/json")
                .memory()
                .maxCount(infinispanCacheSetting.getMaxSize())
                .whenFull(EvictionStrategy.REMOVE)
                .expiration()
                .lifespan(infinispanCacheSetting.getTimeout().toMillis(), TimeUnit.MILLISECONDS);

        if (isRemote(cacheMode)) {
            configBuilder.clustering()
                    .stateTransfer().fetchInMemoryState(infinispanCacheSetting.getFetchInMemoryState())
                    .awaitInitialTransfer(infinispanCacheSetting.getAwaitInitialStateTransfer())
                    .timeout(infinispanCacheSetting.getStateTransferTimeout().toMillis());
        }

        if (cacheMeterRegister.metricsEnabled()) {
            configBuilder.statistics().enable();
        }

        final Cache<Object, Object> cache = cacheManager.administration().withFlags(CacheContainerAdmin.AdminFlag.VOLATILE)
                .getOrCreateCache(name, configBuilder.build());

        if (cacheMeterRegister.metricsEnabled()) {
            cacheMeterRegister.bind(cache);
        }

        setCacheLevelLogging(cache, name, cacheMode, infinispanCacheSetting);
        setClusterLevelLogging(cacheMode, infinispanCacheSetting);
        return cache;
    }

    private void setCacheLevelLogging(final Cache<Object, Object> cache, final String cacheName, final CacheMode cacheMode,
                                      final InfinispanCacheSetting infinispanCacheSetting) {

        if (isRemote(cacheMode) && infinispanCacheSetting.getClusterLogging()) {
            cache.addListener(new ClusterCacheLoggingListener(cacheName));
        }
        if (infinispanCacheSetting.getLocalLogging()) {
            cache.addListener(new LocalCacheLoggingListener(cacheName));
        }
    }

    private void setClusterLevelLogging(final CacheMode cacheMode, final InfinispanCacheSetting infinispanCacheSetting) {

        if (isRemote(cacheMode) && isLoggingEnabled(infinispanCacheSetting)) {
            cacheManager.addListener(new ClusterLoggingListener());
        }
    }

    private boolean isLoggingEnabled(final InfinispanCacheSetting infinispanCacheSetting) {
        return infinispanCacheSetting.getClusterLogging() || infinispanCacheSetting.getLocalLogging();
    }

    private boolean isRemote(final CacheMode cacheMode) {
        return cacheMode.isDistributed() || cacheMode.isReplicated();
    }

Toda la documentación sobre cómo configurar un Infinispan la caché está disponible aquí.

Todo el beans mencionado anteriormente lo obtenemos de forma gratuita al agregar la dependencia de maven mencionada antes.

Sin embargo, el Infinispan el caché requiere los siguientes valores de configuración para cada caché que se proporciona;

ipf.caching.infinispan.settings."${cache_name}".cache-mode=[CacheMode]
ipf.caching.infinispan.settings."${cache_name}".timeout=[Duration]
ipf.caching.infinispan.settings."${cache_name}".max-count=[Long]
ipf.caching.infinispan.settings."${cache_name}".cluster-logging=[Boolean]
ipf.caching.infinispan.settings."${cache_name}".local-logging=[Boolean]
  • cache_name - nombre de la caché que se está utilizando

  • cache-mode - Infinispan Los administradores de caché pueden crear y controlar múltiples cachés que utilizan diferentes modos. Por ejemplo, puede utilizar el mismo administrador de caché para cachés locales, cachés distribuidos y cachés con modo de invalidación.

  • timeout - La duración de la caché permanecerá en memoria activa antes de ser desalojada.

  • max-count - especifique el número total de entradas que las cachés pueden contener antes de Infinispan realiza desalojo

  • cluster-logging - instancia un ClusterCacheLoggingListener

  • local-logging - instancia un LocalCacheLoggingListener

Un ejemplo:

ipf.caching.infinispan.settings.cache1.cache-mode=REPL_ASYNC
ipf.caching.infinispan.settings.cache1.timeout=15m
ipf.caching.infinispan.settings.cache1.max-count=15000
ipf.caching.infinispan.settings.payment-data.cluster-logging=true
ipf.caching.infinispan.settings.payment-data.local-logging=true
  • cache-mode - puede configurarse en uno de los siguientes:

    • LOCAL - Los datos no se replican.

    • REPL_ASYNC - Datos replicados de manera asíncrona

    • REPL_SYNC - Datos replicados de manera sincrónica

    • DIST_SYNC

    • DIST_ASYNC

En caso de que el modo de caché sea distributed or replicated, se requiere la siguiente configuración adicional:

ipf.caching.infinispan.settings."${cache_name}".fetch-in-memory-state=[Boolean]
ipf.caching.infinispan.settings."${cache_name}".await-initial-state-transfer=[Boolean]
ipf.caching.infinispan.settings."${cache_name}".state-transfer-timeout=[Duration]
ipf.caching.infinispan.settings."${cache_name}".global-state-persistence-location=[String]

Más detalles sobre los campos:

  • fetch-in-memory-state - Si es cierto, la caché obtendrá datos de las cachés vecinas al iniciarse, por lo que la caché comienza 'caliente', aunque esto afectará el tiempo de inicio. En modo distribuido, el estado también se transfiere entre las cachés en ejecución, ya que la propiedad de las claves cambia (por ejemplo, porque una caché salió del clúster). Deshabilitar esta configuración significa que una clave a veces tendrá menos de numOwner propietarios.

  • await-initial-state-transfer - Si es cierto, esto causará la primera llamada al método CacheManager.getCache() en el nodo unidor para bloquear y esperar hasta que la unión esté completa y la caché haya terminado de recibir el estado de las cachés vecinas (si fetchInMemoryState está habilitado). Esta opción se aplica únicamente a cachés distribuidas y replicadas y está habilitada por defecto. Tenga en cuenta que establecer esto en falso hará que el objeto de caché esté disponible de inmediato, pero cualquier acceso a claves que deberían estar disponibles localmente pero que aún no se han transferido causará en realidad un acceso remoto (transparente). Si bien esto no tendrá ningún impacto en la lógica de su aplicación, podría afectar el rendimiento.

  • state-transfer-timeout - Este es el tiempo máximo.- en milisegundos-esperar el estado de las cachés vecinas, antes de lanzar una excepción y abortar el inicio.

  • global-state-persistence-location - Esta es la ubicación para persistir el estado global de los nodos. dentro de un clúster, solo relevante en implementaciones de kubernetes. Tiene un valor predeterminado de "java.io.tmpdir". Si la persistencia está habilitada para una caché, este valor DEBE ser siempre la carpeta principal de los datos de persistencia. y ubicaciones de índice. Esta ubicación DEBE sobrevivir a un reinicio, en Kubernetes un PVC por ejemplo.

Un ejemplo:

ipf.caching.infinispan.settings.cache1.fetch-in-memory-state=true
ipf.caching.infinispan.settings.cache1.await-initial-state-transfer=true
ipf.caching.infinispan.settings.cache1.state-transfer-timeout=6m
ipf.caching.infinispan.settings.cache1.global-state-persistence-location=/cache

Infinispan Persistencia

Si es necesario, es posible utilizar el almacenamiento de archivos para proporcionar una caché persistente. Para utilizar esta función, es necesario proporcionar las siguientes configuraciones obligatorias:

ipf.caching.infinispan.settings.cache1.persistence.enabled=true (1)
ipf.caching.infinispan.settings.cache1.persistence.data-location=/cache/data (2)
ipf.caching.infinispan.settings.cache1.persistence.index-location=/cache/index (3)
1 Aquí habilitamos las características persistentes estableciendo la bandera de habilitación en verdadero; si no se establece o es falso, la persistencia permanecerá desactivada.
2 Aquí definimos la ruta a la carpeta en la que deseamos almacenar los datos para respaldar la caché.
3 Aquí definimos la ruta a la carpeta en la que se deben almacenar los índices para la caché.
Los valores asignados a los datos y ubicaciones de índice. Son subdirectorios de /cache que es la ubicación asignada a global-state-persistence-location arriba. Si este no es el caso, verá errores en el registro como el que se muestra a continuación.
ISPN000558: "The store location 'foo' is not a child of the global persistent location 'bar'"

Además, hay propiedades de configuración opcionales adicionales para la caché persistente:

ipf.caching.infinispan.settings.cache1.persistence.shared= (1)
ipf.caching.infinispan.settings.cache1.persistence.preload=true (2)
ipf.caching.infinispan.settings.cache1.persistence.purgeOnStartup= (3)
ipf.caching.infinispan.settings.cache1.persistence.maxFileSize=16777216 (4)
ipf.caching.infinispan.settings.cache1.persistence.compactionThreshold=0. 5 (5)
1 Esta configuración debe establecerse en verdadero cuando múltiples instancias de caché compartan el mismo almacén de caché (por ejemplo, múltiples nodos en un clúster que utilizan un JDBC basado en CacheStore apuntando a la misma base de datos compartida.) Establecer esto en verdadero evita que múltiples instancias de caché escriban la misma modificación múltiples veces. Si está habilitado, solo el nodo donde se originó la modificación escribirá en el almacén de caché. Si está deshabilitado, cada caché individual reacciona a una posible actualización remota almacenando los datos en el almacén de caché.
2 Si es cierto, cuando se inicia la caché, los datos almacenados en el almacén de caché se cargarán previamente en la memoria. Esto es particularmente útil cuando los datos en el almacén de caché se necesitarán inmediatamente después del inicio y usted desea evitar que las operaciones de caché se retrasen como resultado de cargar estos datos de manera perezosa. Puede utilizarse para proporcionar una 'caché caliente' al inicio; sin embargo, hay una penalización en el rendimiento, ya que el tiempo de inicio se ve afectado por este proceso. Por defecto, se establece en verdadero
3 Si es cierto, purga este almacén de caché cuando se inicia.
4 Tamaño máximo de un solo archivo con entradas, en bytes. Por defecto es 16777216
5 Si la cantidad de espacio no utilizado en algún archivo de datos supera este umbral, el archivo se compacta.- Las entradas de ese archivo se copian a un nuevo archivo y el archivo antiguo se elimina. Por defecto, se establece en 0. 5
maxFileSize y compactionThreshold son configuraciones útiles si se modifica la misma entrada de caché con frecuencia; reduzca el umbral de compactación o reduzca el tamaño máximo del archivo para provocar compactaciones más frecuentes del archivo de almacenamiento de archivos. Típicamente, se lanza una excepción "Demasiados registros para esta clave (desbordamiento corto)" para indicar que se necesita un ajuste de cualquiera de estas configuraciones. Esto es particularmente relevante en el caso en que hay una gran cantidad de actualizaciones secuenciales (> 32, 767) a una única clave de caché que tiene un conjunto de datos pequeño, creando así una situación en la que no ocurre ninguna compactación. No hay una regla general aquí, aparte de entender que la compactación frecuente es algo positivo. Nota: La excepción anterior resultará en el fallo del compactador y en una acumulación de archivos en el sistema de archivos, por lo que vale la pena dedicar tiempo a comprender la necesidad. Este es un problema que se puede evitar en gran medida.
Nunca utilice almacenes de caché basados en el sistema de archivos en sistemas de archivos compartidos, como un NFS o un recurso compartido de Samba, porque no proporcionan capacidades de bloqueo de archivos y puede ocurrir corrupción de datos.

Infinispan Implementación

Obtenemos el CacheFactory bean gratis de ipf-cache-infinispan módulo y habilitando la caché infinispan.

    @Bean(name = "infinispanCacheFactory")
    CacheFactory<?, ?> infinispanCacheFactory(InfinispanCacheProvider infinispanCacheProvider, CacheLogger<Object, Object> cacheLogger) {
        return new InfinispanCacheFactory(infinispanCacheProvider, cacheLogger);
    }

Entonces, solo necesita utilizar el CacheFactory para crear ya sea un AsyncCacheAdapter:

        @Bean(name = "paymentInfinispanDataCacheAdapter1")
        AsyncCacheAdapter<Object, Object> paymentInfinispanDataCacheAdapter1(CacheFactory<Object, Object> infinispanCacheFactory) {
            return infinispanCacheFactory.asyncCreateCacheAdapter("cache1");
        }

Infinispan Cache Embedded Agrupación Activar Kubernetes

Para crear un clúster embebido de infinispan basado en kubernetes, usted DEBE habilitar kubernetes configurando la siguiente propiedad.

ipf.caching.infinispan.settings.cache1.kubernetes-stack=true

esto es importante para garantizar la correcta CacheManager la configuración está en su lugar.

La mayoría de las cargas de trabajo desplegadas en Kubernetes (la misma lógica se aplicará a OpenShift) están utilizando un Despliegue manifest. Este enfoque es perfectamente aceptable si la caché infinispan no se está persistiendo en el almacenamiento local. Si existe un requisito de persistencia, el enfoque recomendado es utilizar un StatefulSet. Para ser claro, esto no es porque las cargas de trabajo de implementación no puedan tener persistencia subyacente. Más bien, se debe a que los Statefulsets provisionan volúmenes únicos por instancia, lo cual es lo que se requeriría para un clúster de caché. Un pod de implementaciones, en contraste, compartiría un único volumen entre el pod.

Un ejemplo de Statefulset con una sección de plantilla de reclamo de volumen para configurar la persistencia. Tenga en cuenta la inclusión de la definición de puerto 7800, esto es obligatorio para facilitar JGROUPS, que se discute después del ejemplo.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: ipf-cache-infinispan
spec:
  selector:
    matchLabels:
      app: ipf-cache-infinispan
  serviceName: "ipf-cache-infinispan"
  replicas: 3
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: ipf-cache-infinispan
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: ipf-cache-infinispan
        image:registry.k8s.io/ipf-cache-infinispan:0. 1. 0
        env:
          - name: IPF_JAVA_ARGS
            value: "-Dconfig.override_with_env_vars=true -Djgroups.dns.query=ipf-cache-infinispan.mynamespace.svc.cluster.local"
          - name:
        ports:
        - containerPort: 7800
          name: dns-ping-containerPort: 808
          name: html-containerPort: 5005
          name: app
        volumeMounts:
        - name: ipf-cache-infinispan
          mountPath: /tmp/data-name: ipf-cache-infinispan
          mountPath: /tmp/index
  volumeClaimTemplates:
  - metadata:
      name: ipf-cache-infinispan
    spec:
      accessModes: [ "ReadWriteMany" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 10Gi

Tenga en cuenta la referencia a un servicio llamado " ipf-cache ". En el contexto de infinispan, es importante que el servicio sea sin cabeza, lo que significa que NO se asignará ninguna clusterIP. La razón detrás de esto se relaciona con el uso de" JGROUPS dentro de infinispan y más específicamente el protocolo de descubrimiento de clúster JGROUPS DNS_PING que es preferido para el descubrimiento de clústeres en entornos de kubernetes. Tenga en cuenta también la propiedad del sistema que se está pasando a la variable de entorno "IPF_JAVA_ARGS". La propiedad del sistema jgroups.dns.query se documenta como una anulación aceptable para cualquier configuración predeterminada proporcionada a jGROUPS. El valor asignado es el habitual DNS interno de kubernetes asignado a un servicio en el formato "myservicename.mynamespace.svc.cluster.local"

un ejemplo de configuración de servicio sin cabeza para el Statefulset anterior es el siguiente, la definición del puerto 7800 es una edición obligatoria en todas las definiciones de servicio. Esto habilitó JGROUPS. La inclusión de la configuración adicional publishNotReadyAddresses: true también se recomienda. Esto permite a JGROUPS encontrar miembros adicionales del clúster y formar el clúster de caché antes de que el servicio esté en un estado de "listo".

Se recomienda ENCARECIDAMENTE que el servicio JGROUPS de kubernetes se defina dentro de su propio manifiesto que gestione únicamente el puerto 7800. Esto es particularmente pertinente cuando se involucran clústeres de akka.
apiVersion: v1
kind: Service
metadata:
  name: ipf-cache-infinispan
  labels:
    app: ipf-cache-infinispan
spec:
  ports:
    - name: jgroup
      port: 7800
      protocol: TCP
      targetPort: 7800
  clusterIP: None
  publishNotReadyAddresses: true
  selector:
    app: ipf-cache-infinispan

Infinispan Cluster Global State

Al configurar kubernetes-stack=true, el estado global de la CacheManager se habilita entonces en infinispan. El estado global de un nodo es vital para cualquier clúster de caché. Cuando un nodo del clúster se detiene de manera controlada, el estado del nodo se persiste a medida que el nodo se apaga, como es evidente en los registros por lo siguiente

[INFO] [org.infinispan. CLUSTER] [] [SpringApplicationShutdownHook] - ISPN000080: Disconnecting JGroups channel `ISPN` MDC: {}
[INFO] [org.infinispan. CONTAINER] [] [SpringApplicationShutdownHook] - ISPN000390: Persisted state, version=14. 0. 11. Final timestamp=2023-07-13T08:45:17. 267058Z MDC: {}
[DEBUG] [org.infinispan.manager. DefaultCacheManager] [] [SpringApplicationShutdownHook] - Stopped cache manager

Sin embargo, si un nodo es terminado forzosamente por cualquier motivo y lo anterior no se observa en los registros, es muy probable que el estado del nodo esté corrupto. En este caso, se aconseja purgar los datos de infinispan del nodo fallido antes de reiniciarlo. Esto permitirá que el nodo se reincorpore al clúster como un NEW NODE en lugar de intentar regresar como un nodo existente con un estado corrupto. Hay un ticket abierto en Redhat aquí ISPN-14418 acerca de una posible solución automática para la versión 15. Si el estado de un nodo está corrupto y luego se reincorpora al clúster, es probable que observe errores repetidos en todos los nodos dentro del clúster que se asemejan a lo siguiente.

[ERROR] [org.infinispan.interceptors.impl. InvocationContextInterceptor] [] [timeout-thread--p4-t1] - ISPN000136: Error executing command RemoveCommand on Cache 'paxi001', writing keys [WrappedByteArray[\{\"\v\a\l\u\e\"\:\[\"\c\o\m\.\t\h\e\s\o\l\u\t\i\o\n\s\.\f\b\i\.\c\o\r\e\.\s\h\a\r\e\d\.\d\o\m\a\i\n\.\c\o\n\t\e\x\t\.\U\n\i\t.. (114 bytes)]] MDC: {}
org.infinispan.util.concurrent. TimeoutException: ISPN000476: Timed out waiting for responses for request 6284 from achme-archiving-service-2-15893 after 15 seconds
	at org.infinispan.remoting.transport.impl. SingleTargetRequest.onTimeout(SingleTargetRequest.java:86)
	at org.infinispan.remoting.transport. AbstractRequest.call(AbstractRequest.java:88)
	at org.infinispan.remoting.transport. AbstractRequest.call(AbstractRequest.java:22)
	at java.base/java.util.concurrent. FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent. ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent. ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent. ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang. Thread.run(Thread.java:829)

Para prevenir que esta situación ocurra, la recomendación es implementar una verificación en un initContainer para comprobar si existe un archivo de bloqueo colgante.

Cuando un nodo se detiene de manera ordenada, el archivo de bloqueo (\___global State.lck archivo en el ipf.caching.infinispan.settings.cache1.global-state-persistence-location) se elimina al apagarse. Una verificación simple de la existencia de este archivo, fallando si se encuentra, es suficiente para garantizar que un nodo no se inicie en un estado corrupto. Los siguientes fragmentos de manifiesto proporcionan un ejemplo que además introduce una ventana para una intervención antes de fallar el inicio del nodo si se encuentra un archivo de bloqueo colgante. El script se proporciona al initContainer a través de un configmap.

[snip]
      initContainers:
        - name: preflight-checks
          image:busybox
          env:
            - name: SLEEPTIME
              valueFrom:
                configMapKeyRef:
                  name: ipf-test-service-cm
                  key: preflightcheck.sleep
          args:
            - /bin/sh
            - -ec
            - /ipf-test-service-app/conf/preflightcheck.sh
          volumeMounts:
            - name: cache-disk
              mountPath: /cache-mountPath: /ipf-test-service-app/conf/preflightcheck.sh
              name: config-volume
              subPath: preflightcheck.sh
[snip]
      volumes:
        - name: config-volume
          configMap:
            name: ipf-test-service-cm
            defaultMode: 511
[snip]
apiVersion: v1
kind: ConfigMap
metadata:
  name: ipf-test-service-cm
data:
  preflightcheck.sleep: 60
  preflightcheck.sh: |
    echo "Checking the global state of the cache"
    LOCK=/cache/___global.lck
    STATE=/cache/___global.state
    RDSDOMAINDATA=/cache/rds-domain-data

    if [ -f "$LOCK" ]; then
        ls -latr /cache
    cat <<EOF
    ***ERROR***
    File $LOCK exists, this would strongly suggest the pod was forcibly terminated.
    The result is a dangling lock file and probable corruption of the local cache state,
    it is not advisable to allow this pod to start without an intervention.
    If the remainder of the cluster nodes are in a good state you may purge the persisted cache on this node.

    The command to purge is as follows:
    kubectl exec ${HOSTNAME} -c preflight-checks -- rm -rf ${LOCK} ${STATE} ${RDSDOMAINDATA}
    Please be 100% sure before proceeding, this is a destructive process

    To confirm the purge has worked you can run the following
    kubectl exec ${HOSTNAME} -c preflight-checks -- ls -latr /cache

    This container will remain up for ${SLEEPTIME} seconds after which it will exit 1 forcing the pod to restart
    EOF
        sleep $SLEEPTIME
        exit 1
    else
        echo "Global cache state check completed successfully"
    fi

Infinispan Cache Métricas

InfinispanEl caché tiene soporte para exponer métricas de caché (por ejemplo, conteo de aciertos, conteo de fallos, latencia de inserción, latencia de obtención, etc.).

Las métricas pueden ser habilitadas/deshabilitadas mediante un parámetro de configuración:

ipf.caching.infinispan.enable-metrics=true

El parámetro de configuración se establece por defecto en true.

Cachelas métricas tienen dependencia de Micrometer.