@@ -159,6 +159,7 @@ protected MessageDigest initialValue() {
159159
160160 // Pool data
161161 private MaintThread maintThread ;
162+ private TrafficThread trafficThread ;
162163 private boolean initialized = false ;
163164 private int maxCreate = 1 ; // this will be initialized by pool when the pool is initialized
164165
@@ -170,6 +171,7 @@ protected MessageDigest initialValue() {
170171 private long maxIdle = 1000 * 60 * 5 ; // max idle time for avail sockets
171172 private long maxBusyTime = 1000 * 30 ; // max idle time for avail sockets
172173 private long maintSleep = 1000 * 30 ; // maintenance thread sleep time
174+ private long traffictSleep = 1000 * 120 ;
173175 private int socketTO = 1000 * 3 ; // default timeout of socket reads
174176 private int socketConnectTO = 1000 * 3 ; // default timeout of socket connections
175177 private boolean aliveCheck = false ; // default to not check each connection for being alive
@@ -346,6 +348,22 @@ public static SockIOPool getInstance() {
346348 */
347349 public long getMaintSleep () { return this .maintSleep ; }
348350
351+
352+ /**
353+ * Set the sleep time between runs of the pool traffic thread.
354+ * If set to 0, then the traffic thread will not be started.
355+ *
356+ * @param maintSleep sleep time in ms
357+ */
358+ public void setTraffictSleep ( long traffictSleep ) { this .traffictSleep = traffictSleep ; }
359+
360+ /**
361+ * Returns the current traffic thread sleep time.
362+ *
363+ * @return sleep time in ms
364+ */
365+ public long getTraffictSleep () { return this .traffictSleep ; }
366+
349367 /**
350368 * Sets the socket timeout for reads.
351369 *
@@ -637,6 +655,10 @@ public void initialize() {
637655 // start maint thread
638656 if ( this .maintSleep > 0 )
639657 this .startMaintThread ();
658+
659+ if ( this .traffictSleep > 0 ) {
660+ this .startTrafficThread ();
661+ }
640662 }
641663 }
642664
@@ -1282,6 +1304,74 @@ protected void stopMaintThread() {
12821304 maintThread .stopThread ();
12831305 }
12841306
1307+
1308+ /**
1309+ * Starts the traffic thread.
1310+ *
1311+ * This thread will send fake traffic to ELB<br/>
1312+ * in order to avoid ELB closing the connection<br/>
1313+ * after an idle time.
1314+ */
1315+ protected void startTrafficThread () {
1316+
1317+ if ( trafficThread != null ) {
1318+
1319+ if ( trafficThread .isRunning () ) {
1320+ log .error ( "traffic thread already running" );
1321+ }
1322+ else {
1323+ trafficThread .start ();
1324+ }
1325+ }
1326+ else {
1327+ trafficThread = new TrafficThread ( this );
1328+ trafficThread .setInterval ( this .traffictSleep );
1329+ trafficThread .start ();
1330+ }
1331+ }
1332+
1333+ /**
1334+ * Stops the traffic thread.
1335+ */
1336+ protected void stopTrafficThread () {
1337+ if ( trafficThread != null && trafficThread .isRunning () )
1338+ trafficThread .stopThread ();
1339+ }
1340+
1341+
1342+ /**
1343+ *Fake traffic on avaliable pool to avoid ELB idle timeout
1344+ *
1345+ * This is typically called by the traffic thread to fake traffic.
1346+ */
1347+ protected void sendTrafficToAvailablePool () {
1348+ if ( log .isDebugEnabled () )
1349+ log .debug ( "++++ Traffic thread started" );
1350+
1351+ synchronized ( this ) {
1352+ if ( availPool != null && !availPool .isEmpty () ) {
1353+ for (Iterator <String > i = availPool .keySet ().iterator (); i .hasNext (); ) {
1354+ String host = i .next ();
1355+ Map <SockIO , Long > sockets = availPool .get (host );
1356+
1357+ for (Iterator <SockIO > j = sockets .keySet ().iterator (); j .hasNext (); ) {
1358+ SockIO socket = j .next ();
1359+ try {
1360+ socket .write ( "version\r \n " .getBytes () );
1361+ socket .flush ();
1362+
1363+ if (log .isDebugEnabled ())
1364+ log .debug ("Version: " + socket .readLine ());
1365+ } catch ( IOException ex ) {
1366+ if (log .isDebugEnabled ())
1367+ log .debug ("Fake traffic: " + ex );
1368+ }
1369+ }
1370+ }
1371+ }
1372+ }
1373+ }
1374+
12851375 /**
12861376 * Runs self maintenance on all internal pools.
12871377 *
@@ -1504,6 +1594,67 @@ public void run() {
15041594 }
15051595 }
15061596
1597+ /**
1598+ * Class which extends thread and send traffic to ELB by period.
1599+ *
1600+ */
1601+ protected static class TrafficThread extends Thread {
1602+
1603+ // logger
1604+ private static Logger log =
1605+ Logger .getLogger ( TrafficThread .class .getName () );
1606+
1607+ private SockIOPool pool ;
1608+ private long intervalFakeTraffic = 10000 * 3 ; // every 3 seconds
1609+ private boolean stopThread = false ;
1610+ private boolean running ;
1611+
1612+ protected TrafficThread ( SockIOPool pool ) {
1613+ this .pool = pool ;
1614+ this .setDaemon ( true );
1615+ this .setName ( "TrafficThread" );
1616+ }
1617+
1618+ public void setInterval ( long interval ) { this .intervalFakeTraffic = interval ; }
1619+
1620+ public boolean isRunning () {
1621+ return this .running ;
1622+ }
1623+
1624+ /**
1625+ * sets stop variable
1626+ * and interupts any wait
1627+ */
1628+ public void stopThread () {
1629+ this .stopThread = true ;
1630+ this .interrupt ();
1631+ }
1632+
1633+ /**
1634+ * Start the thread.
1635+ */
1636+ public void run () {
1637+ this .running = true ;
1638+
1639+ while ( !this .stopThread ) {
1640+ try {
1641+ Thread .sleep ( intervalFakeTraffic );
1642+
1643+ // if pool is initialized, then
1644+ // run the sendTrafficToAvailablePool method on itself
1645+ if ( pool .isInitialized () )
1646+ pool .sendTrafficToAvailablePool ();
1647+
1648+ }
1649+ catch ( Exception e ) {
1650+ break ;
1651+ }
1652+ }
1653+
1654+ this .running = false ;
1655+ }
1656+ }
1657+
15071658 /**
15081659 * MemCached client for Java, utility class for Socket IO.
15091660 *
0 commit comments