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 alta velocidad local caches.

  • 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

Infinispan el 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 https://infinispan.zulipchat.com/[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 declaradas caches, controlando su ciclo de vida, y es responsable de la configuración global.

Infinispan naves 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();
    }

A cache 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 cache está disponible aquí.

Todo el beans mencionado anteriormente lo obtenemos gratis al agregar el maven dependency mencionado anteriormente.

Sin embargo, el Infinispan cache requiere los siguientes valores de configuración para cada cache 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 del cache siendo utilizado

  • cache-mode - Infinispan cache los gerentes pueden crear y controlar múltiples caches que utilizan diferentes modos. Por ejemplo, usted puede utilizar el mismo cache gerente local caches, distribuido caches, y caches con modo de invalidación.

  • timeout - duración cache permanecerá en la memoria activa antes de ser desalojado.

  • max-count - especifique el número total de entradas que caches puede contener antes 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 cache modo es 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, el cache recuperará datos del vecino caches cuando se inicia, así que el cache comienza 'caliente', aunque impactará el tiempo de inicio. En modo distribuido,state se transfiere entre en ejecución caches así como la propiedad de las claves cambia (por ejemplo, porque un cache 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 de unión para bloquear y esperar hasta que la unión esté completa y el cache ha terminado de recibir state de los vecinos caches(si fetchInMemoryState está habilitado). Esta opción se aplica a distribuidos y replicados caches solo y está habilitado por defecto. Tenga en cuenta que establecer esto en falso hará que el cache El objeto 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 a state de los vecinos caches, antes de lanzar una excepción y abortar el inicio.

  • global-state-persistence-location - Esta es la ubicación para persistir el global state de nodos dentro de un clúster, solo relevante en kubernetes despliegues. Tiene un valor predeterminado de " java.io.tmpdir". Si la persistencia está habilitada para un cache, este valor DEBE ser siempre la carpeta principal de los datos de persistencia y ubicaciones de índice. Esta ubicación DEBE sobrevivir a un restart, 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 persistencia.cache. 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 al establecer el habilitado flag a verdadero, si no está configurado o es falso, persistente permanecerá desactivado.
2 Aquí definimos la ruta a la carpeta en la que deseamos almacenar los datos para respaldar el cache.
3 Aquí definimos la ruta a la carpeta en la que se deben almacenar los índices para el cache.
Los valores asignados a los datos y ubicaciones de índice. Son subdirectorios de /cache cuál 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, existen propiedades de configuración opcionales adicionales para persistir.cache:

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 cache instancias comparten el mismo cache almacenar (por ejemplo, múltiples nodos en un clúster utilizando un JDBC basado en CacheStore apuntando a la misma base de datos compartida.) Establecer esto en verdadero evita múltiples cache instancias escribiendo la misma modificación múltiples veces. Si está habilitado, solo el nodo donde se originó la modificación escribirá en el cache almacén. Si está deshabilitado, cada individuo cache reacciona a una posible actualización remota almacenando los datos en el cache almacén.
2 Si es cierto, cuando el cache comienza, datos almacenados en el cache la tienda se cargará previamente en la memoria. Esto es particularmente útil cuando los datos en el cache la tienda será necesaria inmediatamente después del inicio y usted quiere evitar cache las operaciones se están retrasando como resultado de cargar estos datos de manera perezosa. Puede utilizarse para proporcionar un 'calentamiento’cache' al iniciar, 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 esto cache almacene cuando se inicie.
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. Se establece por defecto en 0. 5
maxFileSize y compactionThreshold son configuraciones útiles si se modifica el mismo cache Ingrese 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. 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 un solo cache una clave que tiene un conjunto de datos pequeño, creando así una situación en la que no ocurre compresión. No hay una regla general aquí, aparte de entender que la compresión frecuente es algo positivo. N. B. 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 basado en el sistema de archivos cache almacenes en sistemas de archivos compartidos, como un recurso compartido NFS o 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 infinispan caching.

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

Entonces, solo necesita utilizar el CacheFactory para crear 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 kubernetes basado infinispan embedded clúster, usted DEBE habilitar kubernetes estableciendo 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 implementadas en kubernetes(la misma lógica se aplicará a openshift) están utilizando un Despliegue manifest. Este enfoque es perfectamente aceptable si el infinispan cache no se está persistiendo en el almacenamiento local. Si hay 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, es porque los Statefulsets provisionan volúmenes únicos por instancia, lo cual es lo que se requeriría para un cache el clúster. El grupo de Implementaciones compartiría, en contraste, un único volumen a través del 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á clusterIP. La razón detrás de esto se relaciona con el uso de JGROUPS dentro infinispan y más específicamente el protocolo de descubrimiento de clúster JGROUPS DNS_PING que es favorecido para kubernetes descubrimiento de clúster de entorno. 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 interno kubernetes dns 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 cache agrupación antes de que el servicio esté en "listo" state.

Se recomienda ENCARECIDAMENTE que el JGROUPS kubernetes el servicio se define dentro de su propio manifiesto que gestiona el puerto 7800 SOLAMENTE. Esto es particularmente pertinente cuando akka cluster s están involucrados.
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 global state de la CacheManager se habilita en infinispan. El global state de un nodo es vital para cualquier cache cluster. Cuando un nodo del clúster se detiene de manera controlada, el state 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 state del nodo está corrupto. En este caso, se aconseja purgar el infinispan datos para el failed nodo 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 corrupto state. Hay un ticket abierto en Redhat aquí ISPN-14418 acerca de una posible solución automática para la versión 15. Si un nodo state 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 los siguientes

[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 la existencia de 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.state. Los siguientes fragmentos del 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

Infinispan cache tiene soporte para exponer cache métricas (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.

Cache las métricas tienen dependencia de Micrometer.