第4次实践作业
(1)使用Docker-compose实现Tomcat+Nginx负载均衡
项目结构
.
├── docker-compose.yml
├── nginx
│ └── default.conf
├── tomcat00
│ └── index.html
├── tomcat01
│ └── index.html
└── tomcat02
└── index.html
nginx配置文件
default.conf
upstream tomcats {
server tomcat00:8080;
server tomcat01:8080;
server tomcat02:8080;
}
server {
listen 2420;
server_name localhost;
location / {
proxy_pass http://tomcats;
}
}
docker-compose.yml
version: "3"
services:
nginx:
image: nginx
container_name: nginx0
ports:
- 80:2420
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
depends_on:
- tomcat00
- tomcat01
- tomcat02
tomcat00:
image: tomcat
container_name: tomcat00
volumes:
- ./tomcat00:/usr/local/tomcat/webapps/ROOT # 挂载web目录
tomcat01:
image: tomcat
container_name: tomcat01
volumes:
- ./tomcat01:/usr/local/tomcat/webapps/ROOT
tomcat02:
image: tomcat
container_name: tomcat02
volumes:
- ./tomcat02:/usr/local/tomcat/webapps/ROOT
localhost出错(暂时无法解决)
负载均衡测试
轮询策略(默认)
加权轮询,修改default.conf
2.使用Docker-compose部署javaweb运行环境
javaweb运行环境基于第一个tomcat+nginx负载均衡实验,由于web应用需要用到 JDBC,所以在volumes中还额外的添加了 JDBC相关的JAR包的依赖。数据库使用的是MySQL,使用dockerfile对其镜像进行定制,主要是数据库用户、密码、数据库和基本表的初始化。Dockerfile文件内容如下:
FROM mysql
ENV MYSQL_ROOT_PASSWORD=123456 \
MYSQL_ALLOW_EMPTY_PASSWORD=no \
MYSQL_DATABASE=logintimes
COPY tableinit.sql /docker-entrypoint-initdb.d
执行的sql语句如下:
use logintimes;
create table times(
id int primary key,
times int not null
)DEFAULT CHARSET=latin1;
完整的docker-compose
文件内容如下:
version: "3"
services:
proxy:
image: nginx
container_name: webproxy
ports:
- "80:80"
volumes:
- /usr/local/loadbalance/nginx.conf:/etc/nginx/nginx.conf
cat01:
image: tomcat:8.5.55-jdk8
container_name: cat01
volumes:
- /var/lib/tomcat/apps1:/usr/local/tomcat/webapps
- /var/lib/tomcat/lib/mysql-connector-java-8.0.20.jar:/usr/local/tomcat/lib/mysql-connector-java-8.0.20.jar
cat02:
image: tomcat:8.5.55-jdk8
container_name: cat02
volumes:
- /var/lib/tomcat/apps2:/usr/local/tomcat/webapps
- /var/lib/tomcat/lib/mysql-connector-java-8.0.20.jar:/usr/local/tomcat/lib/mysql-connector-java-8.0.20.jar
cat03:
image: tomcat:8.5.55-jdk8
container_name: cat03
volumes:
- /var/lib/tomcat/apps3:/usr/local/tomcat/webapps
- /var/lib/tomcat/lib/mysql-connector-java-8.0.20.jar:/usr/local/tomcat/lib/mysql-connector-java-8.0.20.jar
database:
container_name: mydb
build: ./mysql
ports:
- "3306:3306"
volumes:
- /var/lib/javaweb/mysql:/var/lib/mysql
从博客园中找到同学写的javaweb应用
简单的记录网站被访问次数并显示给用户,主要操作是从数据库中读取已被访问的次数,然后对次数加1再写入数据库,所以涉及的数据库操作为查询与更新。数据库使用的是MySQL8,与MySQL5有些差异。由于功能简单,在一个函数里就能够实现:
// databaseRelated.class
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";// 与MySQL5有差异
static final String DB_URL = "jdbc:mysql://mydb:3306/logintimes?useSSL=true&serverTimezone=GMT";// 与MySQL5有差异
static final String USER = "root";
static final String PASSWD = "123456";
public static synchronized int updateTimes() {
Connection connection = null;
Statement statement = null;
int times = 0;
try {
Class.forName(JDBC_DRIVER);
System.out.println("Database Connecting...");
connection = DriverManager.getConnection(DB_URL, USER, PASSWD);
statement = connection.createStatement();
String sqlCommand;
sqlCommand = "select times from times where id = 1";
System.out.println(sqlCommand);
ResultSet resultSet = statement.executeQuery(sqlCommand);
if (resultSet.next())
times = resultSet.getInt("times") + 1;
sqlCommand = "update times set times = " + times + " where id = 1";
System.out.println(sqlCommand);
statement.executeUpdate(sqlCommand);
statement.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return times;
}
处理get与post请求的函数也极其简单:
// updateTimes.class
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int times = databaseRelated.updateTimes();
resp.getWriter().write("This website has been visited " + times + " times,this message comes from tomcat x.");// x取决于tomcat服务器,如x=1对应于tomcat01.
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
将该web应用的servlet映射设置成如下形式:
...
<servlet>
<servlet-name>counter</servlet-name>
<servlet-class>updateTimes</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>counter</servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
...
将整个web应用打成war包后,放入到tomcat服务器的持久化存储目录中。然后使用docker-compose up
命令生成镜像并启动。使用浏览器通过url访问该web应用,可以看到如下内容:
负载均衡使用的是权重方式,从返回的信息可以看到网站被访问的次数。