[keycloak-dev] Offline sessions preloading PR
Marek Posolda
mposolda at redhat.com
Tue Nov 13 13:18:43 EST 2018
I sent PR https://github.com/keycloak/keycloak/pull/5716 for fixes and
performance improvements about the preloading of offline sessions. With
this, the preloading of offline sessions at startup is still required,
however it is highly optimized. Without this, preloading of 500K
sessions on my laptop took 16 minutes (some customers reported 40
minutes in real environment). Now it is 18 seconds on my laptop.
Moreover the preloading time was previously exponentially dependent to
the total count of sessions, now it is lineary dependent.
I know it will be even better to remove a need for preloading entirely,
but there are few kinks around it. Hopefully in the future, we can
delegate persistence of userSessions to infinispan entirely.
The summary of changes in the PR:
- It is not required anymore to lookup User at the startup when the
UserSession is preloaded. In case that user is not available anymore at
the time of preloading (which can happen especially with 3rd party
UserStorage providers, for example when user was directly deleted from
LDAP), then UserSession will be removed anyway later from both
infinispan and DB due the fact that it will become expired as user
doesn't exists and it won't be possible to refresh token.
- The pagination SQL queries are based on "seeking" rather then classic
pagination based on offset. See
https://www.eversql.com/faster-pagination-in-mysql-why-order-by-with-limit-and-offset-is-slow/
and https://use-the-index-luke.com/sql/partial-results/fetch-next-page
for details. This proved to have much better performance (at least for
MySQL, but probably for the other DBs too)
- DB Index added for column LAST_SESSION_REFRESH of table
OFFLINE_USER_SESSION for the seeking above
- Sessions are put to infinispan through the "cache.putAll" instead of
many separate calls of "cache.put" . This is important especially for
cluster and cross-dc, as when you call "cache.put" 100 times, you may
have around 100 network calls, when with "cache.putAll" it is 1 bigger
network call.
- When some offline sessions are refreshed, there is bulk update of
lastSessionRefresh times to DB every minute. So there is no DB write for
each token refresh, but bulk update similarly like we have for cross-dc.
This allows more proper tracking of expired sessions from both DB and
Infinispan and there is no need for a workaround to automatically update
all sessions at startup to the current time (which was problematic for
environments with often restarts as offline sessions were defacto never
expired). JIRA with the details is
https://issues.jboss.org/browse/KEYCLOAK-5479 .
A side-effect is, that UserSessionInitializerTest seems to be fixed now
- https://issues.jboss.org/browse/KEYCLOAK-8723 . TBH I am not sure
about exact cause why it is failing on master, however with latest
master, it failed for me after 50 runs when running this test in a loop
on my laptop. Similar behaviour was seen by Sebastian as well on his
laptop. With this PR, I had more than 300 runs without any failure.
Marek
More information about the keycloak-dev
mailing list