第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.shstop-dfs.sh文件,添加下列参数

HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root

对于start-yarn.shstop-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系统启动都需要很长的时间。
  但是总体来说,还是学会了许多东西,最后看到结果正确的时候异常兴奋,这次实践也算是在坑底做了一次跳跳蛙。

posted @ 2020-05-17 21:54  一天能饿好多次  阅读(182)  评论(0编辑  收藏  举报