SpringBoot整合Nginx的全部流程
对Nginx还不了解的同学可以先看这篇文章Nginx 相关介绍(Nginx是什么?能干嘛?)
今天的目标是将SpringBoot项目由默认部署方式(jar)替换成war形式,部署在同一台电脑上的两个不同端口的tomcat上,利用Nginx做反向代理,将请求自由的映射到不同端口的tomcat中。
第一步:将SpringBoot项目由默认部署方式(jar)替换成war形式
(1)设置打包方式为war
<groupId>com.sun</groupId><artifactId>mydata</artifactId><version>0.0.1-SNAPSHOT</version><!--因为要放入外部的tomcat中,因此更改默认打包方式(jar)为war包--><packaging>war</packaging><name>mydata</name><description>Demo project for Spring Boot</description>
(2)将SpringBoot内置的Tomcat在发布时剔除,provided表示该包只在编译和测试中使用,在发布时去除。而在发布时,此依赖由servlet容器即Tomcat提供。更详细的解释Maven依赖Scope选项详解
PS:不推荐在spring-boot-starter-web直接将tomcat移除,否则需要添加servlet-api依赖。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency>
(3)由于SpringBoot项目没有传统的web.xml文件,因此我们需要在缺少web.xml文件的情况下构建war包,需要添加以下配置。
<plugin><artifactId>maven-war-plugin</artifactId><version>2.6</version><configuration><!--如果想在没有web.xml文件的情况下构建WAR,请设置为false。--><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin>
(4)更改项目启动类,将之前的启动类删除,新建启动类,继承SpringBootServletInitializer类,重写configure方法,即将启动类交给Servlet容器进行启动。
package com.sun.mydata;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;@SpringBootApplication
public class TMydataApplication extends SpringBootServletInitializer {public static void main(String[] args) {SpringApplication.run(TMydataApplication.class, args);}@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {return builder.sources(TMydataApplication.class);}
}
(5)使用maven package打包项目,拿到war包。
至此,war包已经打包好了。可以修改前端界面,形成两个不同的war包。
之后需要将war包分别放入不同的Tomcat的webapp中。
第二步:在一台机器上配置两个Tomcat
(1)下载Tomcat8,否则低版本的Tomcat启动时,报出找不到javax/el/ELManager类等错误。
(2)下载的Tomcat复制一份,修改这两个Tomcat的配置。
1)避免两个Tomcat启动混乱,需要设置不同CATALINA_HOME
具体方式:修改Tomcat安装目录内的bin/startup.bat,添加以下代码中的中间内容
JAVA_HOME是JDK的安装目录,CATALINA_HOME是对应的Tomcat的安装目录,分别对这两个Tomcat进行修改。
setlocalSET "JAVA_HOME=C:\Java\jdk1.8.0_201"
SET "CATALINA_HOME=D:\tomcat\tomcat2\apache-tomcat-8.5.41"rem Guess CATALINA_HOME if not defined
2)修改Tomcat的端口,防止端口冲突。
仅修改第二个Tomcat安装目录下的conf/server.xml,修改Server port="8006"、Connector port="8081"、redirectPort="8444"、Connector port="8010"、redirectPort="8444"。基本上加1就可以,为了防止潜在的端口冲突,都改了保险点。但Connector port="8081"是必须要改的。
3)设置不加项目名访问,和SpringBoot的访问路径保持一致。
修改Tomcat安装目录下的conf/server.xml,在Host标签下加入该配置。path表示映射后的访问路径,即不需要项目名,docBase表示物理路径,即解压后的war包所处的绝对路径或相对路径。
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"><Context path="/" docBase="D:\tomcat\tomcat2\apache-tomcat-8.5.41\webapps\mydata-0.0.1-SNAPSHOT" reloadable="false"></Context></Host>
此时运行Tomcat安装目录下的bin/startup.bat,可以看到项目正常启动了,但启动的控制台界面可能输出乱码,如下图。
最简单的修改方式为:修改conf/logging.properties下47行左右的UTF-8为GBK
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
java.util.logging.ConsoleHandler.encoding = GBK
再次启动Tomcat,可以看到现在的控制台没有乱码了。
同理,对第二个Tomcat进行以上的配置。
测试一下能够访问主界面
看出来,部署成功了。
最后一步,配置Nginx,这一步相比与之前的配置,简单多了。
(1)修改Nginx安装目录下的conf/nginx.conf,在以下位置设置服务器集群地址。
即添加upstream [name]{...},这个name随便起,不过接下来会用到,需要保持一致。
weight是请求的分配权重,权重越大,对应的Tomcat上接收的请求就越多。
#keepalive_timeout 0;keepalive_timeout 65;#gzip on;upstream mydata {server 127.0.0.1:8080 weight=1;server 127.0.0.1:8081 weight=1;}server {listen 80;server_name localhost;
(2)添加请求转发规则,依然是在nginx.conf中配置。
即通过proxy_pass 配置请求转发地址,访问nginx代理服务器时跳转到指定的服务器。当我们依然输入http://localhost:80 时,请求会跳转到我们配置的服务器。
其中mydata就为之前的name,当我们访问/时,Nginx自动将请求转发至mydata集群中的任意一个Tomcat中。
#charset koi8-r;#access_log logs/host.access.log main;location / {proxy_pass http://mydata;proxy_redirect default; }#error_page 404 /404.html;
更详细的Nginx的配置与说明,参考nginx配置集群,以springboot为例
最后启动Nginx安装目录下的nginx.exe。
在地址栏中输入localhost,即可看到Nginx已经将请求转发至某一个Tomcat中了,不停刷新的话,会出现不同的界面,即分配到不同的Tomcat中(如果界面一直没有变化,可能是浏览缓存造成的,需要在每次的刷新前清除缓存)
第一次点击:
第二次点击:
可见,Nginx已经起到了作用,对整个Tomcat集群做了负载均衡。
到这里,我们就全部配置好了。
关于一致性Session处理,可以单独部署Redis用作Session控制。
更多的架构,可以参考这篇文章高并发的解决方案