GOSSIP-22 New failure detector
This commit is contained in:
@ -23,6 +23,7 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
@ -31,8 +32,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.gossip.event.GossipListener;
|
||||
import org.apache.gossip.event.GossipState;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -46,31 +45,20 @@ public class ShutdownDeadtimeTest {
|
||||
@Test
|
||||
public void DeadNodesDoNotComeAliveAgain()
|
||||
throws InterruptedException, UnknownHostException, URISyntaxException {
|
||||
GossipSettings settings = new GossipSettings(1000, 10000);
|
||||
GossipSettings settings = new GossipSettings(1000, 10000, 1000, 1, 5.0);
|
||||
String cluster = UUID.randomUUID().toString();
|
||||
|
||||
log.info("Adding seed nodes");
|
||||
int seedNodes = 3;
|
||||
List<GossipMember> startupMembers = new ArrayList<>();
|
||||
for (int i = 1; i < seedNodes + 1; ++i) {
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30300 + i));
|
||||
startupMembers.add(new RemoteGossipMember(cluster, uri, i + ""));
|
||||
}
|
||||
|
||||
log.info("Adding clients");
|
||||
final List<GossipService> clients = new ArrayList<>();
|
||||
final List<GossipService> clients = Collections.synchronizedList(new ArrayList<GossipService>());
|
||||
final int clusterMembers = 5;
|
||||
for (int i = 1; i < clusterMembers + 1; ++i) {
|
||||
final int j = i;
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (30300 + i));
|
||||
GossipService gossipService = new GossipService(cluster, uri, i + "", startupMembers,
|
||||
settings, new GossipListener() {
|
||||
@Override
|
||||
public void gossipEvent(GossipMember member, GossipState state) {
|
||||
System.out.println(System.currentTimeMillis() + " Member " + j + " reports "
|
||||
+ member + " " + state);
|
||||
}
|
||||
});
|
||||
settings, (a,b) -> {});
|
||||
clients.add(gossipService);
|
||||
gossipService.start();
|
||||
}
|
||||
@ -100,7 +88,7 @@ public class ShutdownDeadtimeTest {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(16);
|
||||
}).afterWaitingAtMost(40, TimeUnit.SECONDS).isEqualTo(16);
|
||||
clients.remove(randomClientId);
|
||||
|
||||
TUnit.assertThat(new Callable<Integer>() {
|
||||
@ -111,17 +99,12 @@ public class ShutdownDeadtimeTest {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(4);
|
||||
}).afterWaitingAtMost(30, TimeUnit.SECONDS).isEqualTo(4);
|
||||
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + shutdownPort);
|
||||
// start client again
|
||||
GossipService gossipService = new GossipService(cluster, uri, shutdownId + "", startupMembers,
|
||||
settings, new GossipListener() {
|
||||
@Override
|
||||
public void gossipEvent(GossipMember member, GossipState state) {
|
||||
// System.out.println("revived " + member+" "+ state);
|
||||
}
|
||||
});
|
||||
settings, (a,b) -> {});
|
||||
clients.add(gossipService);
|
||||
gossipService.start();
|
||||
|
||||
@ -134,7 +117,7 @@ public class ShutdownDeadtimeTest {
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(20);
|
||||
}).afterWaitingAtMost(60, TimeUnit.SECONDS).isEqualTo(20);
|
||||
|
||||
for (int i = 0; i < clusterMembers; ++i) {
|
||||
clients.get(i).shutdown();
|
||||
|
@ -48,28 +48,16 @@ public class StartupSettingsTest {
|
||||
@Test
|
||||
public void testUsingSettingsFile() throws IOException, InterruptedException, URISyntaxException {
|
||||
File settingsFile = File.createTempFile("gossipTest",".json");
|
||||
log.debug( "Using settings file: " + settingsFile.getAbsolutePath() );
|
||||
settingsFile.deleteOnExit();
|
||||
writeSettingsFile(settingsFile);
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + 50000);
|
||||
final GossipService firstService = new GossipService(
|
||||
CLUSTER, uri, UUID.randomUUID().toString(),
|
||||
CLUSTER, uri, "1",
|
||||
new ArrayList<GossipMember>(), new GossipSettings(), null);
|
||||
|
||||
firstService.start();
|
||||
|
||||
TUnit.assertThat(new Callable<Integer> (){
|
||||
public Integer call() throws Exception {
|
||||
return firstService.getGossipManager().getLiveMembers().size();
|
||||
}}).afterWaitingAtMost(30, TimeUnit.SECONDS).isEqualTo(0);
|
||||
final GossipService serviceUnderTest = new GossipService(
|
||||
StartupSettings.fromJSONFile( settingsFile )
|
||||
);
|
||||
StartupSettings.fromJSONFile(settingsFile));
|
||||
serviceUnderTest.start();
|
||||
TUnit.assertThat(new Callable<Integer> (){
|
||||
public Integer call() throws Exception {
|
||||
return serviceUnderTest.getGossipManager().getLiveMembers().size();
|
||||
}}).afterWaitingAtMost(10, TimeUnit.SECONDS).isEqualTo(1);
|
||||
firstService.shutdown();
|
||||
serviceUnderTest.shutdown();
|
||||
}
|
||||
@ -78,10 +66,13 @@ public class StartupSettingsTest {
|
||||
String settings =
|
||||
"[{\n" + // It is odd that this is meant to be in an array, but oh well.
|
||||
" \"cluster\":\"" + CLUSTER + "\",\n" +
|
||||
" \"id\":\"" + UUID.randomUUID() + "\",\n" +
|
||||
" \"id\":\"" + "2" + "\",\n" +
|
||||
" \"uri\":\"udp://127.0.0.1:50001\",\n" +
|
||||
" \"gossip_interval\":1000,\n" +
|
||||
" \"window_size\":1000,\n" +
|
||||
" \"minimum_samples\":5,\n" +
|
||||
" \"cleanup_interval\":10000,\n" +
|
||||
" \"convict_threshold\":2.6,\n" +
|
||||
" \"members\":[\n" +
|
||||
" {\"cluster\": \"" + CLUSTER + "\",\"uri\":\"udp://127.0.0.1:5000\"}\n" +
|
||||
" ]\n" +
|
||||
|
@ -29,54 +29,39 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.gossip.event.GossipListener;
|
||||
import org.apache.gossip.event.GossipState;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@RunWith(JUnitPlatform.class)
|
||||
public class TenNodeThreeSeedTest {
|
||||
private static final Logger log = Logger.getLogger( TenNodeThreeSeedTest.class );
|
||||
|
||||
@Test
|
||||
public void test() throws UnknownHostException, InterruptedException, URISyntaxException{
|
||||
abc();
|
||||
public void test() throws UnknownHostException, InterruptedException, URISyntaxException {
|
||||
abc(30150);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAgain() throws UnknownHostException, InterruptedException, URISyntaxException{
|
||||
abc();
|
||||
abc(30100);
|
||||
}
|
||||
|
||||
public void abc() throws InterruptedException, UnknownHostException, URISyntaxException{
|
||||
public void abc(int base) throws InterruptedException, UnknownHostException, URISyntaxException{
|
||||
GossipSettings settings = new GossipSettings();
|
||||
String cluster = UUID.randomUUID().toString();
|
||||
|
||||
log.info( "Adding seed nodes" );
|
||||
int seedNodes = 3;
|
||||
List<GossipMember> startupMembers = new ArrayList<>();
|
||||
for (int i = 1; i < seedNodes+1; ++i) {
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (base + i));
|
||||
startupMembers.add(new RemoteGossipMember(cluster, uri, i + ""));
|
||||
}
|
||||
|
||||
log.info( "Adding clients" );
|
||||
final List<GossipService> clients = new ArrayList<>();
|
||||
final int clusterMembers = 5;
|
||||
for (int i = 1; i < clusterMembers+1; ++i) {
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (base + i));
|
||||
GossipService gossipService = new GossipService(cluster, uri, i + "",
|
||||
startupMembers, settings,
|
||||
new GossipListener(){
|
||||
@Override
|
||||
public void gossipEvent(GossipMember member, GossipState state) {
|
||||
log.info(member+" "+ state);
|
||||
}
|
||||
});
|
||||
startupMembers, settings, (a,b) -> {});
|
||||
clients.add(gossipService);
|
||||
gossipService.start();
|
||||
}
|
||||
}
|
||||
TUnit.assertThat(new Callable<Integer> (){
|
||||
public Integer call() throws Exception {
|
||||
int total = 0;
|
||||
@ -84,8 +69,8 @@ public class TenNodeThreeSeedTest {
|
||||
total += clients.get(i).getGossipManager().getLiveMembers().size();
|
||||
}
|
||||
return total;
|
||||
}}).afterWaitingAtMost(20, TimeUnit.SECONDS).isEqualTo(20);
|
||||
|
||||
}}).afterWaitingAtMost(40, TimeUnit.SECONDS).isEqualTo(20);
|
||||
|
||||
for (int i = 0; i < clusterMembers; ++i) {
|
||||
clients.get(i).shutdown();
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.apache.gossip.accrual;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.gossip.LocalGossipMember;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.platform.runner.JUnitPlatform;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(JUnitPlatform.class)
|
||||
public class FailureDetectorTest {
|
||||
|
||||
@Test
|
||||
public void aTest(){
|
||||
int samples = 1;
|
||||
int windowSize = 1000;
|
||||
LocalGossipMember member = new LocalGossipMember("", URI.create("udp://127.0.0.1:1000"), "", 0L, windowSize, samples);
|
||||
member.recordHeartbeat(5);
|
||||
member.recordHeartbeat(10);
|
||||
Assert.assertEquals(new Double(0.4342944819032518), member.detect(10));
|
||||
Assert.assertEquals(new Double(0.5211533782839021), member.detect(11));
|
||||
Assert.assertEquals(new Double(1.3028834457097553), member.detect(20));
|
||||
Assert.assertEquals(new Double(3.9), member.detect(50), .01);
|
||||
Assert.assertEquals(new Double(8.25), member.detect(100), .01);
|
||||
Assert.assertEquals(new Double(12.6), member.detect(150), .01);
|
||||
Assert.assertEquals(new Double(14.77), member.detect(175), .01);
|
||||
Assert.assertEquals(new Double(Double.POSITIVE_INFINITY), member.detect(500), .01);
|
||||
member.recordHeartbeat(4);
|
||||
Assert.assertEquals(new Double(12.6), member.detect(150), .01);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public void sameHeartbeatTest(){
|
||||
int samples = 1;
|
||||
int windowSize = 1000;
|
||||
LocalGossipMember member = new LocalGossipMember("", URI.create("udp://127.0.0.1:1000"), "", 0L, windowSize, samples);
|
||||
member.recordHeartbeat(5);
|
||||
member.recordHeartbeat(5);
|
||||
member.recordHeartbeat(5);
|
||||
Assert.assertEquals(new Double(0.4342944819032518), member.detect(10));
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,8 @@ public class DataReaperTest {
|
||||
String value = "a";
|
||||
GossipSettings settings = new GossipSettings();
|
||||
GossipManager gm = RandomGossipManager.newBuilder().cluster("abc").settings(settings)
|
||||
.withId(myId).uri(URI.create("udp://localhost:5000")).build();
|
||||
.withId(myId).uri(URI.create("udp://localhost:6000")).build();
|
||||
gm.init();
|
||||
gm.gossipPerNodeData(perNodeDatum(key, value));
|
||||
gm.gossipSharedData(sharedDatum(key, value));
|
||||
Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
|
||||
@ -46,6 +47,7 @@ public class DataReaperTest {
|
||||
gm.getDataReaper().runSharedOnce();
|
||||
TUnit.assertThat(() -> gm.findPerNodeGossipData(myId, key)).equals(null);
|
||||
TUnit.assertThat(() -> gm.findSharedGossipData(key)).equals(null);
|
||||
gm.shutdown();
|
||||
}
|
||||
|
||||
private GossipDataMessage perNodeDatum(String key, String value) {
|
||||
@ -74,7 +76,8 @@ public class DataReaperTest {
|
||||
String value = "a";
|
||||
GossipSettings settings = new GossipSettings();
|
||||
GossipManager gm = RandomGossipManager.newBuilder().cluster("abc").settings(settings)
|
||||
.withId(myId).uri(URI.create("udp://localhost:5000")).build();
|
||||
.withId(myId).uri(URI.create("udp://localhost:7000")).build();
|
||||
gm.init();
|
||||
GossipDataMessage before = perNodeDatum(key, value);
|
||||
GossipDataMessage after = perNodeDatum(key, "b");
|
||||
after.setTimestamp(after.getTimestamp() - 1);
|
||||
@ -82,6 +85,7 @@ public class DataReaperTest {
|
||||
Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
|
||||
gm.gossipPerNodeData(after);
|
||||
Assert.assertEquals(value, gm.findPerNodeGossipData(myId, key).getPayload());
|
||||
gm.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -83,14 +83,14 @@ public class RandomGossipManagerBuilderTest {
|
||||
.uri(new URI("udp://localhost:2000"))
|
||||
.settings(new GossipSettings())
|
||||
.gossipMembers(null).build();
|
||||
|
||||
assertNotNull(gossipManager.getLiveMembers());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useMemberListIfProvided() throws URISyntaxException {
|
||||
LocalGossipMember member = new LocalGossipMember("aCluster", new URI("udp://localhost:2000"), "aGossipMember",
|
||||
System.currentTimeMillis(), new TestNotificationListener(), 60000);
|
||||
LocalGossipMember member = new LocalGossipMember(
|
||||
"aCluster", new URI("udp://localhost:2000"), "aGossipMember",
|
||||
System.nanoTime(), 1000, 1);
|
||||
List<GossipMember> memberList = new ArrayList<>();
|
||||
memberList.add(member);
|
||||
RandomGossipManager gossipManager = RandomGossipManager.newBuilder()
|
||||
@ -99,8 +99,8 @@ public class RandomGossipManagerBuilderTest {
|
||||
.settings(new GossipSettings())
|
||||
.uri(new URI("udp://localhost:8000"))
|
||||
.gossipMembers(memberList).build();
|
||||
assertEquals(1, gossipManager.getLiveMembers().size());
|
||||
assertEquals(member.getId(), gossipManager.getLiveMembers().get(0).getId());
|
||||
assertEquals(1, gossipManager.getDeadMembers().size());
|
||||
assertEquals(member.getId(), gossipManager.getDeadMembers().get(0).getId());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user