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相关等,收获还是很大。