Because I have been obsessed with the design principle and practice of large distributed system. But the conditions are limited, after all, still reading, can not touch the real distributed, real big data. can only on their own computer through the Docker of this virtualization technology to build their own "distributed system" to play, experience a distributed session, distributed things and so on.
This article will build a "distributed" system, and first experience in the Distributed System session management problems, and through the centralized session management solution build two springboot mirrors to provide session service.
First use Springboot to build a restful interface and do some very simple session operations.
Maven:
<parent> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-s Tarter-parent</artifactid> <version>1.4.0.RELEASE</version> <relativepath></rel ativepath> </parent> <dependencies> <dependency> <groupid>org.spri Ngframework.boot</groupid> <artifactId>spring-boot-starter-web</artifactId> </DEP endency> <dependency> <groupId>javax.servlet</groupId> <artifactid >servlet-api</artifactId> <version>2.5</version> </dependency> < Dependency> <groupId>org.springframework.boot</groupId> <artifactid>spring-bo ot-starter-test</artifactid> <scope>test</scope> </dependency> </depend Encies>
Then write a relatively simple controller:
@SpringBootApplication
@RestController Public
class app{
@RequestMapping ("/setsession")
public String Home (HttpServletRequest request) {
request.getsession (). setattribute ("User", "Jack");
Return "I am one." You are session has k-v User-wang. "+request.getsession (). getattribute (" user ");
}
@RequestMapping ("/getsession") public
String session (HttpServletRequest request) {return
"I am one." You are: "+request.getsession (). getattribute (" user ");
public static void Main (string[] args) {
springapplication.run (app.class, args);
}
Now a Springboot project has been written. It provides only two rest interfaces. one sets the session value, one gets the session value. Note that the return value in the above code has an identifier for one . Now we're going to docker it: first by MVN package into a jar package, named Dockerone.jar write dockerfile generate mirrors and run
Dockerfile:
From REGISTRY.CN-HANGZHOU.ALIYUNCS.COM/ALIROBOT/ORACLEJDK8-NSCD #基础源
volume/tmp #挂载
Add Dockerone.jar App.jar #传递jar包
entrypoint ["Java", "-djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
#运行命令
Then run sudo docker build-t dockerone/jdk8. Build the first mirror.
Follow the steps above to build a second mirror: one in the code is changed to two. The mirror name is also changed to DOCKERTWO/JDK8.
Start the above two mirrors, through inspect view IP for 192.168.110.2 192.168.110.3 (Docker Network Bridge for 192.168.110.1) build nginx and build load balance
Docker pull download a nginx after. We write a Nginx profile on this machine, and then mount it to the Docker mirror via the-V data volume.
#使用轮询法做负载均衡, the weights are 1, so the request can be randomly assigned.
upstream webservers{
server 192.168.110.3:8080 weight=1;
Server 192.168.110.2:8080 weight=1;
}
server {
listen ;
server_name localhost;
#charset Koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
Location =/index.html{
root/data;
}
Location/{
proxy_pass http://webservers;
}
}
Start Nginx and view IP as 192.168.110.4 access 192.168.110.4 and observe the cookie and session return values that the browser carries
We know that the first time you visit the site (that is, the user has not created a session), the server's response will carry a Set-cookie value random value. Used to represent the session of the user. The next time the user visits the site, the cookie is brought in to the request with the header information of a cookie. This allows the server to find the user's unique session in memory.
First request/setsession
1. Request assigned to two server: not carrying cookie value, server conforms to e5dd28a3b255aeb9b95c2c5304342685
2. Request assigned to one server: Carry Cookie e5dd28a3b255aeb9b95c2c5304342685 but return to Set-cookie 75965aebc91a57b509bde095602b9f97
3. Request to two send 75965aebc91a57b509bde095602b9f97 but return 60BC939E156DBB21676BCC02EC0C7E2A
4. Request to one send 60BC939E156DBB21676BCC02EC0C7E2A but return e090da9b2aba7b7d08915df78edfa31e
5. Request to two send e090da9b2aba7b7d08915df78edfa31e but return 96ba8fcd5305a75ecc0684f9d541ebde
now request/getsession .
1. Request assign to one carry cookie 96ba8fcd5305a75ecc0684f9d541ebde
The return value is I am one. your session Is:null
Returns the set cookie value of 95833d8765eb2818b220ca9ac53da72c
2. Request assigned to two carry cookies 95833d8765eb2818b220ca9ac53da72c
The return value is I am two. your session Is:null
Returns the Set cookie value 6bfb1d62a6b3925a1774cc51c3b21893
Now we should be clear about the session in the distributed system problem, it is not clear that the user's request will be landed on that server. And for the session is to save the default only on the server you requested to landing, for the next request, if the landing on the server not on the previous request, there is no session information. session Centralized management for distributed session resolution
session centralized management is to unify the user's sessions to a central server (and possibly the central server is also built into a distributed cache cluster).
For our above project, there are three servers now. A Nginx load balancing server. Two servers that provide a rest interface. Now add a session cache server. Let the two rest interface servers give the session to the session cache server to hold.
specific implementation We use Spring-session,session cache in Redis
First, start a redis dcoker mirror. View IP as 192.168.110.5
Dependencies added to Redis in maven:
<parent> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-start Er-parent</artifactid> <version>1.4.0.RELEASE</version> <relativepath></relativ epath> </parent> <dependencies> <dependency> <GROUPID>ORG.SPRINGFR Amework.boot</groupid> <artifactId>spring-boot-starter-web</artifactId> </depende ncy> <dependency> <groupId>javax.servlet</groupId> <artifactId> servlet-api</artifactid> <version>2.5</version> </dependency> <depe Ndency> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-s tarter-test</artifactid> <scope>test</scope> </dependency> <depende Ncy> <Groupid>org.springframework.session</groupid> <artifactId>spring-session</artifactId> <version>1.2.2.RELEASE</version> </dependency> <dependency> & Lt;groupid>org.springframework.boot</groupid> <ARTIFACTID>SPRING-BOOT-STARTER-REDIS</ARTIFAC tid> </dependency> <dependency> <groupid>org.springframework.session</ Groupid> <artifactId>spring-session-data-redis</artifactId> <version>1.2.2.re lease</version> <type>pom</type> </dependency> </dependencies>
Configuration in Springboot:
@SpringBootApplication @RestController @EnableRedisHttpSession public class app{@RequestMapping ("/") public stri
NG Home (HttpServletRequest request) {request.getsession (). setattribute ("User", "XI"); Return "I am two." You are session has k-v User-wang.
"+request.getsession (). getattribute (" user "); @RequestMapping ("/getsession") public String session (HttpServletRequest request) {return "I am two.
You are: "+request.getsession (). getattribute (" user ");
public static void Main (string[] args) {Springapplication.run (app.class, args); #缓存服务器的配置 @Bean public jedisconnectionfactory connectionfactory () {jedisconnectionfactory Rediscon
Nectionfactory = new Jedisconnectionfactory ();
Redisconnectionfactory.setusepool (FALSE);
Redisconnectionfactory.sethostname ("192.168.110.2");
Redisconnectionfactory.setport (6379);
return redisconnectionfactory; }
}
In fact, you can add the following configuration to the properties configuration file;
spring.redis.host=192.168.110.5
spring.redis.port=6379
@EnableRedisHttpSession This annotation is the most important thing, after adding it, Spring produces a new interceptor, used to implement session sharing operations, the implementation of this is not open. This jedisconnectionfactory is configured to have spring connect to Redis based on the configuration in the configuration file.
Now proceed to the previous step, the session problem can be resolved.
because no matter which server the final request landed on, the session shared server returns only one session to the browser, and the browser always carries only one cookie value
At this point we look at the Redis database:
dev@dev:~$ redis-cli -H 192.168.110.5
192.168.110.5:6379> keys *
1) "Spring:session:sessions : 96b04dd3-4045-435f-ac2b-935c2af5eb52 "
3" spring:session:expirations:1484127300000 "
4)" Spring:session: Sessions:expires:96b04dd3-4045-435f-ac2b-935c2af5eb52 "
xxxx
One is the session expiration time, and the other is the cookie value we mentioned earlier.