Remove InfinispanMultiSiteLoadBalancerCheckProviderFactory.java
Signed-off-by: Michal Hajas <mhajas@redhat.com>
This commit is contained in:
parent
d08ff5a311
commit
6847af0068
4 changed files with 19 additions and 185 deletions
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.connections.infinispan;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.infinispan.factories.ComponentRegistry;
|
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.health.LoadBalancerCheckProvider;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.ALL_CACHES_NAME;
|
|
||||||
|
|
||||||
public class InfinispanMultiSiteLoadBalancerCheckProvider implements LoadBalancerCheckProvider {
|
|
||||||
private static final Logger LOG = Logger.getLogger(InfinispanMultiSiteLoadBalancerCheckProvider.class);
|
|
||||||
private final InfinispanConnectionProvider connectionProvider;
|
|
||||||
|
|
||||||
public InfinispanMultiSiteLoadBalancerCheckProvider(InfinispanConnectionProvider connectionProvider) {
|
|
||||||
Objects.requireNonNull(connectionProvider, "connectionProvider");
|
|
||||||
this.connectionProvider = connectionProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Non-blocking check if all caches and their persistence are available.
|
|
||||||
* <p />
|
|
||||||
* In a situation where any cache's remote cache is unreachable, this will report the "down" to the caller.
|
|
||||||
* When the remote cache is down, it assumes that it is down for all Keycloak nodes in this site, all incoming
|
|
||||||
* requests are likely to fail and that a loadbalancer should send traffic to the other site that might be healthy.
|
|
||||||
* <p />
|
|
||||||
* This code is non-blocking as the embedded Infinispan checks the connection to the remote store periodically
|
|
||||||
* in the background (default: every second).
|
|
||||||
* See {@link LoadBalancerCheckProvider#isDown()} to read more why this needs to be non-blocking.
|
|
||||||
*
|
|
||||||
* @return true if the component is down/unhealthy, false otherwise
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isDown() {
|
|
||||||
for (String cacheName : ALL_CACHES_NAME) {
|
|
||||||
// do not block in cache creation, as this method is required to be non-blocking
|
|
||||||
Cache<?,?> cache = connectionProvider.getCache(cacheName, false);
|
|
||||||
|
|
||||||
// check if cache is started
|
|
||||||
if (cache == null || !cache.getStatus().allowInvocations()) {
|
|
||||||
LOG.debugf("Cache '%s' is not started yet.", cacheName);
|
|
||||||
return true; // no need to check other caches
|
|
||||||
}
|
|
||||||
|
|
||||||
var persistenceManager = ComponentRegistry.componentOf(cache, PersistenceManager.class);
|
|
||||||
|
|
||||||
if (persistenceManager != null && !persistenceManager.isAvailable()) {
|
|
||||||
LOG.debugf("PersistenceManager for cache '%s' is down.", cacheName);
|
|
||||||
return true; // no need to check other caches
|
|
||||||
}
|
|
||||||
LOG.debugf("Cache '%s' is up.", cacheName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
|
||||||
* and other contributors as indicated by the @author tags.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.keycloak.connections.infinispan;
|
|
||||||
|
|
||||||
import org.infinispan.factories.ComponentRegistry;
|
|
||||||
import org.infinispan.persistence.manager.PersistenceManager;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.common.Profile;
|
|
||||||
import org.keycloak.health.LoadBalancerCheckProvider;
|
|
||||||
import org.keycloak.health.LoadBalancerCheckProviderFactory;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
|
||||||
|
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.ALL_CACHES_NAME;
|
|
||||||
|
|
||||||
|
|
||||||
public class InfinispanMultiSiteLoadBalancerCheckProviderFactory implements LoadBalancerCheckProviderFactory, EnvironmentDependentProviderFactory {
|
|
||||||
|
|
||||||
private LoadBalancerCheckProvider loadBalancerCheckProvider;
|
|
||||||
public static final LoadBalancerCheckProvider ALWAYS_HEALTHY = () -> false;
|
|
||||||
private static final Logger LOG = Logger.getLogger(InfinispanMultiSiteLoadBalancerCheckProviderFactory.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoadBalancerCheckProvider create(KeycloakSession session) {
|
|
||||||
if (loadBalancerCheckProvider == null) {
|
|
||||||
InfinispanConnectionProvider infinispanConnectionProvider = session.getProvider(InfinispanConnectionProvider.class);
|
|
||||||
if (infinispanConnectionProvider == null) {
|
|
||||||
LOG.warn("InfinispanConnectionProvider is not available. Load balancer check will be always healthy for Infinispan.");
|
|
||||||
loadBalancerCheckProvider = ALWAYS_HEALTHY;
|
|
||||||
} else {
|
|
||||||
loadBalancerCheckProvider = () -> isEmbeddedCachesDown(infinispanConnectionProvider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return loadBalancerCheckProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postInit(KeycloakSessionFactory factory) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return "infinispan-multisite";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported(Config.Scope config) {
|
|
||||||
return Profile.isFeatureEnabled(Profile.Feature.MULTI_SITE) && !Profile.isFeatureEnabled(Profile.Feature.REMOTE_CACHE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isEmbeddedCachesDown(InfinispanConnectionProvider provider) {
|
|
||||||
return isAnyEmbeddedCachesDown(provider, ALL_CACHES_NAME, LOG);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isAnyEmbeddedCachesDown(InfinispanConnectionProvider connectionProvider, String[] cacheNames, Logger logger) {
|
|
||||||
for (var name : cacheNames) {
|
|
||||||
var cache = connectionProvider.getCache(name, false);
|
|
||||||
|
|
||||||
// check if cache is started
|
|
||||||
if (cache == null || !cache.getStatus().allowInvocations()) {
|
|
||||||
logger.debugf("Cache '%s' is not started yet.", name);
|
|
||||||
return true; // no need to check other caches
|
|
||||||
}
|
|
||||||
|
|
||||||
var persistenceManager = ComponentRegistry.componentOf(cache, PersistenceManager.class);
|
|
||||||
if (persistenceManager != null && !persistenceManager.isAvailable()) {
|
|
||||||
logger.debugf("Persistence for embedded cache '%s' is down.", name);
|
|
||||||
return true; // no need to check other caches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,6 +20,8 @@ package org.keycloak.connections.infinispan.remote;
|
||||||
import org.infinispan.client.hotrod.impl.InternalRemoteCache;
|
import org.infinispan.client.hotrod.impl.InternalRemoteCache;
|
||||||
import org.infinispan.client.hotrod.impl.operations.PingResponse;
|
import org.infinispan.client.hotrod.impl.operations.PingResponse;
|
||||||
import org.infinispan.commons.util.concurrent.CompletableFutures;
|
import org.infinispan.commons.util.concurrent.CompletableFutures;
|
||||||
|
import org.infinispan.factories.ComponentRegistry;
|
||||||
|
import org.infinispan.persistence.manager.PersistenceManager;
|
||||||
import org.infinispan.util.concurrent.ActionSequencer;
|
import org.infinispan.util.concurrent.ActionSequencer;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
@ -45,12 +47,11 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.CLUSTERED_CACHE_NAMES;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.CLUSTERED_CACHE_NAMES;
|
||||||
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.LOCAL_CACHE_NAMES;
|
import static org.keycloak.connections.infinispan.InfinispanConnectionProvider.LOCAL_CACHE_NAMES;
|
||||||
import static org.keycloak.connections.infinispan.InfinispanMultiSiteLoadBalancerCheckProviderFactory.ALWAYS_HEALTHY;
|
|
||||||
import static org.keycloak.connections.infinispan.InfinispanMultiSiteLoadBalancerCheckProviderFactory.isAnyEmbeddedCachesDown;
|
|
||||||
|
|
||||||
public class RemoteLoadBalancerCheckProviderFactory implements LoadBalancerCheckProviderFactory, EnvironmentDependentProviderFactory {
|
public class RemoteLoadBalancerCheckProviderFactory implements LoadBalancerCheckProviderFactory, EnvironmentDependentProviderFactory {
|
||||||
|
|
||||||
private static final int DEFAULT_POLL_INTERVAL = 5000;
|
private static final int DEFAULT_POLL_INTERVAL = 5000;
|
||||||
|
private static final LoadBalancerCheckProvider ALWAYS_HEALTHY = () -> false;
|
||||||
private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass());
|
private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
private volatile int pollIntervalMillis;
|
private volatile int pollIntervalMillis;
|
||||||
|
@ -135,7 +136,22 @@ public class RemoteLoadBalancerCheckProviderFactory implements LoadBalancerCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isEmbeddedCachesDown() {
|
private boolean isEmbeddedCachesDown() {
|
||||||
return isAnyEmbeddedCachesDown(connectionProvider, LOCAL_CACHE_NAMES, logger);
|
for (var name : LOCAL_CACHE_NAMES) {
|
||||||
|
var cache = connectionProvider.getCache(name, false);
|
||||||
|
|
||||||
|
// check if cache is started
|
||||||
|
if (cache == null || !cache.getStatus().allowInvocations()) {
|
||||||
|
logger.debugf("Cache '%s' is not started yet.", name);
|
||||||
|
return true; // no need to check other caches
|
||||||
|
}
|
||||||
|
|
||||||
|
var persistenceManager = ComponentRegistry.componentOf(cache, PersistenceManager.class);
|
||||||
|
if (persistenceManager != null && !persistenceManager.isAvailable()) {
|
||||||
|
logger.debugf("Persistence for embedded cache '%s' is down.", name);
|
||||||
|
return true; // no need to check other caches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record RemoteCacheCheckList(List<RemoteCacheCheck> list, ActionSequencer sequencer) implements Runnable {
|
private record RemoteCacheCheckList(List<RemoteCacheCheck> list, ActionSequencer sequencer) implements Runnable {
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
org.keycloak.connections.infinispan.InfinispanMultiSiteLoadBalancerCheckProviderFactory
|
|
||||||
org.keycloak.connections.infinispan.remote.RemoteLoadBalancerCheckProviderFactory
|
org.keycloak.connections.infinispan.remote.RemoteLoadBalancerCheckProviderFactory
|
Loading…
Reference in a new issue