第4次系统综合实践作业
使用Docker-compose实现Tomcat+Nginx负载均衡
1.nginx反向代理原理
反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。
2.nginx代理tomcat集群,代理2个以上tomcat
(1)项目结构
.
├── docker-compose.yml
├── nginx
│ └── default.conf
├── tomcat1
│ └── index.html
├── tomcat2
│ └── index.html
└── tomcat3
└── index.html
(2)相关文件编写
- default.conf文件
upstream tomcats {
server tct1:8080 ;
server tct2:8080 ;
server tct3:8080 ;
}
server {
listen 2313;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
proxy_pass http://tomcats;
}
}
- docker-compose.yml文件
version: "3.8"
services:
nginx:
image: nginx
container_name: tngx
ports:
- 80:2313
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
depends_on:
- tomcat1
- tomcat2
- tomcat3
tomcat1:
image: tomcat
container_name: tct1
volumes:
- ./tomcat1:/usr/local/tomcat/webapps/ROOT # 挂载web目录
tomcat2:
image: tomcat
container_name: tct2
volumes:
- ./tomcat2:/usr/local/tomcat/webapps/ROOT
tomcat3:
image: tomcat
container_name: tct3
volumes:
- ./tomcat3:/usr/local/tomcat/webapps/ROOT
(3)执行docker-compose.yml文件
sudo docker-compose up -d
3.添加nginx反向代理服务,实现负载均衡
(1)轮询策略(默认策略)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
测试:
import requests
url='http://localhost'
for i in range(0,6):
response=requests.get(url)
print(response.text)
测试成功,结果如下:
按照3 1 2的顺序依次访问。
(2)weight策略(权重策略)
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
需要修改default.conf配置文件:
upstream tomcats {
server tct1:8080 weight=1;
server tct2:8080 weight=2;
server tct3:8080 weight=3;
}
测试:
import requests
url = 'http://localhost'
count={}
for i in range(0,30):
response=requests.get(url)
if response.text in count:
count[response.text] += 1
else:
count[response.text] = 0
print(response.text)
print(count)
测试成功,测试结果如下:
其中Tomcat1、Tomcat2、Tomcat3分别以1:2:3的比例被进行访问
使用Docker-compose部署javaweb运行环境
1.项目结构
.
├── default.conf
├── docker-compose.yml
├── docker-entrypoint.sh
├── Dockerfile
├── grogshop.sql
└── webapps
2.相关文件编写
- default.conf文件
upstream tomcats {
server tomcat00:8080;
server tomcat01:8080;
}
server {
listen 2313;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.html;
proxy_pass http://tomcats;
}
}
- Dockerfile文件
#基础镜像
FROM registry.saas.hand-china.com/tools/mysql:5.7.17
#mysql的工作目录
ENV WORK_PATH /usr/local/
#定义会被容器自动执行的目录
ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
#复制grogshop.sql到/usr/local
COPY grogshop.sql /usr/local/
#复制要执行的shell文件到/docker-entrypoint-initdb.d/目录下
COPY docker-entrypoint.sh $AUTO_RUN_DIR/
#给执行文件增加可执行权限
RUN chmod a+x $AUTO_RUN_DIR/docker-entrypoint.sh
- docker-compose文件
version: "3"
services:
tomcat00:
image: tomcat
container_name: tomcat00
volumes:
- "./webapps:/usr/local/tomcat/webapps"
networks:
webnet:
ipv4_address: 15.22.0.15
tomcat01:
image: tomcat
container_name: tomcat01
volumes:
- "./webapps:/usr/local/tomcat/webapps"
networks:
webnet:
ipv4_address: 15.22.0.16
mymysql:
build: .
image: mysql
container_name: mymysql
ports:
- "3309:3306"
command: [
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci'
]
environment:
MYSQL_ROOT_PASSWORD: "123456"
networks:
webnet:
ipv4_address: 15.22.0.6
nginx:
image: nginx
container_name: nginx_tomcat
ports:
- 80:2313
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- tomcat00
- tomcat01
tty: true
stdin_open: true
networks:
webnet:
ipv4_address: 15.22.0.7
networks:
webnet:
driver: bridge
ipam:
config:
-
subnet: 15.22.0.0/24
- docker-entrypoint.sh文件
#!/bin/bash
mysql -uroot -p123456 << EOF
source /usr/local/grogshop.sql;
借用教程里的Javaweb项目,并修改连接数据库的ip
webapps/ssmgrogshop_war/WEB-INF/classes/jdbc.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://10.0.2.15:3309/grogshop?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
3.执行docker-compose文件
sudo docker-compose up -d
4.浏览器访问页面(localhost/ssmgrogshop_war/)
进入登录页面(登录名sa,密码123)
登录之后进行插入操作
- 查询操作
- 插入操作
使用Docker搭建大数据集群环境
1.pull Ubuntu镜像并在本地创建工作目录
sudo docker pull ubuntu
cd ~
mkdir build
sudo docker run -it -v /home/monster/build:/root/build --name ubuntu ubuntu
其中,build
文件夹用来本地与Ubuntu容器进行共享文件
2.Ubuntu容器初始化
- 更新软件源
apt-get update
- 安装vim(便于在容器中编辑文件)
apt-get install vim
- 安装ssh(在开启分布式Hadoop时,需要用到ssh连接slave节点)
apt-get install ssh
- 开启sshd服务器:
/etc/init.d/ssh start # 运行脚本即可开启sshd服务器
vim ~/.bashrc
/etc/init.d/ssh start # 在该文件中最后一行添加如下内容,实现进入Ubuntu系统时,都能自动启动sshd服务
- 配置ssh
cd ~/.ssh
ssh-keygen -t rsa #一直按回车即可
cat id_rsa.pub >> authorized_keys
- 安装JDK
apt-get install openjdk-8-jdk
vim ~/.bashrc # 在文件末尾添加以下两行,配置Java环境变量:
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
export PATH=$PATH:$JAVA_HOME/bin
source ~/.bashrc # 使.bashrc生效
- 保存新镜像文件
sudo docker commit 容器ID ubuntu:jdk8 jkd8版本的ubuntu
sudo docker run -it -v /home/monster/build:/root/build --name ubuntu-jdk8 ubuntu:jdk8 #开启保存镜像ubuntu:jdk8容器
3.安装Hadoop
cd /root/build
#将hadoop压缩包放入本地build文件夹中,这里使用大数据实验中的3.1.3版本
tar -zxvf hadoop-3.1.3.tar.gz -C /usr/local
cd /usr/local/hadoop-3.1.3
./bin/hadoop version # 验证安装
4.配置Hadoop
- 进入工作目录
cd /usr/local/hadoop-3.1.3/etc/hadoop
- hadoop-env.sh文件(修改JAVA_HOME)
vim hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ # 在任意位置添加
- core-site.xml文件
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop-3.1.3/tmp</value>
<description>A base for other temporary directories.</description>
</property>
</configuration>
- hdfs-site.xml文件
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop-3.1.3/tmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop-3.1.3/tmp/dfs/data</value>
</property>
</configuration>
- mapred-site.xml文件
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
<property>
<name>mapreduce.application.classpath</name>
<value>/usr/local/hadoop-3.1.3/share/hadoop/mapreduce/lib/*,/usr/local/hadoop-3.1.3/share/hadoop/mapreduce/*</value>
</property>
</configuration>
- yarn-site.xml文件
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>2.5</value>
</property>
</configuration>
- 对于start-dfs.sh和stop-dfs.sh文件
cd /usr/local/hadoop-3.1.3/sbin
添加一下参数:
HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
- 对于start-yarn.sh和stop-yarn.sh,添加下列参数:
YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
- 再次保存镜像
sudo docker commit 容器id ubuntu/hadoop
- 分别打开三个终端,运行ubuntu/hadoop容器
# 第一个终端
sudo docker run -it -h master --name master ubuntu/hadoop
# 第二个终端
sudo docker run -it -h slave01 --name slave01 ubuntu/hadoop
# 第三个终端
sudo docker run -it -h slave02 --name slave02 ubuntu/hadoop
- 三个终端分别查看/etc/hosts,get各自的IP
cat /etc/hosts
- 将三个终端的地址分别在添加到各自的/etc/hosts文件中
172.17.0.4 master
172.17.0.5 slave01
172.17.0.6 slave02
- 在master节点终端检测下master是否可以连上slave01和slave02
ssh slave01
ssh slave02
exit #连接上slave节点后从slave节点退回master节点
- 修改workers文件
#将localhost替换为以下两行
slave01
slave02
5.启动Hadoop集群
- 在master终端上,首先进入/usr/local/hadoop-3.1.3
- 格式化并启动hadoop
cd /usr/local/hadoop-3.1.3
bin/hdfs namenode -format #首次启动Hadoop需要格式化
sbin/start-all.sh #启动Hadoop
- 运行命令jps查看运行结果
master节点:
slave01节点:
slave02节点:
启动成功!!
6.运行grep实例
- 在hdfs中创建input文件夹并将容器本地的文件上传到input中
bin/hdfs dfs -mkdir /user/root/input
bin/hdfs dfs -put ./etc/hadoop/*.xml /user/root/input
- 验证文件是否上传成功
bin/hdfs dfs -ls input
- 运行grep实例
./bin/hadoop jar ./share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar grep /user/hadoop/input output 'dfs[a-z.]+'
- 在hdfs上的output目录下查看到运行结果
./bin/hdfs dfs -cat output/*
- 关闭hadoop
sbin/stop-all.sh
四、遇到的问题及解决方法
问题1.在实验一nginx反向代理Tomcat中,浏览器连接不到网页
解决方法:找了半天,才发现是nginx没有配置好,端口没有映射好。
问题2.在实验三中第二次保存镜像时,虚拟机报错自己暂停,无法使用
解决方法:还好做之前有clone过虚拟机,不然凉凉啊。查看报错,发现是虚拟机存放的本地磁盘空间不足保存十几个G的镜像,所以一切又得重头开始,哭了。
问题3.当再次启动hadoop时,没有jps查看,导致hdfs上传文件时报错
解决方法:查看报错显示0个DataNode,所以又重新jps三个节点,才发现两个slave节点没有DataNode。查找博客,才知道原来我又重新格式化了一次namenode导致DataNode的ID不符,所以需要找到配置文件hdfs-site.xml中data存放目录,然后关闭hadoop并在三个节点中删除data文件夹下的所有内容,重新format,解决:)
五、实验心得
这次实验用时很久,不过也让我又一次体会到了docker的强大,尤其是在hadoop实验中。因为之前在大数据实验课中有在虚拟机上搭建hadoop完全分布式配置,当时运行hadoop实例电脑卡死,发现对性能要求很高。但是这次不一样,在docker容器上运行更加方便快捷,并能可以搭建多个节点的hadoop集群,真的无比感叹。对于Javaweb项目,真的是之前没有接触过,时间有点紧张,所以借用了教程中的项目。同时也了解到nginx反向代理的原理和实现负载均衡。