Spring Boot 应用通常会部署在多个Web服务器上同时提供服务,这样做有很多好处。
- 单个应用宕机不会停止服务,升级应用可以逐个升级而不必停止服务。
- 提高了应用整体的吞吐量
我们称这种方式为水平拓展,前端通过Nginx提供反向代理,回话管理可以通过Spring Session,使用Redis来存放Session。部署Spring Boot 应用带任意一台Web服务器上,从而提高了系统的可靠性和伸缩性。
这里演示一下怎么通过Ngixn + redis 来实现水平拓展实现。
Nginx的安装和配置
安装Nginx
打开Nginx官网(http://nginx.org/),进入下载页面,根据自己的操作系统选择下载即可,这里下的是1.12.2,然后直接解压运行即可。
Nginx启动后,可以访问http://127.0.0.1:80,会看到Nginx的欢迎页面。
配置Nginx
Nginx的配置文件conf/nginx.conf 下包含多个指令块,我们主要关注http 块和 location块。
第一需要在http块中增加upstream指令,内容如下:
upstream backend {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
}
backend 也可以为任意名字,我们在下面的配置将要引用到:
location / {
proxy_pass http://backend;
}
location后可以是一个正则表达式,我们这里用“/”表示所有客户端请求都会传给http://backend,也就是我们配置的backend指令的地址列表。
因为我自己也没有怎么学过nginx在此就不多介绍里面的相关内容
在后面将要创建一个Spring Boot 应用,并且分别以9000和9001两个端口启动,然后在Spring Session的基础上一步步来完成Spring Boot 应用的水平拓展。
使用redis
这里使用redis来保存Session,你需要安装redis,如果未安装,请到https://redis.io/下载安装。
在Spring Boot 中使用redis需要添加以下的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
然后在配置文件application.yml中进行简单的配置:
spring:
redis:
host: 127.0.0.1
port: 6379
这样就能在Spring Boot中使用redis进行缓存
Sprin Session
在默认情况下,Spring Boot 使用Tomcat服务器的Session实现,我们编写一个例子用于测试:
@RestController
@RequestMapping("/session/")
public class SessionController {
Log log = LogFactory.getLog(SessionController.class);
@GetMapping("putsession")
public String putSession(HttpSession session) {
log.info(session.getClass());
log.info(session.getId());
String name = "xhj";
session.setAttribute("user",name);
return "hey," + name;
}
}
如果访问服务/session/putsession,控制台输出为:
2018-03-19 18:43:14.537 INFO 13224 --- [nio-9000-exec-3] c.e.demo.controller.SessionController : class org.apache.catalina.session.StandardSessionFacade
2018-03-19 18:43:14.537 INFO 13224 --- [nio-9000-exec-3] c.e.demo.controller.SessionController : 0DF25B422A362012FC977140ACD45D44
可以看到,Session管理是通过Tomcat提供的:class org.apache.catalina.session.StandardSessionFacade实现的。
Spring Boot 配置很容易切换到不同的Session管理方式,总共有一下几种
- Redis
- JDBC
- Hazelcast
- None
如果想将session存储在redis中需要在,在配置文件application.yml 中添加如下内容:
spring:
...
session:
store-type: redis
然后在pom文件中添加以下依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
修改为配置和增加Spring Session 依赖后,如果访问服务/session/putsession,控制台输出为:
2018-03-19 19:20:47.289 INFO 12444 --- [nio-9001-exec-4] c.e.demo.controller.SessionController : class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
2018-03-19 19:20:47.289 INFO 12444 --- [nio-9001-exec-4] c.e.demo.controller.SessionController : 227a3206-c6f0-496a-85cf-12a6f078959e
可以看到,Session已经替换为HttpSessionWrapper实现,这个类负责Spring Boot的 Session存储类型的具体实现。
Nginx + Redis
在之前我们已经配置了:
upstream backend {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
}
现在假设在本机上部署了两个Spring Boot 应用,使用9000和9001。进入工程目录,运行mvn package,我们看到demo7\target目录下生成了demo-0.0.1-SNAPSHOT.jar 然后进入命令行,进入target目录,启动这个应用:
java -jar target/demo-0.0.1-SNAPSHOT.jar --server.port=9000
打开另一个命令窗口,进入工程目录,运行:
java -jar target/demo-0.0.1-SNAPSHOT.jar --server.port=9001
这时候,我们就有两台Spring Boot 应用。接下来,我们访问以下的地址,并刷新多次:
http://127.0.0.1/session/putsession
这时候就看到两个Spring Boot 应用均有日志输出,比如9000端口的应用控制台输出如下:
2018-03-19 19:50:18.240 INFO 3904 --- [nio-9000-exec-6] c.e.demo.controller.SessionController : class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
2018-03-19 19:50:18.241 INFO 3904 --- [nio-9000-exec-6] c.e.demo.controller.SessionController : 2ab5e152-9ee6-4600-b39c-5b534e045d6d
9001端口的Spring Boot应用也有类似输出:
2018-03-19 19:50:22.234 INFO 3296 --- [nio-9001-exec-8] c.e.demo.controller.SessionController : class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper
2018-03-19 19:50:22.234 INFO 3296 --- [nio-9001-exec-8] c.e.demo.controller.SessionController : 2ab5e152-9ee6-4600-b39c-5b534e045d6d
我们看到,两个Spring Boot应用都具有相同的sessionId,如果停掉任意一台应用,系统还有另外一台服务器提供服务,回话信息保存在Redis中。这样就简单的实现了Spring Session的水平拓展实现。
最后附上完整的application.yml配置:
spring:
redis:
host: 127.0.0.1
port: 6379
session:
store-type: redis
pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<!--更改session为redis管理-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
写的第一篇文章,有很多很多不足的地方,希望大家多多海涵,有帮助的话希望可以关注一下博主 ^ ^
参考资料:《Spring Boot 2 精髓》第十五章