-
Bug
-
Resolution: Fixed
-
Blocker
-
8.6.0.1
-
Security Level: Jimmy
-
ZK 9.0.0 S0
-
None
Core Issue
ZK cannot clear disconnected desktops reliably by remove-desktop requests. Such a no-use desktop causes severe memory problems.
rmDesktop is not sent could be:
- a browser crashes
- the network disconnects
- Chrome energy saver drops a tab
Too many server push events are queued up problem
- the user configures >12 hours session timeout
When scheduling server push events via Executions.schedule or EventQueue.publish (session/application scope) those events are queued in the collection ScheduleInfo DesktopImpl._schedInfos and processed when new requests arrive at server side.
Sometimes the client disconnects without sending and rmDesktop command, in such cases scheduled server push events queue up in the desktop at serverside, without ever being picked up - using more and more memory. Only when the session times out the desktop is finally removed and the memory is GCed again. (especially with longer session timeouts severe problems can occur, with millions of schedule listeners remaining in memory for a long period of time)
A mechanism to detect such disconnected desktops would help to prevent memory problems.
Of course, detecting those desktops directly is not directly possible from the server side.
Possible Improvement
One possibility would be to test the interval between the last processing of the _schedInfos collection and adding a scheduled event
e.g. whenever the a ScheduleListener executes reset the last processing time, and when DesktopImpl.scheduleServerPush is called calculate the difference. If a configurable interval is exceeded (e.g. 5 mins) assume the desktop is not responding anymore and should be destroyed.
In a normal case a scheduled server push event is picked up within a short period of time. Either piggyback of a normal user event, or by a server push dummy request. So that not picked up schedule event listeners are often a good indication of a disconnected browser.
Using this approach a small number of event listeners might still remain in the queue until the session times out - a trade-off between simple code and accuracy.
A trivial custom Desktop implementation can do the following to determine the inactiveInterval:
private long lastEmptyTime = Long.MAX_VALUE; @Override public <T extends Event> void scheduleServerPush(EventListener<T> listener, T event) { long now = System.currentTimeMillis(); if(now - lastEmptyTime > 5000) { this.destroy(); System.out.println("killed desktop: " + this); return; } if(!scheduledServerPush()) { //if queue was empty (i.e. has been processed recently) restart the timer lastEmptyTime = System.currentTimeMillis(); } super.scheduleServerPush(listener, event); }
Alternatives
1. A more accurate/complex solution would involve active watchdog threads checking the _schedInfos queue in configurable intervals to determine disconnected state.
2. OrphanDesktopListener_5912.java
- relates to
-
ZK-4611 Missing rmDesktop in FF with browser popup
- Closed
-
ZK-4193 avoid synchronization blocks with ConcurrentLinkedQueue
- Closed
-
ZK-5435 desktop timeout config doesn't work as expected
- Closed
-
ZK-5436 ZK doesn't remove a desktop after not receiving pong from a browser for a ping interval
- Closed
-
ZK-5611 Executions.schedule() might fail if it's called by multiple threads
- Closed
-
ZK-4654 Connection availability/quality information
- Open