Skip to content

Instantly share code, notes, and snippets.

@spinscale
Created June 10, 2015 07:01
Show Gist options
  • Save spinscale/74a3f2f8fa4c99539998 to your computer and use it in GitHub Desktop.
Save spinscale/74a3f2f8fa4c99539998 to your computer and use it in GitHub Desktop.
Undertow + jgroups-raft example
<config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd">
<UDP
mcast_addr="224.5.5.5"
mcast_port="${jgroups.udp.mcast_port:45588}"
bind_interface="en0"
diagnostics_bind_interfaces="en0"
receive_interfaces="en0"/>
<PING />
<MERGE3 />
<FD_SOCK/>
<FD_ALL/>
<VERIFY_SUSPECT timeout="1500" />
<pbcast.NAKACK2 xmit_interval="500"
discard_delivered_msgs="true"/>
<UNICAST3 xmit_interval="500"
max_msg_batch_size="500"/>
<pbcast.STABLE desired_avg_gossip="50000"
max_bytes="4M"/>
<raft.NO_DUPES/> 1
<pbcast.GMS print_local_addr="true" join_timeout="2000"
view_bundling="true"/>
<UFC max_credits="2M" min_threshold="0.4"/>
<MFC max_credits="2M" min_threshold="0.4"/>
<FRAG2 frag_size="60K" />
<raft.ELECTION election_min_interval="100" election_max_interval="500"/> 2
<raft.RAFT members="A,B,C" raft_id="${raft_id:undefined}"/>
<raft.REDIRECT/> 4
<raft.CLIENT bind_addr="0.0.0.0" /> 5
</config>
#!/bin/bash
echo ; echo ; echo "Setting /foo/bar"
curl -v -X PUT 127.0.0.1:8080/cluster/foo/bar
# wait for consensus
sleep 2
echo ; echo ; echo "Getting /foo/bar"
curl -X GET 127.0.0.1:8081/cluster/foo
echo ; echo ; echo "Deleting /foo/bar"
curl -v -X DELETE 127.0.0.1:8082/cluster/foo
echo ; echo ; echo "Getting /foo/bar"
curl -v -X GET 127.0.0.1:8080/cluster/foo
package de.spinscale.cluster;
import io.undertow.Undertow;
import io.undertow.server.handlers.PathTemplateHandler;
import io.undertow.util.HttpString;
import io.undertow.util.PathTemplateMatch;
import org.jgroups.JChannel;
import org.jgroups.raft.RaftHandle;
import org.jgroups.raft.blocks.ReplicatedStateMachine;
public class Webserver {
public static class RaftNode {
ReplicatedStateMachine<String, String> rsm;
public RaftNode(String id) throws Exception {
JChannel ch = new JChannel("src/main/resources/raft.xml");
rsm = new ReplicatedStateMachine<>(ch);
RaftHandle handle = new RaftHandle(ch, rsm);
handle.raftId(id);
ch.connect("raft-cluster");
}
public String get(String key) {
return rsm.get(key);
}
public void put(String key, String value) throws Exception {
rsm.put(key, value);
}
public void remove(String key) throws Exception {
rsm.remove(key);
}
public boolean exists(String key) {
return get(key) != null;
}
}
public static class UndertowServer {
private final Undertow server;
public UndertowServer(int port, final RaftNode raftNode) {
PathTemplateHandler handler = new PathTemplateHandler();
handler.add("/cluster/{key}/{value}", exchange -> {
PathTemplateMatch attachment = exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY);
String key = attachment.getParameters().get("key");
String value = attachment.getParameters().get("value");
if (exchange.getRequestMethod().equals(HttpString.tryFromString("PUT"))) {
raftNode.put(key, value);
exchange.setResponseCode(200);
}
});
handler.add("/cluster/{key}", exchange -> {
PathTemplateMatch attachment = exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY);
String key = attachment.getParameters().get("key");
if (!raftNode.exists(key)) {
exchange.setResponseCode(404);
} else {
exchange.setResponseCode(200);
if (exchange.getRequestMethod().equals(HttpString.tryFromString("GET"))) {
exchange.getResponseSender().send(raftNode.get(key));
} else if (exchange.getRequestMethod().equals(HttpString.tryFromString("DELETE"))) {
raftNode.remove(key);
}
}
});
server = Undertow.builder()
.addHttpListener(port, "localhost")
.setHandler(handler)
.build();
}
public UndertowServer start() {
server.start();
return this;
}
}
public static void main(String[] args) {
System.setProperty("java.net.preferIPv4Stack", "true"); // osx prefers ipv6
try {
new UndertowServer(8080, new RaftNode("A")).start();
new UndertowServer(8081, new RaftNode("B")).start();
new UndertowServer(8082, new RaftNode("C")).start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment