系统综合实践_4

1、Docker-compose实现Tomcat+Nginx负载均衡


  • nginx反向代理原理

    客户端向反向代理发送请求,接着反向代理转发请求至目标服务器,并把获得的内容返回给客户端。

  • nginx代理tomcat集群

    • 项目结构

    • docker-compose.yml
     version: "3.8"
    services:
        nginx:
            image: nginx
            container_name: t4-nginx
            ports:
                - 80:9191
            volumes:
                - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 挂载配置文件
            depends_on:
                - tomcat1
                - tomcat2
                - tomcat3
    
        tomcat1:
            image: tomcat
            container_name: tct1
            volumes:
                - ./tomcat1:/usr/local/tomcat/webapps/ROOT # 挂载web目录
    
        tomcat2:
            image: tomcat
            container_name: tct2
            volumes:
                - ./tomcat2:/usr/local/tomcat/webapps/ROOT
    
        tomcat3:
            image: tomcat
            container_name: tct3
            volumes:
                - ./tomcat3:/usr/local/tomcat/webapps/ROOT
    
    • nginx配置文件default.conf
      upstream tomcats {
            server tct1:8080;
            server tct2:8081;
            server tct3:8082;
      }
    
      server {
            listen 9191;
            server_name localhost;
    
            location / {
                  proxy_pass http://tomcats; # 请求转向tomcats
            }
      }
    
    • 执行docker-compose up

    • 浏览器访问localhost,显示的是自己编写的html

  • nginx负载均衡策略

    • 负载均衡策略
    • 轮询:最基本的配置方法,上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。
    • weight:在轮询策略的基础上指定轮询的几率。
    • ip_hash:指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。
    • least_conn:把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。
    • 详见:Nginx服务器之负载均衡策略
    • 负载均衡测试

      • 轮询
      • 编写测试代码

        import requests
        
        url = "http://localhost"
        count = {'tomcat1':0,'tomcat2':0,'tomcat3':0}
        for i in range(0,100):
              response = requests.get(url)
        
              if response.text == 'This is tomcat1 !
        ':
                    count['tomcat1'] += 1
              elif response.text == 'This is tomcat2 !
        ':
                    count['tomcat2'] += 1
              elif response.text == 'This is tomcat3 !
        ':
                    count['tomcat3'] += 1
              print(response.text)
        
        print(count)
        
      • 测试结果

      • weight
      • 修改nginx配置文件default.conf

        upstream tomcats {
              server tct1:8080 weight=1;
              server tct2:8081 weight=2;
              server tct3:8082 weight=4;
        }
        
        server {
              listen 9191;
              server_name localhost;
        
              location / {
                    proxy_pass http://tomcats; # 请求转向tomcats
              }
        }
        
      • 重启容器

             sudo docker restart <Container ID>
        
      • 执行测试程序,100次访问,访问数分别为14,29,57,比例接近1:2:4

      • ip-hash
      • 修改default.conf

        upstream tomcats {
              ip_hash
              server tct1:8080 weight=1;
              server tct2:8081 weight=2;
              server tct3:8082 weight=4;
        }
        
        server {
              listen 9191;
              server_name localhost;
        
              location / {
                    proxy_pass http://tomcats; # 请求转向tomcats
              }
        }
        
      • 重启容器并执行测试程序,100次访问都访问同一服务器。

2、Docker-compose部署javaweb运行环境


  • 项目结构

  • docker-compose.yml

     version: "3"   #版            services:     务节点
         tomcat:     #tcat 服务
           image: tcat    #镜像
           hostname: hostnam      #容器的主机名
           container_ne: tomcat00   #容器名
         ports:      #端口
          - "5050:808
           volumes:  #数据卷
            - /webapps:/usr/local/tomcat/webapps"
          - ./wait-for-it.sh:/wt-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 tomcat123 {
     server tomcat00:8080;
 }

 server {
         listen 8080;
         server_name localhost
             location / {
             proxy_pass http://tomcat123;
   }
 }
  • 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"
  • 修改端口容器

进入/webapps/ssmgrogshop_war/WEB-INF/classes/目录下的jdbc.properties文件,修改ip和端口。

  • 启动容器

       docker-compose up -d
  • 浏览器访问http://127.0.0.1:8080/ssmgrogshop_war



3、Docker搭建大数据集群环境


    做的时候忘记截图了,到做完的时候才想起来,所以只截了后面部分内容的图片。

  • 实验环境

ubuntu 18.04
openjdk 1.8
hadoop 3.1.3

  • 创建并运行容器

       docker run -it -v ~/:/root/build --name ubuntu ubuntu
  • 更新软件源 & 安装vim & 安装sshd

       apt-get update
       apt-get install vim # 用于修改配置文件
       apt-get install ssh # 分布式hadoop通过ssh连接
       /etc/init.d/ssh start # 开启sshd服务器
       vim ~/.bashrc # 在文件末尾添加/etc/init.d/ssh start,实现ssd开机自启
  • 实现免密登陆

       ssh-keygen -t rsa # 一直按回车即可
       cd ~/.ssh
       cat id_rsa.pub >> authorized_keys 
  • 安装JDK

       apt-get install openjdk-8-jdk
  • 安装hadoop

  • 将预先下载好的压缩包放到创建的目录下,以便后续安装

  • 将压缩包拷入容器

         cd /root/build
         tar -zxvf hadoop-3.1.3.tar.gz -C /usr/local #将hadoop压缩包放入本地build文件夹中
         cd /usr/local/hadoop-3.1.3
         ./bin/hadoop version # 验证安装
    
  • 配置hadoop集群

    • hadoop_env.sh:将export JAVA_HOME=${JAVA_HOME}替换成
      export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
    
    • core-site.xml
      <?xml version="1.0" encoding="UTF-8" ?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl" ?>
      <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
      <?xml version="1.0" encoding="UTF-8" ?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl" ?>
      <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
      <?xml version="1.0" ?>
      <?xml-stylesheet type="text/xsl" href="configuration.xsl" ?>
      <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
      <?xml version="1.0" ?>
      <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>
    
    • 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镜像,表示Hadoop集群中的master,slave01和slave02
           # 第一个终端
           sudo docker run -it -h master --name master ubuntu_hadoop
           # 第二个终端
           sudo docker run -it -h slave01 --name slave01 ubuntu_hadoop
           # 第三个终端
           sudo docker run -it -h slave02 --name slave02 ubuntu_hadoop
    
    • 配置master,slave01和slave02的地址信息

        分别打开/etc/hosts可以查看本机的ip和主机名信息,得到三个ip和主机地址信息,把三个地址信息分别复制到master,slave01和slave02的/etc/hosts

    • 检测master是否可以连接slave01和slave02
           ssh slave01
           ssh slave02
    


    • 修改master上的workers文件

        将localhost修改为slave01 slave02

    • 启动服务
           cd /usr/local/hadoop-3.1.3
           bin/hdfs namenode -format # 格式化文件系统
           sbin/start-dfs.sh # 开启NameNode和DataNode服务
           sbin/start-yarn.sh 
    
    • 使用jps查看三个终端



  • 运行测试实例

    • grep
           hdfs dfs -mkdir -p /user/root/input
           hdfs dfs -put /usr/local/hadoop-3.1.3/etc/hadoop/*s-site.xml input
           hadoop jar /usr/local/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar grep input output 'dfs[a-z.]+'
           hdfs dfs -cat output/*
    

    • wordcount
           hdfs dfs -mkdir -p /user/root/input
           vim txt1.txt
           vim txt2.txt
           hdfs dfs -put ./*.txt input
           hadoop jar /usr/local/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount input output1
           hdfs dfs -cat output1/*
    

4、问题 & 解决

  • 在负载均衡测试时,编写了python代码,却不知道如何在终端上运行,因此顺便研究了一下如何在linux系统的终端上运行py文件,只需要输入python3 /<File Path>/XX.py即可。

  • 在部署Javaweb时不能正确访问web,后来经同学指点发现是web没有连接到数据库,而是连接到了tomcat,修改后重新运行即可。

5、总结


    这次试验整整花了我两个下午+一个晚上,大部分时间都是花在了实验二和三,幸亏实验三的步骤和大数据实验有很多相似的地方,自己在才能少走了许多弯路。通过这次实验,也学了很多内容,包括反向代理、负载均衡策略、javaweb的简单部署、hadoop相关等,收获还是很大。

原文地址:https://www.cnblogs.com/honger125/p/12895218.html