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


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

    • 理解nginx反向代理原理

      • 参考资料:nginx反向代理原理和配置讲解
      • 原理:以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
    • nginx代理tomcat集群,代理2个以上tomcat;

              upstream tomcats {
                   server tomcat1:7070;
                   server tomcat2:7071;
                   server tomcat3:7072;
              }
      
              server {
                  listen 2420;
                  server_name localhost;
      
                  location / {
                      proxy_pass http://tomcats; # 请求转向tomcats
                  }
              }
      
      • index.jsp
              <%@ page language="java" contentType="text/html; charset=utf-8"  import="java.net.InetAddress"  
                  pageEncoding="utf-8"%>  
              <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
              <html>  
              <head>  
              <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
              <title>Nginx+Tomcat负载均衡</title>  
              </head> 
              <body>  
                   <%  
                       InetAddress addr = InetAddress.getLocalHost();  
                       out.println("主机地址:"+addr.getHostAddress());  
                       out.println("主机名:"+addr.getHostName());   
                    %>  
              </body>  
              </html>
      
      • docker-compose.yml
              version: "3.8"
              services:
                nginx:
                  image: nginx
                  container_name: ex4ngx
                  ports:
                    - 80:2420
                  volumes:
                    - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
                  depends_on:
                    - tomcat01
                    - tomcat02
                    - tomcat03
      
                tomcat01:
                  hostname: tomcat01
                  image: tomcat
                  container_name: tomcat1
                  volumes:
                    - ./webapps:/usr/local/tomcat/webapps/ROOT # 挂载web目录
      
      
                tomcat02:
                  hostname: tomcat2
                  image: tomcat
                  container_name: tomcat2
                  volumes:
                    - ./webapps:/usr/local/tomcat/webapps/ROOT # 挂载web目录
      
      
                tomcat03:
                  hostname: tomcat03
                  image: tomcat
                  container_name: tomcat3
                  volumes:
                    - ./webapps:/usr/local/tomcat/webapps/ROOT # 挂载web目录
      
    • 了解nginx的负载均衡策略,并至少实现nginx的2种负载均衡策略;

      • 编写爬虫:
        import requests
        import re
        
        url = 'http://localhost/index.jsp'
        for i in range(0,6):
            res = requests.get(url)
            text = re.findall('tomcat[0-9]{2}',res.text,re.S)
            print(text)
        
      • 轮询策略:
        默认就是轮询算法
        运行爬虫:
      • 权重策略:
        修改default.conf

        运行爬虫:

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

    • 分别构建tomcat、数据库等镜像服务;

      • 参考资料:
        - SpringBoot项目的创建和jar、war方式的部署
        - Host is not allowed to connect to this MySQL server解决方法
      • 项目结构:
        .
        ├── docker-compose.yml
        ├── mysql
        │   ├── dockerfile
        │   ├── schema.sql
        │   └── setup.sh
        ├── nginx
        │   ├── default.conf
        │   └── Dockerfile
        └── tomcat
        ├── Dockerfile
        ├── ROOT [error opening dir]
        ├── ROOT.war
        在上一个实验的基础上,nginx的配置无需改动
      • mysql
        • dockerfile:

          from mysql:5.7
          #基础镜像
          maintainer lyh<471727250@qq.com>
          #维护者信息
          ENV MYSQL_ALLOW_EMPTY_PASSWORD no
          #不允许空密码登录
          ENV MYSQL_ROOT_PASSWORD=123456
          #root密码
          COPY setup.sh /mysql/setup.sh
          COPY schema.sql /mysql/schema.sql
          #所需文件
          CMD ["sh", "/mysql/setup.sh"]
          #启动命令
          
        • setup.sh

          #!/bin/bash
          set -e
          
          #查看mysql服务的状态,方便调试,这条语句可以删除
          echo `service mysql status` 
          echo '1.启动mysql....'
          #启动mysql
          service mysql start
          sleep 3
          echo `service mysql status`
          
          echo '2.开始导入数据....'
          #导入数据
          mysql < /mysql/schema.sql
          echo '3.导入数据完毕....'
          
          sleep 3
          echo `service mysql status`
          #sleep 3
          echo `service mysql status`
          echo `mysql容器启动完毕,且数据导入成功`     
          tail -f /dev/null
          
        • schema.sql

          -- 远程操作数据库必须,否则会报项目汇报错![](https://img2020.cnblogs.com/blog/1794540/202005/1794540-20200514173613577-1652002256.png)
          
          grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
          flush privileges; 
          -- 创建数据库
          create database ex4_db default character set utf8 collate utf8_general_ci;
          
          use ex4_db;
          
          -- 建表
          DROP TABLE IF EXISTS myuser;
          
          CREATE TABLE myuser (
           username varchar(20),
           phone varchar(255) DEFAULT "",
          PRIMARY KEY (username)
          ) 
          
      • docker-compose.yml
        version: "3.8"
        services:
          mysql:
            image: mysql:5.7
            container_name: ex4_mysql
            restart: always
            build:
              context: ./mysql
              dockerfile: Dockerfile
            ports:
                    - "3306:3306"
          
        
          nginx:
            image: nginx
            container_name: ex4_ngx
            ports:
              - "80:2020"
            build:
                    context: ./nginx
                    dockerfile: Dockerfile      #指定dockerfile文件
            volumes:
              - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
            depends_on:
              - tomcat01
              - tomcat02
              - tomcat03
        
          tomcat01:
            hostname: tomcat01
            image: tomcat
            container_name: tomcat1
            build:
                    context: ./tomcat
                    dockerfile: Dockerfile      #指定dockerfile文件
            depends_on:
              - mysql
            restart: always
            volumes:
              - ./tomcat:/usr/local/tomcat/webapps # 挂载web目录
        
          tomcat02:
            hostname: tomcat02
            image: tomcat
            container_name: tomcat2
            build:
                    context: ./tomcat
                    dockerfile: Dockerfile      #指定dockerfile文件
            depends_on:
              - mysql
            restart: always
            volumes:
              - ./tomcat:/usr/local/tomcat/webapps # 挂载web目录
        
          tomcat03:
            hostname: tomcat03
            image: tomcat
            container_name: tomcat3
            build:
                    context: ./tomcat
                    dockerfile: Dockerfile      #指定dockerfile文件
            depends_on:
              - mysql
            restart: always
            volumes:
              - ./tomcat:/usr/local/tomcat/webapps # 挂载web目录
        
    • javaweb项目:
      刚好最近在竞赛有用springboot构建项目,就用上了

      • 需要排除springboot自带的tomcat,教程:SpringBoot去除内嵌tomcat

      • 还有可能出现这种报错,不用管它,在pojo添加注解@Mapper即可

      • 一定一定一定要用plugin自动生成Mapper.xml代码!自己手写既繁琐又容易错,吃大亏了我,为啥知道了能自动生成我还要自己写

      • 记得修改application.yml文件
        url: jdbc:mysql://ex4_mysql:3306/ex4_db主机名修改为容器名

      • 功能大概如下

          ```
          @RestController
          @RequestMapping(value = "/ex4/")
          public class UserController {
          
              @Autowired
              UserMapper userMapper;
        
              @RequestMapping(value = "add")
              public String add(User user){
                  int result = userMapper.insert(user);
                  if (result == 0){
                      return "add error";
                  }
                  String str = user.getUsername() + " " + user.getPhone();
                  return "add successfully! User:[" + str + "]";
              }
        
              @RequestMapping(value = "update")
              public String update(User user){
                  int result = userMapper.updateByPrimaryKey(user);
                  if (result == 0){
                      return "update error";
                  }
                  String str = user.getUsername() + " " + user.getPhone();
                  return "update success fully! User:[" + str + "]";
              }
        
              @RequestMapping(value = "delete")
              public String delete(String username){
                  User user = userMapper.selectByPrimaryKey(username);
                  int result = userMapper.deleteByPrimaryKey(username);
                  if (result == 0){
                      return "delete error";
                  }
                  String str = user.getUsername() + " " + user.getPhone();
                  return "delete success fully! User:[" + str + "]";
              }
        
              @RequestMapping(value = "search")
              public String search(String username){
                  User user = userMapper.selectByPrimaryKey(username);
                  if (user == null){
                      return "user not exists";
                  }
                  String str = user.getUsername() + " " + user.getPhone();
                  return "search success fully! User:[" + str + "]";
              }
        
              @RequestMapping(value = "addr")
              String getPort(HttpServletRequest request) {
                  return "hello from " + request.getLocalAddr();
              }
          }
          ```
        
        • 部署项目
          - 将项目打包成.war,并修改文件名问ROOT.war,放置在tomcat挂载目录下
          - sudo docker-compose up -d --build构建
      • 测试接口:

        • 增:
        • 查:
        • 改:

          验证
        • 删:

          验证
    • 负载均衡

      • 爬虫:
        import requests
        
        url = 'http://localhost/ex4/addr'
        num = {}
        for i in range(0,100):
        	      res = requests.get(url)
            if res.text in num:
                  	num[res.text] += 1
            else:
                num[res.text] = 0
        print(num)
        
      • 运行爬虫:
        此时根据nginx配置,是权重策略


        负载均衡成功

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

    参考资料:

    - [使用Docker搭建Hadoop分布式集群](http://dblab.xmu.edu.cn/blog/1233/)
    

    项目结构:

    - dockerfile:
      ```
      FROM ubuntu
      #基础镜像
      maintainer lyh<471727250@qq.com>
      #维护者信息
      ```
    

    环境搭建:

    • ubuntu
      • 创建容器:
        使用sudo docker pull ubuntu拉取ubuntu镜像
        使用如下命令创建并进入ubuntu容器

        docker build -t ubuntu .
        docker run -it --name ubuntu ubuntu
        
      • ubuntu环境的初始化:

        apt-get update # 更新系统源
        apt-get install vim # 用于修改配置文件
        apt-get install ssh # 安装sshd,因为在开启分布式Hadoop时,需要用到ssh连接slave:
        /etc/init.d/ssh start # 运行脚本即可开启sshd服务器
        

        每次在开启镜像时,都需要手动开启sshd服务,因此我们把这启动命令写进~/.bashrc文件,这样我们每次登录Ubuntu系统时,都能自动启动sshd服务
        vim ~/.bashrc 并在最后一行添加/etc/init.d/ssh start

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

        cd ~/.ssh
        sh-keygen -t rsa #一直按回车键即可
        cat id_rsa.pub >> authorized_keys #参考文档好像拼写错了
        

        即可无密码访问本地sshd服务;

      • 为容器安装SDK
        由于版本依赖问题不能用默认的apt安装,否则会导致很多错误,根据官方文档,最好下载java8
        apt install openjdk-8-jdk

        安装好后需要配置环境变量
        vim ~/.bashrc打开配置文件
        在最后添加

        export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
        export PATH=$PATH:$JAVA_HOME/bin
        

        source ~/.bashrc 使~/.bashrc生效

      • 保存配置好的镜像文件

        docker ps # 查看当前容器id
        docker commit 容器ID ubuntu/ex4.3 # 存为镜像
        

      • 安装Hadoop
        docker run -it -v /home/hadoop/build:/root/build --name ubuntu-ex4.3 ubuntu/ex4.3 开启保存的那份镜像ubuntu/ex4.3

        Hadoop下载选择清华源

        下载完成后,用cp命令将文件复制入共享文件夹/home/hadoop/build
        sudo cp /home/ubuntu/Desktop/hadoop-3.2.1.tar.gz /home/hadoop/build
        此时,能在ubuntu镜像的/root/build下看见文件

        解压文件tar -zxvf hadoop-3.2.1.tar.gz -C /usr/local

        ./bin/hadoop version # 验证安装```
        ![](https://img2020.cnblogs.com/blog/1794540/202005/1794540-20200514210045030-75499166.png)
        
        
      • 配置Hadoop集群

        • 先进入配置文件存放目录:cd /usr/local/hadoop-3.2.1/etc/hadoop

        • 修改环境变量
          vim hadoop-env.sh

          export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ # 找不到教程说的export JAVA_HOME=${JAVA_HOME},好像直接加就行了
          
        • 修改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>
          
      • 存档
        sudo docker commit 8ff ubuntu/hadoopinstalled

      • 运行Hadoop集群

        • 在三个终端上开启三个容器运行ubuntu/hadoopinstalled镜像,分别表示Hadoop集群中的master,slave01和slave02;

          # 第一个终端
          sudo docker run -it -h master --name master ubuntu/hadoopinstalled
          # 第二个终端
          sudo docker run -it -h slave01 --name slave01 ubuntu/hadoopinstalled
          # 第三个终端
          sudo docker run -it -h slave02 --name slave02 ubuntu/hadoopinstalled
          
        • 配置master,slave01和slave02的地址信息
          分别打开/etc/hosts可以查看本机的ip和主机名信息,最后得到三个ip和主机地址信息如下:

          172.17.0.2 master
          172.17.0.3 slave01
          172.17.0.4 slave02
          

          最后把上述三个地址信息分别复制到master,slave01和slave02的/etc/hosts即可

      • 测试ssh
        检测下是否master是否可以连上slave01和slave02

        ssh slave01
        ssh slave02
        


      • 修改slaves(worker
        参考资料为什么hadoop没有slaves配置文件?(搞了半天人家改名了,我真是吐血
        vim /usr/local/hadoop-3.2.1/etc/hadoop/workers

        # 将localhost替换成两个slave的主机名
        slave01
        slave02
        
      • 配置完成,启动集群
        master终端上,首先进入/usr/local/hadoop-3.2.1

        cd /usr/local/hadoop-3.2.1
        bin/hdfs namenode -format # 格式化文件系统
        sbin/start-dfs.sh # 开启NameNode和DataNode服务
        

        执行sbin/start-dfs.sh报错,

        用jsp命令测试结果:成功

      • 运行Hadoop实例程序grep
        运行的实例是hadoop自带的grep
        要用到hdfs,所以我们先在hdfs上创建一个目录:./bin/hdfs dfs -mkdir -p /user/hadoop/input

        将/usr/local/hadoop/etc/hadoop/目录下的所有文件拷贝到hdfs上的目录:bin/hdfs dfs -put ./etc/hadoop/*.xml /user/hadoop/input

        已经正确将文件上传到hdfs下

        执行实例程序:bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.1.jar grep /user/hadoop/input output 'dfs[a-z.]+'

        可以在hdfs上的output目录下查看到运行结果:./bin/hdfs dfs -cat output/*
        输出为:

        成功!

    4.用时&心得

    时间统计

    • 查资料4小时
    • 动手6小时
    • 写博客3小时
    • 合计13小时左右

    心得

      这次作业也太花时间了,实验三做的是最舒服的,基本上照着教程打就行了,不过自己花时间慢慢琢磨确实也能学到很多东西(但是好容易暴毙啊,我其他课怎么办,我的竞赛怎么办,我还想当个无忧无虑的考研党
  • 相关阅读:
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
    学期总结
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
  • 原文地址:https://www.cnblogs.com/fangdaoyou/p/12882330.html
Copyright © 2020-2023  润新知