Akik: : Have you been paying attention?
Making: making
CSDN: Check it out??
Hobby: Americano More Ice!
directory
- directory
- Session
- Problems & pain points
- How to solve it?
- Hand-in-hand – Resolve distributed shared sessions
- Lead to
- Don’t talk much, practice first
Session
First of all, what is a Session?
- Storage: Stored on the server.
key-value
Data structure storage - Common scenario: Insert
Cookie
Is used for session persistence - Logic:
client
The first visit toserver
Will respond with aSession id
.client
Temporarily saved to a local directoryCookie
, will be used in future visitscookie
In thesessionId
In theheaders
If no server is found, a new one will be createdSession id
Response to theclient
Problems & pain points
In a distributed cluster, sessions must be shared. Ask why, and I’ll tell you! Of course you don’t ask, I also want to tell you hh🤭🤭
Because we often run into problems like this, cluster load balancing, and when a client accesses a server (is allocated to one of the resource nodes), and for some reason the load balancing mechanism triggers the client to be allocated to another resource node, In this case, the newly allocated resource node does not store the session information of the client. For example, if the client has logged in but does not obtain the session, the user may be forced to log in again.
How to solve it?
This article mainly recommends a spring-Session integration solution. The overall idea is to share sessions in Redis
- Distributed sharing Session- source code
Hand-in-hand – Resolve distributed shared sessions
Lead to
Docker
IDEA
Compile environment
Don’t talk much, practice first
- download
redis
(the default islastest
Version 5.0)
$Docker pull redis: 5.0Pulling from library/redis 69692152171A: Already exists a4a46f2fd7e0: Pull complete bCDf6fDDc3BD: Pull complete 1f499504197d: Pull complete 021b18181099: Pull complete 1fb4123902bc: Pull complete Digest: sha256:c2b0f6fe0588f011c7ed7571dd5a13de58cff538e08d100f0a197a71ea35423a Status: Downloaded newer image for redis: 5.0 docker. IO/library/redis: 5.0Copy the code
- Run the container
$ docker run -itd --name redis-test -p 6379:6379 redis
169ad20a55ab0a9e1f05ec237bbfe01dcd8011c4b937ff17a500d6b4210f6165
#Check whether Redis has been started
$ docker ps | grep redis169 ad20a55ab redis: 5.0 "docker - entrypoint. S..." 5 hours ago Up 5 hours 0.0.0.0:6379->6379/ TCP redis-testCopy the code
- This is a
pox.xml
Documents, only the key parts are listed, i.eredis
Rely on
.<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>.Copy the code
- Write a
restful
Method is used to make requests, and the most important thing about this block of code is that@EnableRedisHttpSession
The source code implementation of this annotation will also be highlighted below
package geektime.spring.web.session;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@SpringBootApplication
@RestController# Here's the point@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SessionDemoApplication.class, args);
}
@RequestMapping("/hello")
public String printSession(HttpSession session, String name) {
String storedName = (String) session.getAttribute("name");
if (storedName == null) {
session.setAttribute("name", name);
storedName = name;
}
return "hello "+ storedName; }}Copy the code
For emphasis, @enableredisHttpSession annotation source code analysis
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
/ / note
@Import({RedisHttpSessionConfiguration.class})
@Configuration
// Implement interface annotations
public @interface EnableRedisHttpSession {
// Sessio default expiration time (30s x 60s=1800s=30min)
int maxInactiveIntervalInSeconds(a) default 1800;
// Session default namespace, 'spring: Session'
String redisNamespace(a) default "spring:session";
// Refresh the default Redis Session mode, 'ON_SAVE' : the Session is committed to Redis only after the Response is committed
RedisFlushMode redisFlushMode(a) default RedisFlushMode.ON_SAVE;
// Clear the default expiration time of Session, 1min
String cleanupCron(a) default "0 * * * * *";
}
Copy the code
Part of the code above note, RedisHttpSessionConfiguration is the key to realize, we will find it is inherited SpringHttpSessionConfiguration
public class RedisHttpSessionConfiguration
extends SpringHttpSessionConfiguration
implements BeanClassLoaderAware.EmbeddedValueResolverAware.ImportAware.SchedulingConfigurer {... }Copy the code
We are into SpringHttpSessionConfiguration see its implementation, registered a SessionRepositoryFilter inside
@Configuration
public class SpringHttpSessionConfiguration implements ApplicationContextAware {...@Bean
public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter(sessionRepository);
sessionRepositoryFilter.setServletContext(this.servletContext);
sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
returnsessionRepositoryFilter; }... }Copy the code
And lacked a sessionRepository parameters, is injected in RedisHttpSessionConfiguration, have implemented the session configuration of the core code
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration implements BeanClassLoaderAware.EmbeddedValueResolverAware.ImportAware.SchedulingConfigurer {...@Bean
public RedisOperationsSessionRepository sessionRepository(a) {
RedisTemplate<Object, Object> redisTemplate = this.createRedisTemplate();
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(redisTemplate);
sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
if (this.defaultRedisSerializer ! =null) {
sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
}
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (StringUtils.hasText(this.redisNamespace)) {
sessionRepository.setRedisKeyNamespace(this.redisNamespace);
}
sessionRepository.setRedisFlushMode(this.redisFlushMode);
int database = this.resolveDatabase();
sessionRepository.setDatabase(database);
returnsessionRepository; }... }Copy the code
- We’ve had a bit of a hiccup, so let’s start our
springboot
Again, after successconsole
The following information is displayed
/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home/bin/java -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=60016:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/lidean/gitee/geektime-spring-family/Chapter 8/session-demo/target/classes:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.1.3.RELEASE/spring-boot-starter-web-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter/2.1.3.RELEASE/spring-boot-starter-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot/2.1.3.RELEASE/spring-boot-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.3.RELEASE/spring-boot-autoconfigure-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.1.3.RELEASE/spring-boot-starter-logging-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/lidean/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/lidean/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.11.2/log4j-to-slf4j-2.11.2.jar:/Users/lidean/.m2/repository/org/apache/logging/log4j/log4j-api/2.11.2/log4j-api-2.11.2.jar:/Users/lidean/.m2/repository/org/slf4j/jul-to-slf4j/1.7.25/jul-to-slf4j-1.7.25.jar:/Users/lidean/.m2/repository/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar:/Users/lidean/.m2/repository/org/yaml/snakeyaml/1.23/snakeyaml-1.23.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.1.3.RELEASE/spring-boot-starter-json-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.8/jackson-databind-2.9.8.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.8/jackson-core-2.9.8.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.9.8/jackson-datatype-jdk8-2.9.8.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.9.8/jackson-datatype-jsr310-2.9.8.jar:/Users/lidean/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.8/jackson-module-parameter-names-2.9.8.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.1.3.RELEASE/spring-boot-starter-tomcat-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.16/tomcat-embed-core-9.0.16.jar:/Users/lidean/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.16/tomcat-embed-el-9.0.16.jar:/Users/lidean/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.16/tomcat-embed-websocket-9.0.16.jar:/Users/lidean/.m2/repository/org/hibernate/validator/hibernate-validator/6.0.14.Final/hibernate-validator-6.0.14.Final.jar:/Users/lidean/.m2/repository/javax/validation/validation-api/2.0.1.Final/validation-api-2.0.1.Final.jar:/Users/lidean/.m2/repository/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar:/Users/lidean/.m2/repository/com/fasterxml/classmate/1.4.0/classmate-1.4.0.jar:/Users/lidean/.m2/repository/org/springframework/spring-web/5.1.5.RELEASE/spring-web-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-beans/5.1.5.RELEASE/spring-beans-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-webmvc/5.1.5.RELEASE/spring-webmvc-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-aop/5.1.5.RELEASE/spring-aop-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-context/5.1.5.RELEASE/spring-context-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-expression/5.1.5.RELEASE/spring-expression-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/boot/spring-boot-starter-data-redis/2.1.3.RELEASE/spring-boot-starter-data-redis-2.1.3.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/data/spring-data-redis/2.1.5.RELEASE/spring-data-redis-2.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/data/spring-data-keyvalue/2.1.5.RELEASE/spring-data-keyvalue-2.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/data/spring-data-commons/2.1.5.RELEASE/spring-data-commons-2.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-tx/5.1.5.RELEASE/spring-tx-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-oxm/5.1.5.RELEASE/spring-oxm-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-context-support/5.1.5.RELEASE/spring-context-support-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:/Users/lidean/.m2/repository/io/lettuce/lettuce-core/5.1.4.RELEASE/lettuce-core-5.1.4.RELEASE.jar:/Users/lidean/.m2/repository/io/netty/netty-common/4.1.33.Final/netty-common-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/netty/netty-handler/4.1.33.Final/netty-handler-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/netty/netty-buffer/4.1.33.Final/netty-buffer-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/netty/netty-codec/4.1.33.Final/netty-codec-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/netty/netty-transport/4.1.33.Final/netty-transport-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/netty/netty-resolver/4.1.33.Final/netty-resolver-4.1.33.Final.jar:/Users/lidean/.m2/repository/io/projectreactor/reactor-core/3.2.6.RELEASE/reactor-core-3.2.6.RELEASE.jar:/Users/lidean/.m2/repository/org/reactivestreams/reactive-streams/1.0.2/reactive-streams-1.0.2.jar:/Users/lidean/.m2/repository/org/springframework/session/spring-session-core/2.1.4.RELEASE/spring-session-core-2.1.4.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-jcl/5.1.5.RELEASE/spring-jcl-5.1.5.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/session/spring-session-data-redis/2.1.4.RELEASE/spring-session-data-redis-2.1.4.RELEASE.jar:/Users/lidean/.m2/repository/org/springframework/spring-core/5.1.5.RELEASE/spring-core-5.1.5.RELEASE.jar geektime.spring.web.session.SessionDemoApplication
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \ / _ ` | \ \ \ \ \ \ / ___) | | _) | | | | | | | (_ | |))))' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3. RELEASE) the 2021-06-04 10:34:48. 97269-122 the INFO [main] G.S.W eb. Session. SessionDemoApplication: Starting SessionDemoApplication on MacBook-Pro-9.local with PID 97269 (started by lidean in / Users/lidean/gitee/geektime - spring - family/Chapter 8 / session - demo) 10:34:48 2021-06-04. 97269-125 the INFO [main] g.s.web.session.SessionDemoApplication : No active profile set, falling back to default profiles: Default 10:34:49 2021-06-04. 97269-209 the INFO [main] S.D.R.C.R epositoryConfigurationDelegate: Multiple Spring Data modules found, entering strict repository configuration mode! The 2021-06-04 10:34:49. 97269-214 the INFO [main]. S.D.R.C.R epositoryConfigurationDelegate: Bootstrapping Spring Data repository in DEFAULT mode. 2021-06-04 10:34:49.247 INFO 97269 -- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 20ms. Found 0 Repository interfaces. 2021-06-04 10:34:50.151 INFO 97269 -- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (HTTP) 10:34:50 2021-06-04. 97269-181 the INFO [main] o.a pache, catalina. Core. StandardService: Starting the service [Tomcat] 2021-06-04 10:34:50. 182 INFO 97269 - [the main] org. Apache. Catalina. Core. StandardEngine: Starting Servlet engine: Apache Tomcat / 9.0.16 10:34:50 2021-06-04. 97269-194 the INFO [main] O.A.C atalina. Core. AprLifecycleListener: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/lidean/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Ex Tensions :/usr/lib/java:.] 2021-06-04 10:34:50.720 INFO 97269 -- [main] O.A.C.C.C. [Tomcat].[/] : Initializing Spring Embedded WebApplicationContext 2021-06-04 10:34:50.720 INFO 97269 -- [main] o.s.web.context.ContextLoader : Root WebApplicationContext: Initialization completed in 2477, the 2021-06-04 ms 10:34:51. 578 INFO 97269 - [the main] IO. Lettuce. Core. EpollProvider: Starting with optional epoll library 10:34:51 2021-06-04. 579 INFO 97269 - [the main] IO. Lettuce. Core. KqueueProvider: Starting without Optional kqueue Library 2021-06-04 10:34:51.970 INFO 97269 -- [main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'97269-2021-06-04 10:34:52. 889 INFO [main] S.A.S cheduledAnnotationBeanPostProcessor: No TaskScheduler/ScheduledExecutorService bean found for scheduled processing 10:34:52 2021-06-04. 97269-920 the INFO [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''97269-2021-06-04 10:34:52. 924 INFO [main] G.S.W eb. Session. SessionDemoApplication: Started SessionDemoApplication in 5.234 seconds (JVM running for 5.782) 2021-06-04 10:34:53.851 INFO 97269 -- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'97269-2021-06-04 10:34:53. 851 INFO [nio - 8080 - exec - 1] O.S.W eb. Servlet. The DispatcherServlet: Initializing the servlet'dispatcherServlet'
2021-06-04 10:34:53.861 INFO 97269 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 10 ms
Copy the code
- Now for our first visit
http://localhost:8080/hello?name=spring
, remember to open itChrome tool
, you can see the createdsession
Enter Redis directly to see the stored K-V data, of course, the specific storage of our information format can also be seen
$ docker exec -it redis-test redis-cli
127.0.0.1:6379> keys *
1) "spring:session:expirations:1622794680000"
2) "spring:session:sessions:expires:1f74b429-8695-47b9-9b24-7adde8bd6aec"
3) "spring:session:sessions:1f74b429-8695-47b9-9b24-7adde8bd6aec"
type spring:session:sessions:1f74b429-8695-47b9-9b24-7adde8bd6aec
hash127.0.0.1:6379 > HGETALL spring: session: f74b429 sessions: 1-8695-47 b9-9 b24 adde8bd6aec 1)"sessionAttr:name"
2) "\xac\xed\x00\x05t\x00\x06spring"
3) "creationTime"
4) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long; \x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x0 0xp\x00\x00\x01y\xd5\xfdO\n"
5) "maxInactiveInterval"
6) "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.N umber\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\a\b"
7) "lastAccessedTime"
8) "\xac\xed\x00\x05sr\x00\x0ejava.lang.Long; \x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x0 0xp\x00\x00\x01y\xd5\xff7\x1e"
Copy the code
- We try to modify access
url
theRequest parameters
, you will find that no matter how the request parameter changes, it will not affect the return result, because the server uses it firstRedis
The cacheSession
Data and information
About the realization of the idea is the above content ~