cassandra day sv 2014: infinite session clustering with apache cassandra
DESCRIPTION
In this session Les Hazlewood, the Apache Shiro PMC Chair, will cover Shiro's enterprise session management capabilities, how it can be used across any application (not just web or JEE applications) and how to use Cassandra as Shiro's session store, enabling a distributed session cluster supporting hundreds of thousands or even millions of concurrent sessions. As a working example, Les will show how to set up a session cluster in under 10 minutes using Cassandra. If you need to scale user session load, you won't want to miss this!TRANSCRIPT
@lhazlewood | @goStormpath
Infinite Session Clustering with Apache Shiro & Cassandra
Les Hazlewood @lhazlewood Apache Shiro Project Chair
CTO, Stormpath stormpath.com
Silicon Valley C* Day 2014
@lhazlewood | @goStormpath
.com • User Management and AuthenAcaAon API
• Security for your applicaAons • User security workflows • Security best pracAces • Developer tools, SDKs, libraries
@lhazlewood | @goStormpath
• ApplicaAon security framework
• ASF TLP hMp://shiro.apache.org
• Quick and Easy • Simplifies Security
What is Apache Shiro?
@lhazlewood | @goStormpath
Web Session Management
Auxiliary Features
AuthorizaAon AuthenAcaAon
Cryptography Session
Management
Web Support
@lhazlewood | @goStormpath
Quick Concepts
Subject currentUser = SecurityUtils.getSubject();
currentUser.login(...) currentUser.isPermitted(...)
@lhazlewood | @goStormpath
Session Management Defined
Managing the lifecycle of Subject-‐specific temporal data context
@lhazlewood | @goStormpath
Session Management Features
• Heterogeneous client access • POJO/J2SE based (IoC friendly) • Event listeners • Host address retenAon • InacAvity/expiraAon support (touch()) • Transparent web use -‐ HMpSession • Container-‐Independent Clustering!
@lhazlewood | @goStormpath
Acquiring and CreaNng Sessions Subject subject = SecurityUtils.getSubject() //guarantee a session Session session = subject.getSession(); //get a session if it exists subject.getSession(false);
@lhazlewood | @goStormpath
Session API getStartTimestamp()
getLastAccessTime()
getAttribute(key)
setAttribute(key, value)
get/setTimeout(long)
touch()
...
@lhazlewood | @goStormpath
Session Management Architecture Subject .getSession() à Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
.getSession() à Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
.getSession() à
Session Factory
Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session Factory
Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session ID Generator
Session Factory
Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session ID Generator
Session Cache
Session Factory
Session
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session ID Generator
Session Cache
Session Factory
Session
Data store
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session ID Generator
Session Cache
Session Factory
ValidaAon Scheduler
Session
Data store
@lhazlewood | @goStormpath
Session Management Architecture Subject
SessionManager
SessionDAO
.getSession() à
Session ID Generator
Session Cache
Session Factory
ValidaAon Scheduler Session
Listeners
Session
Data store
@lhazlewood | @goStormpath
Session Clustering: Clustered Data Store of Choice
SessionDAO
Session ID Generator
Session Cache
ValidaAon Scheduler
Data store
@lhazlewood | @goStormpath
Web ConfiguraNon
• web.xml elements
• Protects all URLs
• InnovaAve Filtering (URL-‐specific chains)
• JSP Tag support
• Transparent HMpSession support
@lhazlewood | @goStormpath
web.xml <listener> <listener-class> org.apache.shiro.web.env.EnvironmentLoaderListener </listener-class> </listener> <filter> <filter-name>ShiroFilter</filter-name> <filter-class> org.apache.shiro.web.servlet.ShiroFilter </filter-class> </filter>
@lhazlewood | @goStormpath
web.xml cont’d <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
@lhazlewood | @goStormpath
shiro.ini overview [main] # bean config here [users] # optional static user accounts (and their roles) here [roles] # optional static roles (and their permissions) here [urls] # filter chains here
@lhazlewood | @goStormpath
Session Clustering
@lhazlewood | @goStormpath
Two Approaches • Write a SessionDAO
• Use EnterpriseCacheSessionDAO and
write a CacheManager
@lhazlewood | @goStormpath
Cassandra SessionDAO
@lhazlewood | @goStormpath
SessionDAO Concerns
SessionManager
SessionDAO
Session ID Generator
Session Cache
Data store
@lhazlewood | @goStormpath
Custom SessionDAO public class MySessionDAO extends AbstractSessionDAO { protected void doCreate(Session s){...} protected void doReadSession(Serializable id){...} protected void delete(Session s){...} protected void update(Session s){...}
Collection<Session> getActiveSessions(){...} } Or public class MySessionDAO extends CachingSessionDAO { ... //enables write-through caching }
@lhazlewood | @goStormpath
NaNve Web Session Manager [main] sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager = $sessionManager
@lhazlewood | @goStormpath
Cassandra SessionDAO [main] ... cassandraCluster = com.leshazlewood.samples.shiro.cassandra.ClusterFactory
sessionDAO = com.leshazlewood.samples.shiro.cassandra.CassandraSessionDAO sessionDAO.cluster = $cassandraCluster sessionDAO.keyspaceName = shirosessions sessionDAO.tableName = sessions ...
@lhazlewood | @goStormpath
Plug in the SessionDAO [main] ... sessionManager.sessionDAO = $sessionDAO
@lhazlewood | @goStormpath
Sessions Table (CQL 3) CREATE TABLE sessions ( id timeuuid PRIMARY KEY, start_ts timestamp, stop_ts timestamp, last_access_ts timestamp, timeout bigint, expired boolean, host varchar, serialized_value blob )
@lhazlewood | @goStormpath
No ValidaNon Scheduler?
@lhazlewood | @goStormpath
No ValidaNon Scheduler?
Use Cassandra’s TTL
@lhazlewood | @goStormpath
TTL for session Nmeout [main] # Cassandra can enforce a TTL. # No need for Shiro to invalidate! sessionManager.sessionValidationSchedulerEnabled = false
@lhazlewood | @goStormpath
Session Upsert (CQL 3) UPDATE sessions USING TTL $timeout SET start_ts = ?, stop_ts = ?, last_access_ts = ?, timeout = ?,
expired = ?, host = ?, serialized_value = ? WHERE id = ?
@lhazlewood | @goStormpath
But what about tombstones!?!?
@lhazlewood | @goStormpath
Sessions Table (revised) CREATE TABLE sessions ( id timeuuid PRIMARY KEY, start_ts timestamp, stop_ts timestamp, last_access_ts timestamp, timeout bigint, expired boolean, host varchar, serialized_value blob ) WITH gc_grace_seconds = 86400 AND compacation = {‘class’:’LeveledCompactionStrategy’}
@lhazlewood | @goStormpath
But what about row caching?
@lhazlewood | @goStormpath
Row Cache? Don’t need it! • SSTable likely in OperaAng System page cache (off heap)
• DO use Key Cache (very important, enabled by default in 1.2+)
@lhazlewood | @goStormpath
Demo Time!
@lhazlewood | @goStormpath
Code
$ git clone https://github.com/lhazlewood/shiro-cassandra-sample.git $ cd shiro-cassandra-sample $ $CASSANDRA_HOME/bin/cassandra $ mvn jetty:run Open a browser to http://localhost:8080
@lhazlewood | @goStormpath
Thank You!
• [email protected] • TwiMer: @lhazlewood • hMp://www.stormpath.com