Skip to content

Commit

Permalink
Distributed Session Management #7529
Browse files Browse the repository at this point in the history
  • Loading branch information
rymsha committed Oct 28, 2019
1 parent f12f51a commit 40cc924
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.enonic.xp.web.jetty.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.ServletContext;

import org.eclipse.jetty.server.session.SessionCacheFactory;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.osgi.framework.BundleContext;
Expand All @@ -32,8 +32,6 @@ public final class JettyActivator

protected JettyService service;

private JettyConfig config;

private ServiceRegistration controllerReg;

private ServiceRegistration statusReporterReg;
Expand All @@ -44,27 +42,18 @@ public final class JettyActivator

private SessionDataStoreFactory sessionDataStoreFactory;

private SessionCacheFactory sessionCacheFactory;

@Activate
public void activate( final BundleContext context, final JettyConfig config )
throws Exception
{
this.context = context;
fixJettyVersion();

this.config = config;
this.service = new JettyService();
this.service.config = this.config;
this.service.workerName = clusterConfig.name().toString();
if ( clusterConfig.isEnabled() && clusterConfig.isSessionReplicationEnabled() )
{
if ( sessionDataStoreFactory == null )
{
throw new IllegalStateException( "Session replication enabled, but no Session datastore provided" );
}
this.service.sessionDataStoreFactory = sessionDataStoreFactory;
}
this.service =
new JettyService( clusterConfig.name().toString(), sessionDataStoreFactory, sessionCacheFactory, dispatchServlets, config );

this.service.dispatcherServlets = this.dispatchServlets;
this.service.start();

publishController();
Expand Down Expand Up @@ -95,28 +84,28 @@ private void fixJettyVersion()
@Override
public List<ServletContext> getServletContexts()
{
return Arrays.stream( this.service.contexts.getHandlers() ).map(
return this.service.handlers().stream().map(
handler -> ( (ServletContextHandler) handler ).getServletHandler().getServletContext() ).collect( Collectors.toList() );
}

private void publishController()
{
final Hashtable<String, Object> map = new Hashtable<>();
map.put( "http.enabled", this.config.http_enabled() );
map.put( "http.port", this.config.http_xp_port() );
map.put( "http.enabled", this.service.httpEnabled() );
map.put( "http.port", this.service.httpPort() );

this.controllerReg = this.context.registerService( JettyController.class, this, map );
}

private void publishStatusReporter()
{
final HttpThreadPoolStatusReporter statusReporter = new HttpThreadPoolStatusReporter( this.service.server.getThreadPool() );
final HttpThreadPoolStatusReporter statusReporter = new HttpThreadPoolStatusReporter( this.service.getServer().getThreadPool() );
this.statusReporterReg = this.context.registerService( StatusReporter.class, statusReporter, new Hashtable<>() );
}

private void publishThreadPoolInfo()
{
final ThreadPoolInfoImpl threadPoolInfo = new ThreadPoolInfoImpl( this.service.server.getThreadPool() );
final ThreadPoolInfoImpl threadPoolInfo = new ThreadPoolInfoImpl( this.service.getServer().getThreadPool() );
this.statusReporterReg = this.context.registerService( ThreadPoolInfo.class, threadPoolInfo, new Hashtable<>() );
}

Expand All @@ -138,8 +127,14 @@ public void setClusterConfig( final ClusterConfig clusterConfig )
}

@Reference
public void setSessionDataStore( final SessionDataStoreFactory sessionDataStoreFactory )
public void setSessionDataStoreFactory( final SessionDataStoreFactory sessionDataStoreFactory )
{
this.sessionDataStoreFactory = sessionDataStoreFactory;
}

@Reference
public void setSessionCacheFactory( final SessionCacheFactory sessionCacheFactory )
{
this.sessionCacheFactory = sessionCacheFactory;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
import org.eclipse.jetty.server.session.NullSessionCacheFactory;
import org.eclipse.jetty.server.session.SessionCacheFactory;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
Expand All @@ -28,17 +28,31 @@ final class JettyService
{
private final static Logger LOG = LoggerFactory.getLogger( JettyService.class );

protected Server server;
private final JettyConfig config;

protected JettyConfig config;
private final List<DispatchServlet> dispatcherServlets;

protected List<DispatchServlet> dispatcherServlets;
private final SessionDataStoreFactory sessionDataStoreFactory;

protected ContextHandlerCollection contexts;
private final SessionCacheFactory sessionCacheFactory;

protected String workerName;

protected SessionDataStoreFactory sessionDataStoreFactory;
private final String workerName;

private Server server;

private ContextHandlerCollection contexts;

public JettyService( final String workerName, final SessionDataStoreFactory sessionDataStoreFactory,
final SessionCacheFactory sessionCacheFactory, final List<DispatchServlet> dispatcherServlets,
final JettyConfig config )
{
this.workerName = workerName;
this.sessionDataStoreFactory = sessionDataStoreFactory;
this.sessionCacheFactory = sessionCacheFactory;
this.dispatcherServlets = List.copyOf( dispatcherServlets );
this.config = config;
}

public void start()
{
Expand Down Expand Up @@ -70,6 +84,21 @@ public void stop()
}
}

int httpPort()
{
return config.http_xp_port();
}

boolean httpEnabled()
{
return config.http_enabled();
}

List<Handler> handlers()
{
return List.of( contexts.getHandlers() );
}

private void startJetty()
throws Exception
{
Expand All @@ -90,12 +119,6 @@ private void startJetty()
if ( sessionDataStoreFactory != null )
{
this.server.addBean( sessionDataStoreFactory );

NullSessionCacheFactory sessionCacheFactory = new NullSessionCacheFactory();
sessionCacheFactory.setSaveOnCreate( true );
sessionCacheFactory.setRemoveUnloadableSessions( true );
sessionCacheFactory.setFlushOnResponseCommit( true );

this.server.addBean( sessionCacheFactory );
}

Expand Down Expand Up @@ -135,4 +158,14 @@ private void stopJetty()
this.server = null;
LOG.info( "Stopped Jetty" );
}

public Server getServer()
{
return server;
}

public void setServer( Server server )
{
this.server = server;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void testLifecycle()

assertEquals( "9.x", System.getProperty( "jetty.version" ) );
assertNotNull( this.activator.service );
assertTrue( this.activator.service.server.isRunning() );
assertTrue( this.activator.service.getServer().isRunning() );

this.activator.deactivate();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.enonic.xp.web.session.impl;

import java.util.Hashtable;

import org.apache.ignite.Ignite;
import org.eclipse.jetty.server.session.DefaultSessionCache;
import org.eclipse.jetty.server.session.NullSessionCacheFactory;
import org.eclipse.jetty.server.session.NullSessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionCacheFactory;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.enonic.xp.cluster.ClusterConfig;
import com.enonic.xp.web.session.impl.ignite.IgniteSessionDataStoreFactory;

@Component(immediate = true, configurationPid = "com.enonic.xp.web.session")
public class SessionDataStoreFactoryActivator
{
private final static Logger LOG = LoggerFactory.getLogger( SessionDataStoreFactoryActivator.class );

private Ignite ignite;

private ServiceRegistration sessionDataStoreFactoryReg;

private ServiceRegistration sessionCacheReg;

private ClusterConfig clusterConfig;

@Activate
public void activate( final BundleContext context, final WebSessionConfig config )
{
if ( clusterConfig.isEnabled() && clusterConfig.isSessionReplicationEnabled() )
{
if ( ignite == null )
{
LOG.debug( "Waiting for ignite" );
}
else
{
final IgniteSessionDataStoreFactory sessionDataStoreFactory = new IgniteSessionDataStoreFactory( ignite, config );
sessionDataStoreFactory.setSavePeriodSec( config.session_save_period() );

NullSessionCacheFactory sessionCacheFactory = new NullSessionCacheFactory();
sessionCacheFactory.setSaveOnCreate( true );
sessionCacheFactory.setRemoveUnloadableSessions( true );
sessionCacheFactory.setFlushOnResponseCommit( true );
sessionDataStoreFactoryReg =
context.registerService( SessionDataStoreFactory.class, sessionDataStoreFactory, new Hashtable<>() );
sessionCacheReg = context.registerService( SessionCacheFactory.class, sessionCacheFactory, new Hashtable<>() );
}
}
else
{
final NullSessionDataStoreFactory sessionDataStoreFactory = new NullSessionDataStoreFactory();
sessionDataStoreFactory.setSavePeriodSec( config.session_save_period() );
sessionDataStoreFactoryReg =
context.registerService( SessionDataStoreFactory.class, sessionDataStoreFactory, new Hashtable<>() );
sessionCacheReg = context.registerService( SessionCacheFactory.class, DefaultSessionCache::new, new Hashtable<>() );
}
}

@Deactivate
public void deactivate()
throws Exception
{
ignite = null;
sessionDataStoreFactoryReg.unregister();
sessionCacheReg.unregister();
}

@Reference(cardinality = ReferenceCardinality.OPTIONAL)
public void setIgnite( final Ignite ignite )
{
this.ignite = ignite;
}

@Reference
public void setClusterConfig( final ClusterConfig clusterConfig )
{
this.clusterConfig = clusterConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,22 @@
import org.apache.ignite.Ignite;
import org.eclipse.jetty.server.session.AbstractSessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionDataStore;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.server.session.SessionHandler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

import com.enonic.xp.web.session.impl.SessionCacheConfigFactory;
import com.enonic.xp.web.session.impl.WebSessionConfig;

@Component(immediate = true, service = SessionDataStoreFactory.class, configurationPid = "com.enonic.xp.web.session")
public class IgniteSessionDataStoreFactory
extends AbstractSessionDataStoreFactory
{
public static final String WEB_SESSION_CACHE = "com.enonic.xp.webSessionCache";

private Ignite ignite;
private final Cache<String, IgniteSessionData> igniteCache;

private Cache<String, IgniteSessionData> igniteCache;
public IgniteSessionDataStoreFactory( final Ignite ignite, final WebSessionConfig config )
{
this.igniteCache = ignite.getOrCreateCache( SessionCacheConfigFactory.create( WEB_SESSION_CACHE, config ) );
}

@Override
public SessionDataStore getSessionDataStore( final SessionHandler handler )
Expand All @@ -31,18 +29,4 @@ public SessionDataStore getSessionDataStore( final SessionHandler handler )
isds.setSavePeriodSec( getSavePeriodSec() );
return isds;
}

@Activate
public void activate( final WebSessionConfig config )
{
setSavePeriodSec( config.session_save_period() );
igniteCache = ignite.getOrCreateCache( SessionCacheConfigFactory.create( WEB_SESSION_CACHE, config ) );
}

@Reference
public void setIgnite( final Ignite ignite )
{
this.ignite = ignite;
}

}

0 comments on commit 40cc924

Please sign in to comment.