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

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

概念

正向代理:客户端想要访问一个服务器,但是它可能无法直接访问这台服务器,这时候这可找一台可以访问目标服务器的另外一台服务器,而这台服务器就被当做是代理人的角色 ,称之为代理服务器,于是客户端把请求发给代理服务器,由代理服务器获得目标服务器的数据并返回给客户端。客户端是清楚目标服务器的地址的,而目标服务器是不清楚来自客户端,它只知道来自哪个代理服务器,所以正向代理可以屏蔽或隐藏客户端的信息。
反向代理:从上面的正向代理,你会大概知道代理服务器是为客户端作代理人,它是站在客户端这边的。其实反向代理就是代理服务器为服务器作代理人,站在服务器这边,它就是对外屏蔽了服务器的信息,常用的场景就是多台服务器分布式部署,像一些大的网站,由于访问人数很多,就需要多台服务器来解决人数多的问题,这时这些服务器就由一个反向代理服务器来代理,客户端发来请求,先由反向代理服务器,然后按一定的规则分发到明确的服务器,而客户端不知道是哪台服务器。常常用nginx来作反向代理。
Nginx的负载均衡:
负载:就是Nginx接受请求

均衡:Nginx将收到的请求按照一定的规则分发到不同的服务器进行处理

nginx代理tomcat集群,代理2个以上tomcat;

创建项目的目录结构如下:

即代理三个tomcat

编写nginx的默认配置文件

通过upstream tomcats配置后面负载均衡的策略选择
先使用的是轮询算法(默认),配置内容如下

upstream tomcats {
    server c_tc1:8080; 
    server c_tc2:8080; 
    server c_tc3:8080; 
}

server {
    listen 2419;
    server_name localhost;

    location / {
        proxy_pass http://tomcats; # 请求转向tomcats
    }
}

docker-compose.yml

version: "3.8"
services:
    nginx:
        image: nginx
        container_name: c_ngx
        ports:
            - 80:2419
        volumes:
            - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
        depends_on:
            - tomcat01
            - tomcat02
            - tomcat03

    tomcat01:
        image: tomcat
        container_name: c_tc1
        volumes:
            - ./tomcat01:/usr/local/tomcat/webapps/ROOT # 挂载web目录

    tomcat02:
        image: tomcat
        container_name: c_tc2
        volumes:
            - ./tomcat02:/usr/local/tomcat/webapps/ROOT

    tomcat03:
        image: tomcat
        container_name: c_tc3
        volumes:
            - ./tomcat03:/usr/local/tomcat/webapps/ROOT

index.html

I am the host 03/02/01

了解nginx的负载均衡策略,并至少实现nginx的2种负载均衡策略

常用的负载均衡策略有

  • 轮询(默认)
  • 指定权重
  • IP绑定 ip_hash
  • fair(第三方)
  • url_hash(第三方)

这里选择测试默认的轮询算法和指定权重算法

轮询算法

nginx的配置文件上面已经给出

cd homework4/
sudo docker-compose up -d --build

成功运行yml文件,由于之前已经创建完成,结果如下

于是可以通过浏览器访问localhost发现是可以成功访问之前设置的index.html界面的,并且刷新界面结果会轮询。这里为了直观看出负载均衡的策略,直接用创建py文件测试

test_lx.py
import requests
url = 'http://localhost'
for i in range(1,10):
    response=requests.get(url)
    print(response.text)

得到结果如下,可发现是三个tomcat服务器是轮流执行的

权重算法

更改default.conf文件

upstream tomcats {
    server c_tc1:8080 weight=1;   //weight后面的数字表示权重
    server c_tc2:8080 weight=3;
    server c_tc3:8080 weight=5;
}

server {
    listen 2419;
    server_name localhost;

    location / {
        proxy_pass http://tomcats; # 请求转向tomcats
    }
}

重新sudo docker-compose up -d --build
直接使用py代码测试

test.qz.py
import requests
url = 'http://localhost'
count={'I am the host 03':0,'I am the host 01':0,'I am the host 02':0}
for i in range(0,90):
    response=requests.get(url)
    if  'I am the host 03' in response.text:
        count['I am the host 03'] += 1
    if  'I am the host 02' in response.text:
        count['I am the host 02'] += 1
    if  'I am the host 01' in response.text:
        count['I am the host 01'] += 1
    print(response.text)
print(count)

显然三种结果的出现比例和权重是一致的

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

  • 分别构建tomcat、数据库等镜像服务;
  • 成功部署Javaweb程序,包含简单的数据库操作;
  • 为上述环境添加nginx反向代理服务,实现负载均衡。
    创建项目文件,文件结构如图(javaweb程序老师给的参考博客)


    其中war包放在webapp文件目录下

文件配置

docker-compose.yml

version: "3"   
services:    
  tomcat00:     
    image: tomcat    
    hostname: hostname       
    container_name: tomcat00   
    ports:      
     - "5050:8080"          #后面访问网页的时候要选择对应的端口号5050
    volumes:  #数据卷
     - "./webapps:/usr/local/tomcat/webapps"
     - ./wait-for-it.sh:/wait-for-it.sh
    networks:   #网络设置静态IP
      webnet:
        ipv4_address: 15.22.0.15
  mymysql:  #mymysql服务
    build: .   #通过MySQL的Dockerfile文件构建MySQL
    image: mymysql:test
    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:
          - 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   #子网

default.conf

upstream tomcats {
    server tomcat00:5050; 

}

server {
    listen 8080
    server_name localhost;

    location / {
        proxy_pass http://tomcat123;
        proxy_set_header   Host    $host; 
        proxy_set_header   X-Real-IP   $remote_addr; 
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

    }
}


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"]

修改连接数据库的IP

通过ip config -a查看本机ip地址,inet对应的即为结果

修改jdbc.properties对应的ip地址和之前设置的对应端口号

启动容器

docker-compose up -d --build

数据库操作

访问网页,登陆

http://127.0.0.1:5050/ssmgrogshop_war

对应的可以进行数据库操作

修改nginx配置文件,反向代理tomcat

upstream tomcats {
    server tomcat00:5050; 
    server tomcat00:5051; 
    server tomcat00:5052; 
     
}

修改yml文件,增加

tomcat01:     
    image: tomcat    
    hostname: hostname       
    container_name: tomcat01   
    ports:      
     - "5051:8080"          #后面访问网页的时候要选择对应的端口号5050
    volumes:  #数据卷
     - "./webapps:/usr/local/tomcat/webapps"
     - ./wait-for-it.sh:/wait-for-it.sh
    networks:   #网络设置静态IP
      webnet:
        ipv4_address: 15.22.0.16
  tomcat02:     
    image: tomcat    
    hostname: hostname       
    container_name: tomcat02   
    ports:      
     - "5052:8080"          #后面访问网页的时候要选择对应的端口号5050
    volumes:  #数据卷
     - "./webapps:/usr/local/tomcat/webapps"
     - ./wait-for-it.sh:/wait-for-it.sh
    networks:   #网络设置静态IP
      webnet:
        ipv4_address: 15.22.0.17
  nginx:
    depends_on:
     - tomcat00
     - tomcat01
     - tomcat02   

重新运行容器,可以发现在三个端口下都可以访问nginx

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

环境搭建

  • 拉取ubantu镜像
sudo su
docker pull ubantu
  • 创建dockerfile文件
FROM ubuntu
maintainer Yaobink
  • 进入ubantu容器
docker build -t ubuntu .
docker run -it --name ubuntu ubuntu

Ubuntu系统初始化

  • 更新系统软件源
    更新系统源命令如下:
apt-get update
  • 安装vim
apt-get install vim
  • 安装sshd
    接着安装sshd,因为在开启分布式Hadoop时,需要用到ssh连接slave:
apt-get install ssh

然后运行如下脚本即可开启sshd服务器:

/etc/init.d/ssh start

但是这样的话,就需要每次在开启镜像时,都需要手动开启sshd服务,因此我们把这启动命令写进~/.bashrc文件,这样我们每次登录Ubuntu系统时,都能自动启动sshd服务;

vim ~/.bashrc

在该文件中最后一行添加如下内容:

/etc/init.d/ssh start

配置sshd
安装好sshd之后,我们需要配置ssh无密码连接本地sshd服务,如下命令:

ssh-keygen -t rsa #一直按回车键即可
cat id_rsa.pub >> authorized_keys

执行完上述命令之后,即可无密码访问本地sshd服务;

安装JDK

  • 根据官方文档,最好下载java8
apt install openjdk-8-jdk
  • 安装好后需要配置环境变量
vim ~/.bashrc  #打开配置文件
#在最后添加使~/.bashrc生效
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
export PATH=$PATH:$JAVA_HOME/bin
source ~/.bashrc  

存档

docker commit 09ab62943c02  ubuntu/jdk8 
docker run -it -v /home/y/hw4_3/build:/root/build --name ubuntu-jdk8 ubuntu/jdk8

安装Hadoop

首先下载好Hadoop,这里下载的是3.2.1的版本,移入ubuntu桌面
然后通过cp复制到挂载的文件目录下,解压文件,并验证安装

sudo cp /home/y/桌面/hadoop-3.2.1.tar.gz /home/y/hw4_3/build
tar -zxvf hadoop-3.2.1.tar.gz -C /usr/local
cd /usr/local/hadoop-3.2.1
./bin/hadoop version

配置Hadoop集群

  • 进入配置文件存放目录:
cd /usr/local/hadoop-3.2.1/etc/hadoop
  • 修改环境变量
vim hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ 
  • 修改core-site.xml
vim core-site.xml

添加:

<configuration>
      <property>
          <name>hadoop.tmp.dir</name>
          <value>file:/usr/local/hadoop/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
vim hdfs-site.xml

添加:

<configuration>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/usr/local/hadoop/namenode_dir</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/usr/local/hadoop/datanode_dir</value>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
</configuration>
  • 修改mapred-site.xml
vim 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.2.1</value>
    </property>
    <property>
        <name>mapreduce.map.env</name>
        <value>HADOOP_MAPRED_HOME=/usr/local/hadoop-3.2.1</value>
    </property>
    <property>
        <name>mapreduce.reduce.env</name>
        <value>HADOOP_MAPRED_HOME=/usr/local/hadoop-3.2.1</value>
    </property>
</configuration>
  • 修改yarn-site.xml
vim yarn-site.xml

添加:

<configuration>
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>master</value>
    </property>
</configuration>

修改脚本

  • 进入脚本文件存放目录:
cd /usr/local/hadoop-3.2.1/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
  • 存档
sudo docker commit ID ubuntu/hadoop

运行Hadoop集群

  • 在三个终端上开启三个容器运行ubuntu/hadoop镜像,分别表示Hadoop集群中的master,slave01和slave02;
# 第一个终端
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
vim /etc/hosts
#修改为
172.17.0.2      master
172.17.0.3      slave01
172.17.0.4      slave02

  • 测试ssh
    检测下是否master是否可以连上slave01和slave02(exit为退出)
ssh slave01
ssh slave02

  • 修改workers
vim /usr/local/hadoop-3.2.1/etc/hadoop/workers
# 将localhost替换成两个slave的主机名
slave01
slave02

启动集群

在master终端上运行如下命令

cd /usr/local/hadoop-3.2.1
bin/hdfs namenode -format # 格式化文件系统
sbin/start-dfs.sh # 开启NameNode和DataNode服务
bin/hdfs dfs -mkdir /user # 建立HDFS文件夹,也可以放到下面示例程序中进行
bin/hdfs dfs -mkdir /user/root
bin/hdfs dfs -mkdir input
bin/hdfs dfs -put etc/hadoop/*.xml input # 将xml复制到input下,作为示例程序输入
sbin/start-yarn.sh # 开启ResourceManager和NodeManager服务
jps # 查看服务状态

运行Hadoop示例程序

在master终端运行:

bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.1.jar grep input output 'dfs[a-z.]+' # 运行示例
bin/hdfs dfs -get output output # 获取输出结果
cat output/* # 查看输出结果
sbin/stop-all.sh # 停止所有服务

查看文件列表

在hdfs上的output目录下查看到运行结果:

./bin/hdfs dfs -cat output/*

得到的结果为

问题:

(1)
在配置ssh无密码连接本地sshd服务的时候出现了找不到目录的情况

后面查资料知道这个并不用先进入文件夹,而是可以直接执行自动创建这个目录

接着要先cd进入目录在执行cat id_rsa.pub >> authorized_keys,否则同样会找不到目标文件
(2)在运行Hadoop示例程序的时候ubuntu卡住了,所以我又重新创建了三个运行容器重新实验,然后在过程中发现,workers这个文件的修改应该得在master的目录下,否则后面在jps查看服务状态的过程种会出现错误,在slave01/02的jps命令下只能看到56Jps这样的情况,而NodeManager和DataNode都不存在。

用时

大概花了两个下午加一个晚上的时间,主要还是花在了第三个实验和第二个实验的javaweb的文件阅读上,最后无奈还是剽一下范例文档的war包。
感觉好多内容都是需要学习的,这种混杂的东西如果有一点不通就经常容易出现错误,就比如第三个实验有的时候某个步骤做错了就得重新开始,感觉特别麻烦,虽然前面有一些存档,不过毕竟还是有一些是无法保存的,但是万幸存档重来其实也节省了许多时间。

posted @ 2020-05-15 19:30  Yaobink  阅读(333)  评论(0编辑  收藏  举报