之前使用nginx配置代理,还是nginx + php。记忆中就是配置一下虚拟主机,以及修改一下linux的hosts文件。。。总之,对nginx的使用很少。前几天阿里云服务器到期了,又入手了腾讯云一款服务器。(ps:个人觉得这款服务器性价比很高,对喜欢折腾服务器的同学来说,还不错。有意愿入手的朋友:点这里腾讯云:1核2G 1M带宽 50G系统盘,18个月120元,活动8月20号到期哦QAQ)
入手服务器后,先搭好java的开发环境以及目前流行的redis和消息队列(包括jdk + tomcat + nginx + mysql + redis + rabbimq)。
然后昨天又部署了一下nginx+tomcat+java,主要玩一下nginx的反向代理和负载均衡,出现了很多问题,记录一下。。
这里我使用war部署到tomcat。
了解nginx配置:
Nginx配置文件详解
Nginx location模块整理
Nginx配置文件详解2
操作系统:腾讯云 Ubuntu Server 16.04.1 LTS 64位
数据库:mysql5.7
demo项目:Spring Boot
////////////////////////// 安装过程及查询资料 //////////////////////////
安装jdk1.8
https://www.cnblogs.com/eczhou/p/7860592.html
安装tomcat
安装mysql
https://www.linuxidc.com/Linux/2017-05/143864.htm
安装git
安装nginx
使用命令apt-get install nginx
直接安装;
安装redis
https://blog.csdn.net/hkw207/article/details/72850306
安装rabbitmq
/////////////////////////// 安装目录记录 //////////////////////////
tomcat
mysql
root 123456
ps:java web项目打war包部署到tomcat具体方法可以参考我上一篇博客:spring boot 项目部署到服务器 两种方式
这里,要做nginx负载均衡,因为我只有一台服务器,那我们启动两个tomcat(tomcat1和tomcat2),运行同一个项目,tomcat1配置端口:8080;tomcat2配置端口:8081;
1.我新建了一个基于spring boot的简单demo项目,源码在这:demo1
嫌麻烦的同学可以下载到本地,打成war包。这个demo项目只是简单的输出了一下日志,所有测试代码都在入口文件里面:
package com.example.demo1;
import com.example.demo1.utils.BusiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@SpringBootApplication
@RestController
public class Demo1Application extends SpringBootServletInitializer {
private static Logger logger = LoggerFactory.getLogger(Demo1Application.class);
@RequestMapping("/")
public String home() {
Date now = new Date();
// 访问时,tomcat日志打印,便于观察
logger.info("url:{},time:{},", "/", now);
return "hello 朋友";
}
@RequestMapping("/user/{id}")
public String getUser(@PathVariable("id") Integer id) {
if (id == null) {
throw new BusiException(500, "参数错误");
}
Date now = new Date();
logger.info("url:{},time:{},id:{}", "/user/{id}", now, id);
return "user:...........";
}
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Demo1Application.class);
}
}
2.下载一个Apache tomcat8,并复制一份
复制的tomcat需要修改配置文件:server.xml
server.xml文件中有三个端口必须重新设置,不然端口会冲突:
"8005" shutdown="SHUTDOWN"> :关闭时使用
"8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> : 一般应用使用
"8009" protocol="AJP/1.3" redirectPort="8443" />:为AJP端口,即容器使用,如 APACHE能通过AJP协议访问Tomcat的8009端口
#### 上面的3个端口,复制的时候,一定要修改;不然启动时端口会冲突。
#### 这里我们把复制的tomcat中这3个端口对应都加上1。
#### 8006/8081/8010
上面的截图中,你会发现我将demo1.war
包放到了两个tomcat的同级目录下面,而不是直接放到tomcat的webapps目录下。如果你跟我一样,将demo1.war放到tomcat外面,那么你需要做一件事情,就是在tomcat中指定启动的时候,tomcat去哪里找war包。你也可以将war包直接放到两个tomcat的webapps下面运行,就不需要管下面的步骤。
具体操作:找到tomcat的server.xml
配置文件,往文件中的
节点添加下面一句:
<Context path="/demo1" docBase="/opt/project/demo1.war" reloadable="true"/>
tomcat1,server.xml完整代码如下:
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/demo1" docBase="/opt/project/demo1.war" reloadable="true"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
Host>
Engine>
Service>
Server>
tomcat2,server.xml完整代码如下:
<Server port="8006" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
GlobalNamingResources>
<Service name="Catalina">
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="/demo1" docBase="/opt/project/demo1.war" reloadable="true"/>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
Host>
Engine>
Service>
Server>
启动两个tomcat,然后访问,看是否启动成功:服务器Ip:端口/项目名称
ok,同一项目部署到多个tomcat这一步成功!!!!!!!!
1.修改nginx配置
vim /etc/nginx/nginx.conf
# 修改nginx配置文件,加入upstream location
nginx -t # 检查配置是否正确
nginx -s reload #重新读取配置,让配置生效,不需要重启nginx
2.ok,现在我们测试是否nginx简单的负载均衡是否成功了。
2.1 先用tail命令,打开两个tomcat的日志:如下
root@VM-0-14-ubuntu:/etc/nginx# cd /opt/project/
root@VM-0-14-ubuntu:/opt/project# ll
total 17628
drwxr-xr-x 4 root root 4096 Aug 14 09:47 ./
drwxr-xr-x 6 root root 4096 Aug 13 12:42 ../
drwxr-xr-x 9 root root 4096 Aug 13 11:09 apache-tomcat-8.5.32/
drwxr-xr-x 9 root root 4096 Aug 13 14:08 apache-tomcat-8.5.32-2/
-rw-r--r-- 1 root root 18008700 Aug 14 09:47 demo1.war
root@VM-0-14-ubuntu:/opt/project# tail -f apache-tomcat-8.5.32*/logs/catalina.out # 同时查看两个tomcat的日志,这里用了通配符*
==> apache-tomcat-8.5.32-2/logs/catalina.out <==
2018-08-14 10:02:30.434 INFO 23146 --- [nio-8081-exec-3] com.example.demo1.Demo1Application : url:/,time:Tue Aug 14 10:02:30 CST 2018,
==> apache-tomcat-8.5.32/logs/catalina.out <==
2018-08-14 10:02:29.181 INFO 23115 --- [nio-8080-exec-4] com.example.demo1.Demo1Application : url:/,time:Tue Aug 14 10:02:29 CST 2018,
2.2 浏览器请求多次(比如连续20次),查看日志变化
注意,这个时候请求就不要端口号了,直接访问ip/项目名称。nginx会负责去判断这一次由哪一个tomcat处理该请求,并转发给2个tomcat中的其中一个处理。
从日志看出,tomcat1执行一次,马上tomca2执行一次,紧接着下一次收到请求,tomcat1又执行了。这个跟nginx的调度有关系,且可以配置每个服务器的权重!!这个后续再研究!
我的nginx:
# Default server configuration
#
upstream malls_server{
server localhost:8080;
server localhost:8081;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
#root /var/www/html;
# Add index.php to the list if you are using PHP
#index index.html index.htm index.nginx-debian.html;
server_name 132.232.54.105 localhost;
location = /upgrading.html {
root /var/www/html/;
}
# location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
# return 200 '系统维护中......';
# return 503;
# }
location / {
if ($request_method = OPTIONS ) {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,Content-Type,Accept;
return 200;
}
proxy_pass http://malls_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Connection "";
client_max_body_size 250m;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
#root html;
root /var/www/html/upgrading.html;
}
}