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:
jrandom
2004-10-12 21:29:41 +00:00
committed by zzz
parent 8329d045f1
commit f799a25aeb
5 changed files with 107 additions and 7 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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++) {