org.wildfly.swarm.topology.webapp.runtime.TopologyProxyService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of topology-webapp Show documentation
Show all versions of topology-webapp Show documentation
Server-Sent Events of instances being added/removed from cluster
/**
* Copyright 2015-2017 Red Hat, Inc, and individual contributors.
*
* 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.wildfly.swarm.topology.webapp.runtime;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.NamingException;
import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.proxy.LoadBalancingProxyClient;
import io.undertow.server.handlers.proxy.ProxyHandler;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler;
import org.wildfly.swarm.topology.Topology;
import org.wildfly.swarm.topology.TopologyListener;
import org.wildfly.swarm.topology.webapp.TopologyWebAppFraction;
public class TopologyProxyService implements Service, TopologyListener {
public static final ServiceName SERVICE_NAME = ServiceName.parse("swarm.topology.proxy");
public TopologyProxyService(Set serviceNames) {
this.serviceNames = serviceNames;
}
public ServiceName mscServiceNameForServiceProxy(String serviceName) {
return ServiceName.of("jboss", "undertow", "handler",
TopologyWebAppFraction.proxyHandlerName(serviceName));
}
@Override
public void start(StartContext context) throws StartException {
try {
Topology topology = Topology.lookup();
topology.addListener(this);
} catch (NamingException ex) {
throw new StartException(ex);
}
}
@Override
public void stop(StopContext context) {
try {
Topology.lookup().removeListener(this);
} catch (NamingException e) {
// Swallow, as we're closing anyway
}
}
@Override
public TopologyProxyService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}
@Override
public void onChange(Topology topology) {
Map> topologyMap = topology.asMap();
for (String serviceName : serviceNames) {
if (topologyMap.containsKey(serviceName)) {
updateProxyHosts(serviceName, topologyMap.get(serviceName));
} else {
// All instances of this service went away
updateProxyHosts(serviceName, Collections.emptyList());
}
}
}
public Injector getHandlerInjectorFor(String serviceName) {
InjectedValue injector = proxyHandlerMap.get(serviceName);
if (injector == null) {
injector = new InjectedValue<>();
proxyHandlerMap.put(serviceName, injector);
}
return injector;
}
private void updateProxyHosts(String serviceName, List entries) {
HttpHandler proxyHandler = proxyHandlerMap.get(serviceName).getOptionalValue();
if (proxyHandler == null) {
// Service has been shutdown
proxyHandlerMap.remove(serviceName);
return;
}
LoadBalancingProxyClient proxyClient = null;
// with SWARM-189 the request controller subsystem does replace
// all HttpHandler (including ProxyHandler) with GlobalRequestControllerHandler,
// which then wraps the next handler in the chain
if (proxyHandler instanceof GlobalRequestControllerHandler) {
ProxyHandler proxy = (ProxyHandler) ((GlobalRequestControllerHandler) proxyHandler).getNext(); // next in the chain of handlers
proxyClient = (LoadBalancingProxyClient) proxy.getProxyClient();
} else {
proxyClient = (LoadBalancingProxyClient) ((ProxyHandler) proxyHandler).getProxyClient();
}
List oldEntries = proxyEntries.get(serviceName);
List entriesToRemove = new ArrayList<>();
List entriesToAdd = new ArrayList<>();
if (oldEntries == null) {
entriesToAdd.addAll(entries);
} else {
for (Topology.Entry oldEntry : oldEntries) {
if (!entries.contains(oldEntry)) {
entriesToRemove.add(oldEntry);
}
}
for (Topology.Entry entry : entries) {
if (!oldEntries.contains(entry)) {
entriesToAdd.add(entry);
}
}
}
for (Topology.Entry entry : entriesToRemove) {
try {
proxyClient.removeHost(entryToURI(entry));
} catch (URISyntaxException ex) {
log.log(Level.WARNING, "Error converting topology entry to URI", ex);
}
}
for (Topology.Entry entry : entriesToAdd) {
try {
proxyClient.addHost(entryToURI(entry));
} catch (URISyntaxException ex) {
log.log(Level.WARNING, "Error converting topology entry to URI", ex);
}
}
proxyEntries.put(serviceName, entries);
}
private URI entryToURI(Topology.Entry entry) throws URISyntaxException {
List tags = entry.getTags();
String scheme = "http";
if (tags.contains("https")) {
scheme = "https";
}
return new URI(scheme, null, entry.getAddress(), entry.getPort(), null, null, null);
}
private static final Logger log = Logger.getLogger(TopologyProxyService.class.getName());
private final Set serviceNames;
private Map> proxyHandlerMap = new HashMap<>();
private Map> proxyEntries = new HashMap<>();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy