Created
February 26, 2015 16:48
-
-
Save cbeams/f21bc3f27d380cbce5ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 354f3886f2e457463b446f0f0360ec97388b7f67 (HEAD, origin/master, origin/HEAD, master) | |
Author: Chris Beams <[email protected]> | |
Date: Thu Feb 26 12:12:04 2015 +0100 | |
Externalize http sessions to Redis when on Heroku | |
We are now running the site with multiple dyno instances on Heroku, | |
but Heroku does not support sticky sessions [1]. This means that signed | |
in users don't stay signed in as Heroku load balances user requests | |
across these multiple instances. | |
This commit solves this problem by externalizing the management of HTTP | |
session data to Redis. We already have several Redis instances connected | |
to the site on Heroku, so this is a convenient solution anyway. | |
The externalization of session data is done with a combination of Spring | |
Session [2], Spring Data Redis [3], and the Heroku Spring Cloud | |
Connector [4] (we were already using the latter for connecting to | |
Postgres on Heroku. See DataSourceConfig). | |
The implementation/configuration seen in this commit (simple as it is) | |
was derived from the guide for using Spring Session within a Spring Boot | |
app [5]. | |
Note that sessions are managed in Redis only when the app is deployed on | |
Heroku. When running the app locally, the normal Tomcat HttpSession | |
remains in use as it did before this commit. This reduces the overall | |
complexity of the application by avoiding the need to run a Redis server | |
locally (or run a Redis server embedded). | |
To query and manipulate sessions, connect to the redis instance using | |
`redis-cli` as follows: | |
$ redis-cli -a <password> -h <redis-host> -p <port> | |
Query existing sessions: | |
redis-host:12794> keys 'spring:session:sessions:*' | |
[...] | |
29) "spring:session:sessions:7827ad64-037f-4bf4-b1ce-7d3a8b3c3e12" | |
[...] | |
Delete a session (i.e., sign a user out): | |
redis-host:12794> del spring:session:sessions:7827ad64-037f-4bf4-b1ce-7d3a8b3c3e12" | |
Where the session ID seen above is the value of an individual signed-in | |
user's `SESSION` cookie value. | |
[1]: https://devcenter.heroku.com/articles/node-sessions#sessions-and-scaling | |
[2]: http://docs.spring.io/spring-session/docs/current/reference/html5/ | |
[3]: http://projects.spring.io/spring-data-redis/ | |
[4]: https://github.com/spring-cloud/spring-cloud-connectors/tree/master/spring-cloud-heroku-connector | |
[5]: http://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html | |
diff --git build.gradle build.gradle | |
index a8eae9d..4376565 100644 | |
--- build.gradle | |
+++ build.gradle | |
@@ -36,6 +36,8 @@ dependencies { | |
compile 'org.projectlombok:lombok:1.14.8' | |
compile "com.mandrillapp.wrapper.lutung:lutung:0.0.5" | |
compile "com.h2database:h2" | |
+ compile "org.springframework.session:spring-session-data-redis:1.0.0.RELEASE" | |
+ compile "org.springframework.data:spring-data-redis:1.4.2.RELEASE" | |
runtime "org.flywaydb:flyway-core:3.1" | |
runtime "org.postgresql:postgresql:9.3-1102-jdbc41" | |
testCompile "org.springframework.boot:spring-boot-starter-test" | |
diff --git src/main/java/com/example/site/config/HttpSessionConfiguration.java src/main/java/com/example/site/config/HttpSessionConfiguration.java | |
new file mode 100644 | |
index 0000000..5c9c2bc | |
--- /dev/null | |
+++ src/main/java/com/example/site/config/HttpSessionConfiguration.java | |
@@ -0,0 +1,21 @@ | |
+package com.example.site.config; | |
+ | |
+import org.springframework.cloud.config.java.AbstractCloudConfig; | |
+import org.springframework.context.annotation.Bean; | |
+import org.springframework.context.annotation.Configuration; | |
+import org.springframework.context.annotation.Profile; | |
+import org.springframework.data.redis.connection.RedisConnectionFactory; | |
+import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; | |
+ | |
+import static com.example.site.Profiles.cloud_db; | |
+ | |
+@Profile(cloud_db) | |
+@Configuration | |
+@EnableRedisHttpSession | |
+class HttpSessionConfiguration extends AbstractCloudConfig { | |
+ | |
+ @Bean | |
+ public RedisConnectionFactory redisConnectionFactory() { | |
+ return connectionFactory().redisConnectionFactory(); | |
+ } | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment