系统综合实践 第4次实践作业


奉劝大家在实验前拍摄一个镜像,在实验过程中完成某一步关键步骤后也可以拍一个镜像,毕竟你不知道你能把你的虚拟机搞成什么样

(一)使用Docker-compose实现Tomcat+Nginx负载均衡

要求:
理解nginx反向代理原理;
nginx代理tomcat集群,代理2个以上tomcat;
了解nginx的负载均衡策略,并至少实现nginx的2种负载均衡策略;

1)nginx反向代理原理

  • 正向代理
    正向代理服务器位于客户端和服务器之间,为了向服务器获取数据,客户端要向代理服务器发送一个请求,并指定目标服务器,代理服务器将目标服务器返回的数据转交给客户端。
  • 反向代理
    反向代理和正向代理的区别就是:正向代理代理客户端,反向代理代理服务器。
    反向代理,其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址。

2)tomcat负载均衡

  • Nginx负载均衡的概念
    在服务器集群中,Nginx起到一个代理服务器的角色(即反向代理),为了避免单独一个服务器压力过大,将来自用户的请求转发给不同的服务器。
  • Nginx负载均衡策略
    • 轮询(默认)
      策略:在upstream模块内写上一组动态服务器组,再指定访问反向代理到服务器列表。客户端每个请求会按时间顺序逐一分配到不同的后端服务器
      适用:适合服务器配置相当,无状态且短平快的服务使用
    • weight
      策略:weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比
      适用:合服务器的硬件配置差别比较大的情况
    • ip_hash
      策略:指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
      适用:此策略适合有状态服务,比如session;当有服务器需要剔除,必须手动down掉。
    • least_conn
      策略:把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
      适用:请求处理时间长短不一造成服务器过载的情况
    • fair(需第三方插件)
      策略:按照服务器端的响应时间来分配请求,响应时间短的优先分配。
    • url_hash(需第三方插件)
      策略:同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。 

3)nginx代理tomcat集群

1.文件配置

  • 所需镜像
    tomcat、nginx

  • 目录结构

  • docker-compose.yml

version: "3"
services:
    #nginx服务
    nginx:
        image: nginx  #镜像名
        container_name: nginxc  #容器名
        build: ./nginx
        ports:
            - "80:2208"     #暴露端口
        volumes:          
            - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - tomcat01
            - tomcat02
            - tomcat03
    #tomcat服务
    tomcat01:
       image: tomcat
       container_name: tc01
       volumes: 
         - ./tomcat1:/usr/local/tomcat/webapps/ROOT
    tomcat02:
       image: tomcat
       container_name: tc02
       volumes: 
         - ./tomcat2:/usr/local/tomcat/webapps/ROOT
    tomcat03:
       image: tomcat
       container_name: tc03
       volumes: 
         - ./tomcat3:/usr/local/tomcat/webapps/ROOT

  • nginx配置文件default.conf
server {
    listen       2208;  #修改映射端口
    server_name  localhost;

    location / {
     proxy_pass http://tomcats;
    }
upstream tomcats {
        server tc01:8080;  #tc01、tc02、tc03对应docker-compose.yml里的container_name
        server tc02:8080;  
        server tc03:8080;  
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

运行docker-compose

sudo docker-compose up -d --build

2.nginx负载均衡策略实现

  • Python文件测试
import requests

url='http://localhost'
for i in range(0,6):
    response=requests.get(url)
    print(response.text)
  • 轮询策略(默认)

  • weight策略
    修改default.conf如下

upstream tomcats{
        server tc01:8080 weight=2;  #tc01、tc02、tc03对应docker-compose.yml里的container_name
        server tc02:8080 weight=1;  
        server tc03:8080 weight=1;  
    }

需要重启nginx容器docker restart 容器名

(二) 使用Docker-compose部署javaweb运行环境

要求:
分别构建tomcat、数据库等镜像服务;
成功部署Javaweb程序,包含简单的数据库操作;
为上述环境添加nginx反向代理服务,实现负载均衡。

参考资料:使用docker-compose部署Javaweb项目

1)文件配置

  • 需要拉取的镜像:nginx、docker-compose、tomcat、mysql

  • 文件目录
    .
    ├── default.conf
    ├── docker-compose.yml
    ├── docker-entrypoint.sh
    ├── Dockerfile
    ├── grogshop.sql
    ├── wait-for-it.sh [error opening dir]
    └── webapps
    ├── docs
    ├── examples
    ├── host-manager
    ├── manager
    ├── ROOT
    ├── ssmgrogshop_war
    └── ssmgrogshop_war.war

  • 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"]
    
    • docker-entrypoint.sh
    #!/bin/bash
    mysql -uroot -p123456 << EOF
    source /usr/local/grogshop.sql;
    
  • nginx

    • default.conf
        upstream tomcat123 {
        server tomcatc:8080;
    }
    server {
        listen 8080;
        server_name localhost;
    
        location / {
        proxy_pass http://tomcat123;
        }
    }
    
  • docker-compose.yml

    version: "3"   
    services:     
    tomcat:     
        image: tomcat    #镜像
        hostname: hostname       #容器的主机名
        container_name: tomcatc   #容器名
        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
    
    mymysql:  
        build: .   #通过MySQL的Dockerfile文件构建MySQL
        image: mymysql:test
        container_name: mysqlc
        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
        networks:
        webnet:
            ipv4_address: 15.22.0.7
    
    networks:   #网络设置
    webnet:
    driver: bridge  #网桥模式
    ipam:
        config:
        - subnet: 15.22.0.0/24   #子网
    
  • jdbc.properties
    修改/webapps/ssmgrogshop_war/WEB-INF/classes下的jdbc.properties
    使用ipconfig查看本机ip修改

2)执行javaweb实例

  • 构建容器
sudo docker-compose up -d --build
  • 访问网页
    http://127.0.0.1:8080/ssmgrogshop_warhttp://localhost:8080/ssmgrogshop_war密码为sa、123

  • 增删查改操作
    以增为例

(三)使用Docker搭建大数据集群环境

直接用机器搭建Hadoop集群,会因为不同机器配置等的差异,遇到各种各样的问题;也可以尝试用多个虚拟机搭建,但是这样对计算机的性能要求比较高,通常无法负载足够的节点数;使用Docker搭建Hadoop集群,将Hadoop集群运行在Docker容器中,使Hadoop开发者能够快速便捷地在本机搭建多节点的Hadoop集群。
要求:
完成hadoop分布式集群环境配置,至少包含三个节点(一个master,两个slave);
成功运行hadoop 自带的测试实例。

1)目录结构

2)镜像拉取

  • 拉取Ubuntu镜像
docker pull ubuntu
  • 启动容器
sudo docker build -t ubuntu:18.04 .
sudo docker run -it --name ubuntu ubuntu:18.04

3)Ubuntu系统初始化

apt-get update#更新系统软件源
apt-get install vim#安装vim
apt-get install ssh#安装sshd
/etc/init.d/ssh start#开启sshd服务器

设置登录Ubuntu系统时,自启动sshd服务

vim ~/.bashrc
/etc/init.d/ssh start#添加在文件最后一行

设置sshd免密登陆

ssh-keygen -t rsa #一直按回车键即可
cd ~/.ssh  
cat id_dsa.pub >> authorized_keys
  • 安装配置jdk
    安装java8
apt-get install openjdk-8-jdk

配置环境变量

vim ~/.bashrc#在文件尾部添加以下两行
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
export PATH=$PATH:$JAVA_HOME/bin

输入source ~/.bashrc命令使之生效
输入java -version查看java版本,查看是否安装成功

  • 镜像文件保存

在Docker内部的容器做的修改是不会自动保存到镜像的,也就是说,把容器关闭,然后重新开启容器,则之前的设置会全部消失,因此需要保存当前的配置。为了达到复用配置信息,可以在每个步骤完成之后,都保存成一个新的镜像,然后开启保存的新镜像。

sudo docker ps # 查看容器ID
docker commit 容器ID ubuntu/jdk8 # 存为镜像

docker images命令查看一下

  • 安装hadoop

将hadoop安装包放在共享目录下,在Docker内部Ubuntu系统的/root/build目录即可获取到Hadoop安装文件;在Docker内部的Ubuntu系统安装Hadoop和本地安装一样,

docker run -it -v /home/yeye/docker/hadoop/build:/root/build --name ubuntu-jdk8 ubuntu/jdk8

安装Hadoop

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使配置生效
安装验证

hadoop version 

4)Hadoop集群配置

进入hadoop配置文件夹,路径为/usr/local/hadoop-3.1.3/etc/hadoop
配置如下几个文件

  • hadoop_env.sh
vim 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.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>
  • 修改脚本
    进入脚本目录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
  • 保存镜像
docker commit 容器ID ubuntu/hadoop
  • 开启容器运行ubuntu/hadoop镜像
    开启三个终端
# 第一个终端
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


三个终端分别打开/etc/hosts,修改节点ip如下

172.17.0.4      master
172.17.0.5      slave01
172.17.0.6      slave02

在master节点测试是否可以连上slave01和slave02

ssh slave01
ssh slave02

exit退出连接

在master节点上执行如下操作配置

cd /usr/local/hadoop
bin/hdfs namenode -format#
sbin/start-all.sh

在slave01、slave02上键入jsp查看

5)Hadoop实例运行

bin/hdfs dfs -mkdir -p /user/hadoop/input #在hdfs上创建input目录
bin/hdfs dfs -put ./etc/hadoop/*.xml /user/hadoop/input #将/usr/local/hadoop/etc/hadoop/目录下的所有文件拷贝到hdfs上的目录
bin/hdfs dfs -ls /user/hadoop/input #通过ls命令查看下是否正确将文件上传到hdfs下

实例运行

./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/*

(四)遇到问题及解决

  • 1.安装ssh时显示no more space to left

查看磁盘空间df -f
发现目录满了
进入满目录du -sh 命令查找出空间占用最大的文件
最后发现是yum/package爆满
删除了packages,yum clean packages
然后拉取了3天都失败的tomcat镜像都拉取成功了,眼泪掉下来
但这个问题没有得到很大的改善,原因出在我看网上教程的问题多数为log文件太大,但我不是这个问题,其他文件不知道什么可以删,所以删除后实际上是从100%到86%。

  • 2.active endpoint

参考:docker 解决network has active endpoints
问题如图,是在实验一关闭容器的时候发生的

可以使用指令docker network disconnect -f {network} {endpoint-name}解决
network

endpoint-name

最终

docker network disconnect -f javaweb_webnet tomcatc
  • 3.无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)

参考:解决‘E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用) ’ 问题

  • 容器闪退问题
    在进行实验1的时候,如果是用dockerfile构造的nginx会闪退,我一开始没有注意容器状态,只是发现容器会发生问题2这样的毛病,但是当我解决后重启容器问题依然存在。后来我发现前面交作业的同学都没有使用dockerfile构建nginx,按照他们的方法问题就解决了。

(五)实验感想

实验时间(报告与实验同步):实验1:16小时(因为内存不足引发了很多问题,加上最后还无法从window复制文件,在网上找了方法没有解决就干脆换ubuntu从头开始,再加上ubuntu之前没有做过实验要重新配置环境);实验2:5小时;实验3:7小时
这次实验十分坎坷,在经过10小时centos一步执行10个错之后,我转战了ubuntu,并且每执行到一个关键点就保存一个镜像。大大小小的问题出了很多,一开始面对这么多问题心情很烦躁,

后来已经可以心如止水的百度解决问题了,感觉这次实验比起实验本身好像更考验我的耐心。再一次次的推翻重做中,感觉对docker操作也更加熟练了,后面遇到的问题前面记录过也可以更快解决。

由于是做过大数据实验的,所以看到hadoop格外亲切,说一下对比用虚拟机直接实现hadoop全分布式实验和使用docker实现的感想。

  • 首先是网络配置,直接使用虚拟机配置hadoop全分布式环境需要进行一系列网络配置,这点上docker比较亲切,过程更简易
  • 其次是docker不需要克隆虚拟机去实现多节点,如果节点更多的情况下,克隆机的数量肯定会过于臃肿
  • 但是docker的镜像拉取的确有点耗时间,特别是有时候会遇到几次都拉取不下来的情况(即使是在有加速器的情况下)。
posted @ 2020-05-18 22:14  叶叶叶子  阅读(319)  评论(0编辑  收藏  举报