Skip to content

Commit

Permalink
Add interfaces for querying and controlling mod_cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed May 20, 2015
1 parent 56c96f2 commit 0a640c5
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 50 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ void nodeCommandString(StringBuilder buf, String uri, MCMPAction status, String


static void printProxyStat(StringBuilder buf, Node node, boolean reduceDisplay) { static void printProxyStat(StringBuilder buf, Node node, boolean reduceDisplay) {
String status = "NOTOK"; String status = "NOTOK";
if (node.getStatus() == Node.Status.NODE_UP) if (node.getStatus() == NodeStatus.NODE_UP)
status = "OK"; status = "OK";
if (reduceDisplay) { if (reduceDisplay) {
buf.append(" " + status + " "); buf.append(" " + status + " ");
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class ModCluster {
private final int requestQueueSize; private final int requestQueueSize;
private final boolean queueNewRequests; private final boolean queueNewRequests;
private final int maxRequestTime; private final int maxRequestTime;
private final long ttl;


private final XnioWorker xnioWorker; private final XnioWorker xnioWorker;
private final ModClusterContainer container; private final ModClusterContainer container;
Expand All @@ -63,6 +64,7 @@ public class ModCluster {
this.removeBrokenNodes = builder.removeBrokenNodes; this.removeBrokenNodes = builder.removeBrokenNodes;
this.healthChecker = builder.healthChecker; this.healthChecker = builder.healthChecker;
this.maxRequestTime = builder.maxRequestTime; this.maxRequestTime = builder.maxRequestTime;
this.ttl = builder.ttl;
this.container = new ModClusterContainer(this, builder.xnioSsl, builder.client); this.container = new ModClusterContainer(this, builder.xnioSsl, builder.client);
} }


Expand All @@ -74,6 +76,10 @@ protected ModClusterContainer getContainer() {
return container; return container;
} }


public ModClusterController getController() {
return container;
}

public int getMaxConnections() { public int getMaxConnections() {
return maxConnections; return maxConnections;
} }
Expand Down Expand Up @@ -102,6 +108,10 @@ public NodeHealthChecker getHealthChecker() {
return healthChecker; return healthChecker;
} }


public long getTtl() {
return ttl;
}

/** /**
* Get the handler proxying the requests. * Get the handler proxying the requests.
* *
Expand Down Expand Up @@ -181,6 +191,7 @@ public static class Builder {
private boolean queueNewRequests = false; private boolean queueNewRequests = false;


private int maxRequestTime = -1; private int maxRequestTime = -1;
private long ttl;


private NodeHealthChecker healthChecker = NodeHealthChecker.NO_CHECK; private NodeHealthChecker healthChecker = NodeHealthChecker.NO_CHECK;
private long healthCheckInterval = TimeUnit.SECONDS.toMillis(10); private long healthCheckInterval = TimeUnit.SECONDS.toMillis(10);
Expand Down Expand Up @@ -235,6 +246,14 @@ public Builder setHealthChecker(NodeHealthChecker healthChecker) {
this.healthChecker = healthChecker; this.healthChecker = healthChecker;
return this; return this;
} }

public long getTtl() {
return ttl;
}

public void setTtl(long ttl) {
this.ttl = ttl;
}
} }


} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@


package io.undertow.server.handlers.proxy.mod_cluster; package io.undertow.server.handlers.proxy.mod_cluster;


import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

import io.undertow.UndertowLogger; import io.undertow.UndertowLogger;
import io.undertow.client.UndertowClient; import io.undertow.client.UndertowClient;
import io.undertow.server.HttpServerExchange; import io.undertow.server.HttpServerExchange;
Expand All @@ -41,11 +32,20 @@
import org.xnio.XnioIoThread; import org.xnio.XnioIoThread;
import org.xnio.ssl.XnioSsl; import org.xnio.ssl.XnioSsl;


import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

/** /**
* @author Stuart Douglas * @author Stuart Douglas
* @author Emanuel Muckenhuber * @author Emanuel Muckenhuber
*/ */
class ModClusterContainer { class ModClusterContainer implements ModClusterController {


// The configured balancers // The configured balancers
private final ConcurrentMap<String, Balancer> balancers = new CopyOnWriteMap<>(); private final ConcurrentMap<String, Balancer> balancers = new CopyOnWriteMap<>();
Expand Down Expand Up @@ -148,10 +148,10 @@ public ModClusterProxyTarget findTarget(final HttpServerExchange exchange) {
/** /**
* Register a new node. * Register a new node.
* *
* @param config the node configuration * @param config the node configuration
* @param balancerConfig the balancer configuration * @param balancerConfig the balancer configuration
* @param ioThread the associated I/O thread * @param ioThread the associated I/O thread
* @param bufferPool the buffer pool * @param bufferPool the buffer pool
* @return whether the node could be created or not * @return whether the node could be created or not
*/ */
public synchronized boolean addNode(final NodeConfig config, final Balancer.BalancerBuilder balancerConfig, final XnioIoThread ioThread, final Pool<ByteBuffer> bufferPool) { public synchronized boolean addNode(final NodeConfig config, final Balancer.BalancerBuilder balancerConfig, final XnioIoThread ioThread, final Pool<ByteBuffer> bufferPool) {
Expand Down Expand Up @@ -196,7 +196,7 @@ public synchronized boolean addNode(final NodeConfig config, final Balancer.Bala
/** /**
* Management command enabling all contexts on the given node. * Management command enabling all contexts on the given node.
* *
* @param jvmRoute the jvmRoute * @param jvmRoute the jvmRoute
* @return * @return
*/ */
public synchronized boolean enableNode(final String jvmRoute) { public synchronized boolean enableNode(final String jvmRoute) {
Expand All @@ -213,7 +213,7 @@ public synchronized boolean enableNode(final String jvmRoute) {
/** /**
* Management command disabling all contexts on the given node. * Management command disabling all contexts on the given node.
* *
* @param jvmRoute the jvmRoute * @param jvmRoute the jvmRoute
* @return * @return
*/ */
public synchronized boolean disableNode(final String jvmRoute) { public synchronized boolean disableNode(final String jvmRoute) {
Expand All @@ -230,7 +230,7 @@ public synchronized boolean disableNode(final String jvmRoute) {
/** /**
* Management command stopping all contexts on the given node. * Management command stopping all contexts on the given node.
* *
* @param jvmRoute the jvmRoute * @param jvmRoute the jvmRoute
* @return * @return
*/ */
public synchronized boolean stopNode(final String jvmRoute) { public synchronized boolean stopNode(final String jvmRoute) {
Expand Down Expand Up @@ -325,7 +325,7 @@ public synchronized boolean enableContext(final String contextPath, final String
return false; return false;
} }


synchronized boolean disableContext(final String contextPath, final String jvmRoute, List<String> aliases) { public synchronized boolean disableContext(final String contextPath, final String jvmRoute, List<String> aliases) {
final Node node = nodes.get(jvmRoute); final Node node = nodes.get(jvmRoute);
if (node != null) { if (node != null) {
node.disableContext(contextPath, aliases); node.disableContext(contextPath, aliases);
Expand Down Expand Up @@ -386,10 +386,10 @@ Context findNewNode(final VirtualHost.HostEntry entry) {
/** /**
* Try to find a failover node within the same load balancing group. * Try to find a failover node within the same load balancing group.
* *
* @oaram entry the resolved virtual host entry * @param domain the load balancing domain, if known
* @param domain the load balancing domain, if known * @param jvmRoute the original jvmRoute
* @param jvmRoute the original jvmRoute
* @return the context, {@code null} if not found * @return the context, {@code null} if not found
* @oaram entry the resolved virtual host entry
*/ */
Context findFailoverNode(final VirtualHost.HostEntry entry, final String domain, final String jvmRoute, final boolean forceStickySession) { Context findFailoverNode(final VirtualHost.HostEntry entry, final String domain, final String jvmRoute, final boolean forceStickySession) {
String failOverDomain = null; String failOverDomain = null;
Expand Down Expand Up @@ -421,7 +421,7 @@ Context findFailoverNode(final VirtualHost.HostEntry entry, final String domain,
/** /**
* Map a request to virtual host. * Map a request to virtual host.
* *
* @param exchange the http exchange * @param exchange the http exchange
* @return * @return
*/ */
private PathMatcher.PathMatch<VirtualHost.HostEntry> mapVirtualHost(final HttpServerExchange exchange) { private PathMatcher.PathMatch<VirtualHost.HostEntry> mapVirtualHost(final HttpServerExchange exchange) {
Expand All @@ -442,8 +442,8 @@ private PathMatcher.PathMatch<VirtualHost.HostEntry> mapVirtualHost(final HttpSe
if (host == null) { if (host == null) {
return null; return null;
} }
PathMatcher.PathMatch<VirtualHost.HostEntry> result = host.match(context); PathMatcher.PathMatch<VirtualHost.HostEntry> result = host.match(context);
if(result.getValue() == null) { if (result.getValue() == null) {
return null; return null;
} }
return result; return result;
Expand Down Expand Up @@ -586,4 +586,190 @@ public void run() {
} }
} }



@Override
public ModClusterStatus getStatus() {
List<ModClusterStatus.LoadBalancer> balancers = new ArrayList<>();
for(Map.Entry<String, Balancer> bentry : this.balancers.entrySet()) {
List<ModClusterStatus.Node> nodes = new ArrayList<>();
for(Node node : this.getNodes()) {
if(node.getBalancer().getName().equals(bentry.getKey())) {
List<ModClusterStatus.Context> contexts = new ArrayList<>();

for(Context i : node.getContexts()) {
contexts.add(new ContextImpl(i));
}

nodes.add(new NodeImpl(node, contexts));
}
}

balancers.add(new BalancerImpl(bentry.getValue(), nodes));
}
return new ModClusterStatusImpl(balancers);
}

private class ModClusterStatusImpl implements ModClusterStatus {

private final List<LoadBalancer> balancers;

private ModClusterStatusImpl(List<LoadBalancer> balancers) {
this.balancers = balancers;
}

@Override
public List<LoadBalancer> getLoadBalancers() {
return balancers;
}

@Override
public LoadBalancer getLoadBalancer(String name) {
for (LoadBalancer b : balancers) {
if (b.getName().equals(name)) {
return b;
}
}
return null;
}
}

private class BalancerImpl implements ModClusterStatus.LoadBalancer {
private final Balancer balancer;
private final List<ModClusterStatus.Node> nodes;

private BalancerImpl(Balancer balancer, List<ModClusterStatus.Node> nodes) {
this.balancer = balancer;
this.nodes = nodes;
}

@Override
public String getName() {
return balancer.getName();
}

@Override
public List<ModClusterStatus.Node> getNodes() {
return nodes;
}

@Override
public ModClusterStatus.Node getNode(String name) {
for (ModClusterStatus.Node i : nodes) {
if(i.getName().equals(name)) {
return i;
}
}
return null;
}

@Override
public boolean isStickySession() {
return balancer.isStickySession();
}

@Override
public String getStickySessionCookie() {
return balancer.getStickySessionCookie();
}

@Override
public String getStickySessionPath() {
return null;
}

@Override
public boolean isStickySessionRemove() {
return balancer.isStickySessionRemove();
}

@Override
public boolean isStickySessionForce() {
return balancer.isStickySessionForce();
}

@Override
public int getWaitWorker() {
return balancer.getWaitWorker();
}

@Override
public int getMaxAttempts() {
return balancer.getMaxattempts();
}
}

private class NodeImpl implements ModClusterStatus.Node {

private final Node node;
private final List<ModClusterStatus.Context> contexts;

private NodeImpl(Node node, List<ModClusterStatus.Context> contexts) {
this.node = node;
this.contexts = contexts;
}

@Override
public String getName() {
return node.getJvmRoute();
}

@Override
public List<ModClusterStatus.Context> getContexts() {
return Collections.unmodifiableList(contexts);
}

@Override
public ModClusterStatus.Context getContext(String name) {
for (ModClusterStatus.Context i : contexts) {
if(i.getName().equals(name)) {
return i;
}
}
return null;
}

@Override
public int getLoad() {
return node.getLoad();
}

@Override
public NodeStatus getStatus() {
return node.getStatus();
}
}

private class ContextImpl implements ModClusterStatus.Context {
private final Context context;

private ContextImpl(Context context) {
this.context = context;
}

@Override
public String getName() {
return context.getPath();
}

@Override
public boolean isEnabled() {
return context.isEnabled();
}

@Override
public int getRequests() {
return context.getActiveRequests();
}

@Override
public void enable() {
context.enable();
}

@Override
public void disable() {
context.disable();
}
}

} }
Loading

0 comments on commit 0a640c5

Please sign in to comment.