第4次实践作业
(1)使用Docker-compose实现Tomcat+Nginx负载均衡
1.理解nginx反向代理原理;
举例一下,目前如日中天的某宝网站,每天同时连接到网站的访问人数已经爆表,单个服务器远远不能满足人民日益增长的购买欲望了,此时就出现了一个大家耳熟能详的名词:分布式部署;也就是通过部署多台服务器来解决访问人数限制的问题;某宝网站中大部分功能也是直接使用nginx进行反向代理实现的,并且通过封装nginx和其他的组件之后起了个高大上的名字:Tengine,那么反向代理具体是通过什么样的方式实现的分布式的集群操作呢,我们先看一个示意图:
通过上述的图解大家就可以看清楚了,多个客户端给服务器发送的请求,nginx服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。此时~请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,nginx扮演的就是一个反向代理角色。简而言之,反向代理就是主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。
项目场景
通常情况下,我们在实际项目操作时,正向代理和反向代理很有可能会存在在一个应用场景中,正向代理代理客户端的请求去访问目标服务器,目标服务器是一个反向单利服务器,反向代理了多台真实的业务处理服务器。具体的拓扑图如下:
2.nginx代理tomcat集群,代理2个以上tomcat;
2.1项目分支如下:
文档如下:
docker-compose.yml
default.conf
index.html
三个文件夹里头内容为tomcat1、tomcat2、tomcat3
2.2运行yml文件
2.3访问浏览器localhost
刷新后轮番出现以下界面:
神奇!
2.4查看新创建的容器状态
3.了解nginx的负载均衡策略,并至少实现nginx的2种负载均衡策略;
3.1轮询方式
3.1.1新建临时文档temp.py用于测试
temp.py
import requests
url="http://localhost"
for i in range(0,10):
reponse=requests.get(url)
print(reponse.text)
测试
3.2权重方式
3.2.1修改default.conf文档用于测试
upstream tomcats {
server ex4_tomcat01:8080 weight=1; #weight参数用于指定轮询几率,weight的数值与访问比率成正比
server ex4_tomcat02:8080 weight=1; #设置比重为1:1:8
server ex4_tomcat03:8080 weight=8;
}
3.2.2重启nginx容器
3.2.3新建临时文档temp1.py用于测试
import requests
url='http://localhost'
count={}
for i in range(0,100):
response=requests.get(url)
if response.text in count:
count[response.text]+=1;
else:
count[response.text]=1
print(count)
测试
3.3基于客户端IP的分配方式
- weight 权重过大代表承担的负载就越大
- max_fails 失败超过指定次数会暂停或请求转往其它服务器
- fail_timeout 失败超过指定次数后暂停时间
- 每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
3.3.1修改default.conf文档
upstream tomcats {
ip_hash; #保证每个访客固定访问一个后端服务器
server ex4_tomcat1:8080 weight=3;
server ex4_tomcat2:8080;
server ex4_tomcat3:8080 max_fails=3 fail_timeout=20s;
}
通过temp1.py测试(记得要重启容器)
(2) 使用Docker-compose部署javaweb运行环境
参考博客:使用docker-compose部署Javaweb项目
1.建立文件结构
default.conf
upstream tomcats {
server tomcat01:8080;
server tomcat02:8080;
}
server {
listen 2020;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
proxy_pass http://tomcats;
}
docker-compose
version: "3" #版本
services: #服务节点
tomcat01: #tomcat 服务
image: tomcat #镜像
hostname: hostname #容器的主机名
container_name: tomcat01 #容器名
ports: #端口
- "5050:8080"
volumes: #数据卷
- "./webapps:/usr/local/tomcat/webapps"
- ./wait-for-it.sh:/wait-for-it.sh
networks: #网络设置静态IP
webnet:
ipv4_address: 15.22.0.15
tomcat02: #tomcat 服务
image: tomcat #镜像
hostname: hostname #容器的主机名
container_name: tomcat02 #容器名
ports: #端口
- "5055:8080"
volumes: #数据卷
- "./webapps:/usr/local/tomcat/webapps"
- ./wait-for-it.sh:/wait-for-it.sh
networks: #网络设置静态IP
webnet:
ipv4_address: 15.22.0.16
mymysql: #mymysql服务
build: . #通过MySQL的Dockerfile文件构建MySQL
image: mymysql:test
container_name: mymysql
ports:
- "3309:3306"
#红色的外部访问端口不修改的情况下,要把Linux的MySQL服务停掉
#service mysql stop
#反之,将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:
- 8080:8080
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
tty: true
stdin_open: true
depends_on:
- tomcat00
- tomcat01
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;
Dockerfile
# 这个是构建MySQL的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
#复制gropshop.sql到/usr/local
COPY grogshop.sql /usr/local/
#把要执行的shell文件放到/docker-entrypoint-initdb.d/目录下,容器会自动执行这个shell
COPY docker-entrypoint.sh $AUTO_RUN_DIR/
#给执行文件增加可执行权限
RUN chmod a+x $AUTO_RUN_DIR/docker-entrypoint.sh
# 设置容器启动时执行的命令
#CMD ["sh", "/docker-entrypoint-initdb.d/import.sh"]
2.部署Javaweb程序
2.1修改连接数据库的IP
vim ~/ex4_2/webapps/ssmgrogshop_war/WEB-INF/classes/jdbc.properties
2.2启动容器
docker-compose up -d
2.3浏览器访问前端页面
实现负载均衡
http://10.0.2.15:5050/ssmgrogshop_war
http://10.0.2.15:5050/ssmgrogshop_war
2.3数据库操作
(3)使用Docker搭建大数据集群环境
直接用机器搭建Hadoop集群,会因为不同机器配置等的差异,遇到各种各样的问题;也可以尝试用多个虚拟机搭建,但是这样对计算机的性能要求比较高,通常无法负载足够的节点数;使用Docker搭建Hadoop集群,将Hadoop集群运行在Docker容器中,使Hadoop开发者能够快速便捷地在本机搭建多节点的Hadoop集群。
1.初始化系统
1.1在Docker安装Ubuntu系统
docker pull ubuntu
个人文件下创建一个目录并运行Ubuntu系统
cd ~
mkdir build
1.2Ubuntu系统初始化
更新系统软件源
16.04系统所需的源(这里使用的是阿里源)
apt-get update
安装vim、sshd
apt-get install vim # 用于修改配置文件
apt-get install ssh # 分布式hadoop通过ssh连接
/etc/init.d/ssh start # 开启sshd服务器
vim ~/.bashrc # 在文件末尾添加/etc/init.d/ssh start,实现ssd开机自启
细节忽略
配置sshd
ssh-keygen -t rsa #一直按回车键即可
cat id_dsa.pub >> authorized_keys
至此实现免密验证
1.3安装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生效
保存镜像文件
docker ps
docker commit 91f51e3bb091 ubuntu/jdk8
2.Hadoop安装与配置
2.1安装Hadoop
开启保存的那份镜像ubuntu/jdk8
sudo docker commit 容器id ubuntu/jdk8 #jkd8版本的ubuntu
sudo docker run -it -v /home/caifeng/build:/root/build --name ubuntu-jdk8 ubuntu:jdk8#这一步一定别漏,我漏了,后面会出问题
安装并验证Hadoop
docker cp ./build/hadoop-3.1.3.tar.gz 容器ID:/root/build
cd /root/build
tar -zxvf hadoop-3.1.3.tar.gz -C /usr/local
vim ~/.bashrc #添加以下三行
export HADOOP_HOME=/usr/local/hadoop-3.1.3
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$JAVA_HOME/bin
source ~/.bashrc # 使.bashrc生效
hadoop version
2.2配置Hadoop
进入配置目录
cd /usr/local/hadoop-3.1.3/etc/hadoop
hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ # 在任意位置添加
core-site.xml
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop-3.1.3/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</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>
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
</configuration>
mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop-3.1.3</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop-3.1.3</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop-3.1.3</value>
</property>
</configuration>
yarn-site.xml
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>Master</value>
</property>
<!--虚拟内存和物理内存比,不加这个模块程序可能跑不起来-->
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>2.5</value>
</property>
</configuration>
进入脚本目录
cd /usr/local/hadoop-3.1.3/sbin
对于start-dfs.sh和stop-dfs.sh文件,添加下列参数
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
2.2保存镜像
另开一个终端运行以下指令:
docker commit 容器ID ubuntu/hadoop
2.3另开三个终端运行主机
# 第一个终端
docker run -it -h master --name master ubuntu/hadoop
# 第二个终端
docker run -it -h slave01 --name slave01 ubuntu/hadoop
# 第三个终端
docker run -it -h slave02 --name slave02 ubuntu/hadoop
运行vim /etc/hosts,根据各自ip修改为如下形式
172.17.0.4 master
172.17.0.5 slave01
172.17.0.6 slave02
2.4在master终端做结点测试
从master连接到slave各个结点
ssh slave01
ssh slave02
exit
2.5在master主机上修改workers
vim /usr/local/hadoop-3.1.3/etc/hadoop/workers
将默认的localhost替换为
slave01
slave02
3.测试Hadoop并运行程序实例
3.1测试Hadoop集群
打开master终端
cd /usr/local/hadoop-3.1.3
bin/hdfs namenode -format #首次启动Hadoop需要格式化
sbin/start-all.sh #启动所有服务
jps #分别查看三个终端
3.2运行Hadoop实例程序
bin/hdfs dfs -mkdir -p /user/hadoop/input
bin/hdfs dfs -put ./etc/hadoop/*.xml /user/hadoop/input
bin/hdfs dfs -ls /user/hadoop/input
执行实例
爆卡预警
bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar grep /user/hadoop/input output 'dfs[a-z.]+'
查看运行结果
bin/hdfs dfs -cat output/*
(4)遇到的问题及解决方案
1.Ubuntu 16.04安全重启后处于emergency mode状态无法进入图形界面问题
- 登陆root,输入用户名和密码
- vim /etc/fstab ,检查磁盘挂载信息
- 注释掉自己增加的内容,如果确定不在使用可以删除
- 重启ok
待续
(5)小结
这次实验的量真的太大了,我大概边写博客边做花了30多个小时。真的这次实践有太多感想了。
前两个实验还好,了解了nginx的负载均衡策略,其实还挺有意思的,轮询和权重都不失为一种好方法,在nginx部署项目的时候运用一下负载均衡也是极佳的选择,这是真实能够给之后的项目提供帮助的负载均衡,至于基于客户端IP的分配方式其实挺神奇的,我至今还是对他怀着惊叹的态度。然后就是第三次实验了,第三次是使用Docker搭建大数据集群环境。不得不说第三个实验的容错率太低了,我硬生生错了6次,基本上都是从头来过,尤其到最后一次直接系统崩溃了,安全重启后又进入了emergency mode..我检查了一波磁盘挂载信息,然后发现是之前有加入了一些东西,注释过后才总算可以启动,我感觉我在玩火,至此之后我的虚拟机ubantu系统启动都需要很长的时间。
但是总体来说,还是学会了许多东西,最后看到结果正确的时候异常兴奋,这次实践也算是在坑底做了一次跳跳蛙。