2004-10-12 jrandom
* Disable the probabalistic drop by default (enable via the router config property "tcp.dropProbabalistically=true") * Disable the actual watchdog shutdown by default, but keep track of more variables and log a lot more when it occurs (enable via the router config property "watchdog.haltOnHang=true") * Implement some tunnel participation smoothing by refusing requests probabalistically as our participating tunnel count exceeds the previous hour's, or when the 10 minute average tunnel test time exceeds the 60 minute average tunnel test time. The probabilities in both cases are oldAverage / #current, so if you're suddenly flooded with 200 tunnels and you had previously only participated in 50, you'll have a 25% chance of accepting a subsequent request.
This commit is contained in:
16
history.txt
16
history.txt
@ -1,4 +1,18 @@
|
||||
$Id: history.txt,v 1.43 2004/10/10 09:57:15 jrandom Exp $
|
||||
$Id: history.txt,v 1.44 2004/10/10 14:33:09 jrandom Exp $
|
||||
|
||||
2004-10-12 jrandom
|
||||
* Disable the probabalistic drop by default (enable via the router config
|
||||
property "tcp.dropProbabalistically=true")
|
||||
* Disable the actual watchdog shutdown by default, but keep track of more
|
||||
variables and log a lot more when it occurs (enable via the router
|
||||
config property "watchdog.haltOnHang=true")
|
||||
* Implement some tunnel participation smoothing by refusing requests
|
||||
probabalistically as our participating tunnel count exceeds the previous
|
||||
hour's, or when the 10 minute average tunnel test time exceeds the 60
|
||||
minute average tunnel test time. The probabilities in both cases are
|
||||
oldAverage / #current, so if you're suddenly flooded with 200 tunnels
|
||||
and you had previously only participated in 50, you'll have a 25% chance
|
||||
of accepting a subsequent request.
|
||||
|
||||
* 2004-10-10 0.4.1.2 released
|
||||
|
||||
|
@ -41,6 +41,8 @@ class RouterThrottleImpl implements RouterThrottle {
|
||||
_context.statManager().createRateStat("router.throttleTunnelProcessingTime1m", "How long it takes to process a message (1 minute average) when we throttle a tunnel?", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
_context.statManager().createRateStat("router.throttleTunnelProcessingTime10m", "How long it takes to process a message (10 minute average) when we throttle a tunnel?", "Throttle", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
_context.statManager().createRateStat("router.throttleTunnelMaxExceeded", "How many tunnels we are participating in when we refuse one due to excees?", "Throttle", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
_context.statManager().createRateStat("router.throttleTunnelProbTooFast", "How many tunnels beyond the previous 1h average are we participating in when we throttle?", "Throttle", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
_context.statManager().createRateStat("router.throttleTunnelProbTestSlow", "How slow are our tunnel tests when our average exceeds the old average and we throttle?", "Throttle", new long[] { 10*60*1000, 60*60*1000, 24*60*60*1000 });
|
||||
}
|
||||
|
||||
public boolean acceptNetworkMessage() {
|
||||
@ -128,6 +130,45 @@ class RouterThrottleImpl implements RouterThrottle {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numTunnels > getMinThrottleTunnels()) {
|
||||
Rate avgTunnels = _context.statManager().getRate("tunnel.participatingTunnels").getRate(60*60*1000);
|
||||
if (avgTunnels != null) {
|
||||
double avg = avgTunnels.getAverageValue();
|
||||
if (avg < numTunnels) {
|
||||
// we're accelerating, lets try not to take on too much too fast
|
||||
double probAccept = avg / numTunnels;
|
||||
if (_context.random().nextDouble() >= probAccept) {
|
||||
// ok
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Probabalistically refusing tunnel request (avg=" + avg
|
||||
+ " current=" + numTunnels + ")");
|
||||
_context.statManager().addRateData("router.throttleTunnelProbTooFast", (long)(numTunnels-avg), 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rate tunnelTestTime10m = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
|
||||
Rate tunnelTestTime60m = _context.statManager().getRate("tunnel.testSuccessTime").getRate(60*60*1000);
|
||||
if ( (tunnelTestTime10m != null) && (tunnelTestTime60m != null) ) {
|
||||
double avg10m = tunnelTestTime10m.getAverageValue();
|
||||
double avg60m = tunnelTestTime60m.getAverageValue();
|
||||
if (avg10m > avg60m) {
|
||||
double probAccept = avg60m/avg10m;
|
||||
if (_context.random().nextDouble() >= probAccept) {
|
||||
// ok
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Probabalistically refusing tunnel request (test time avg 10m=" + avg10m
|
||||
+ " 60m=" + avg60m + ")");
|
||||
_context.statManager().addRateData("router.throttleTunnelProbTestSlow", (long)(avg10m-avg60m), 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String maxTunnels = _context.getProperty(PROP_MAX_TUNNELS);
|
||||
if (maxTunnels != null) {
|
||||
try {
|
||||
@ -154,6 +195,14 @@ class RouterThrottleImpl implements RouterThrottle {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** dont ever probabalistically throttle tunnels if we have less than this many */
|
||||
private int getMinThrottleTunnels() {
|
||||
try {
|
||||
return Integer.parseInt(_context.getProperty("router.minThrottleTunnels", "40"));
|
||||
} catch (NumberFormatException nfe) {
|
||||
return 40;
|
||||
}
|
||||
}
|
||||
|
||||
public long getMessageDelay() {
|
||||
Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000);
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.50 $ $Date: 2004/10/09 19:03:27 $";
|
||||
public final static String ID = "$Revision: 1.51 $ $Date: 2004/10/10 14:33:09 $";
|
||||
public final static String VERSION = "0.4.1.2";
|
||||
public final static long BUILD = 0;
|
||||
public final static long BUILD = 1;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.i2p.router;
|
||||
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -45,7 +47,32 @@ class RouterWatchdog implements Runnable {
|
||||
}
|
||||
|
||||
private boolean shutdownOnHang() {
|
||||
return true;
|
||||
return Boolean.valueOf(_context.getProperty("watchdog.haltOnHang", "false")).booleanValue();
|
||||
}
|
||||
|
||||
private void dumpStatus() {
|
||||
if (_log.shouldLog(Log.ERROR)) {
|
||||
Job cur = _context.jobQueue().getLastJob();
|
||||
if (cur != null)
|
||||
_log.error("Most recent job: " + cur);
|
||||
_log.error("Ready and waiting jobs: " + _context.jobQueue().getReadyCount());
|
||||
_log.error("Job lag: " + _context.jobQueue().getMaxLag());
|
||||
_log.error("Participating tunnel count: " + _context.tunnelManager().getParticipatingCount());
|
||||
|
||||
RateStat rs = _context.statManager().getRate("transport.sendProcessingTime");
|
||||
Rate r = null;
|
||||
if (rs != null)
|
||||
r = rs.getRate(60*1000);
|
||||
double processTime = (r != null ? r.getAverageValue() : 0);
|
||||
_log.error("1minute send processing time: " + processTime);
|
||||
|
||||
rs = _context.statManager().getRate("bw.sendBps");
|
||||
r = null;
|
||||
if (rs != null)
|
||||
r = rs.getRate(60*1000);
|
||||
double kbps = (r != null ? r.getAverageValue() : 0);
|
||||
_log.error("Outbound send rate: " + kbps + "KBps");
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
@ -59,9 +86,14 @@ class RouterWatchdog implements Runnable {
|
||||
boolean ok = verifyJobQueueLiveliness();
|
||||
ok = ok && verifyClientLiveliness();
|
||||
|
||||
if (!ok && shutdownOnHang()) {
|
||||
_log.log(Log.CRIT, "Router hung! hard restart!");
|
||||
System.exit(Router.EXIT_HARD_RESTART);
|
||||
if (!ok) {
|
||||
dumpStatus();
|
||||
if (shutdownOnHang()) {
|
||||
_log.log(Log.CRIT, "Router hung! hard restart!");
|
||||
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
|
||||
// halt and not system.exit, since some of the shutdown hooks might be misbehaving
|
||||
Runtime.getRuntime().halt(Router.EXIT_HARD_RESTART);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,12 +174,17 @@ public class TCPConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldDropProbabalistically() {
|
||||
return Boolean.valueOf(_context.getProperty("tcp.dropProbabalistically", "false")).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement a probabalistic dropping of messages on the queue to the
|
||||
* peer along the lines of RFC2309.
|
||||
*
|
||||
*/
|
||||
private void locked_throttle() {
|
||||
if (!shouldDropProbabalistically()) return;
|
||||
int bytesQueued = 0;
|
||||
long earliestExpiration = -1;
|
||||
for (int i = 0; i < _pendingMessages.size(); i++) {
|
||||
|
Reference in New Issue
Block a user