🍁博主简介:
🏅云计算领域优质创作者
🏅2022年CSDN新星计划python赛道第一名🏅2022年CSDN原力计划优质作者
🏅阿里云ACE认证高级工程师
🏅阿里云开发者社区专家博主💊交流社区:CSDN云计算交流社区欢迎您的加入!
目录
1.web子目录
1.1 index.py
1.2 index.html
1.3 Dockerfile
2.haproxy子目录
3.docker-compose.yml文件
4.运行compose项目
👑👑👑结束语👑👑👑
负载均衡器+Web应用是十分经典的应用结构。下面,博主将创建一个该结构的Web项目:将Haproxy作为负载均衡器,后端挂载三个Web容器。
|
首先创建一个haproxy_web目录,作为项目工作目录,并在其中分别创建两个子目录:web和haproxy。
|
1.web子目录
在web子目录下将放置所需Web应用代码和Dockerfile,下面将生成需要的Web镜像。
|
这里用Python程序来实现一个简单的Web应用,该应用能响应HTTP请求,返回的页面将打印出访问者的IP和响应请求的后端容器的IP。
|
1.1 index.py
编写一个index.py作为服务器文件,代码为: |
#!/usr/bin/python
#authors: yeasy.github.com
#date: 2013-07-05
import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
import socket
import fcntl
import struct
import pickle
from datetime import datetime
from collections import OrderedDict
class HandlerClass(SimpleHTTPRequestHandler):
def get_ip_address(self,ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
def log_message(self, format, *args):
if len(args) < 3 or "200" not in args[1]:
return
try:
request = pickle.load(open("pickle_data.txt","r"))
except:
request=OrderedDict()
time_now = datetime.now()
ts = time_now.strftime('%Y-%m-%d %H:%M:%S')
server = self.get_ip_address('eth0')
host=self.address_string()
addr_pair = (host,server)
if addr_pair not in request:
request[addr_pair]=[1,ts]
else:
num = request[addr_pair][0]+1
del request[addr_pair]
request[addr_pair]=[num,ts]
file=open("index.html", "w")
file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\"
face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit
Results</h1></center>");
for pair in request:
if pair[0] == host:
guest = "LOCAL: "+pair[0]
else:
guest = pair[0]
if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d %H:%M:%S'))
.seconds < 3:
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair]
[1]) +": <font color=\"red\">"+str(request[pair][0])+ "</
font> requests " + "from <<font color=\"blue\">"+guest+"
</font>> to WebServer <<font color=\"blue\">"+pair[1]+"
</font>></p>")
else:
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair]
[1]) +": <font color=\"maroon\">"+str(request[pair][0])+
"</font> requests " + "from <<font color=\"navy\">"+guest+
"</font>> to WebServer <<font color=\"navy\">"+pair[1]+
"</font>></p>")
file.write("</body> </html>");
file.close()
pickle.dump(request,open("pickle_data.txt","w"))
if __name__ == '__main__':
try:
ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"
addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1]
port = len(sys.argv) < 3 and 80 or int(sys.argv[2])
HandlerClass.protocol_version = Protocol
httpd = ServerClass((addr, port), HandlerClass)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
except:
exit()
1.2 index.html
生成一个临时的index.html文件,其内容会由index.py来更新:模板文件 |
$ touch index.html
1.3 Dockerfile
生成一个Dockerfile,部署该Web应用,内容为: |
FROM python:2.7
WORKDIR /code
ADD . /code
EXPOSE 80
CMD python index.py
2.haproxy子目录
该目录将配置haproxy镜像。
在其中生成一个haproxy.cfg文件,内容为:
|
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen stats
bind 0.0.0.0:70
mode http
stats enable
stats hide-version
stats scope .
stats realm Haproxy\ Statistics
stats uri /
stats auth user:pass
frontend balancer
bind 0.0.0.0:80
mode http
default_backend web_backends
backend web_backends
mode http
option forwardfor
balance roundrobin
server weba weba:80 check
server webb webb:80 check
server webc webc:80 check
option httpchk GET /
http-check expect status 200
3.docker-compose.yml文件
在haproxy_web目录下编写一个docker-compose.yml文件,该文件是Compose使用的主模板文件。其中,指定启动3个Web容器(weba、webb、webc),以及1个Haproxy容器:
|
# This will start a haproxy and three web services. haproxy will act as a
loadbalancer.
# Authors: yeasy.github.com
# Date: 2015-11-15
weba:
build: ./web
expose:
- 80
webb:
build: ./web
expose:
- 80
webc:
build: ./web
expose:
- 80
haproxy:
image: haproxy:1.6
volumes:
- ./haproxy:/haproxy-override
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- weba
- webb
- webc
ports:
- "80:80"
- "70:70"
4.运行compose项目
现在haproxy_web目录应该长成下面的样子: |
haproxy_web├── docker-compose.yml├── haproxy│ └── haproxy.cfg└── web
├── Dockerfile
├── index.html
└── index.py
在该目录下执行sudo docker-compose up命令,控制台会整合显示出所有容器的输出信息:
|
$ sudo docker-compose up
Recreating haproxyweb_webb_1...
Recreating haproxyweb_webc_1...
Recreating composehaproxyweb_weba_1...
Recreating composehaproxyweb_haproxy_1...
Attaching to composehaproxyweb_webb_1, composehaproxyweb_webc_1, composehaproxyweb_weba_1, composehaproxyweb_haproxy_1
此时通过浏览器访问本地的80端口,会获取到页面信息,如图所示。 |
经过Haproxy自动转发到后端的某个Web容器上,刷新页面,可以观察到访问的容器地址的变化。
|
访问本地70端口,可以查看到Haproxy的统计信息,如下图所示。 查看本地的镜像,会发现Compose自动创建的haproxyweb_weba、 haproxyweb_webb、haproxyweb_webc镜像:
|
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
haproxyweb_webb latest 33d5e6f5e20b 44 minutes ago 675.2 MB
haproxyweb_weba latest 33d5e6f5e20b 44 minutes ago 675.2 MB
haproxyweb_webc latest 33d5e6f5e20b 44 minutes ago 675.2 MB
当然,还可以进一步使用Consul等方案来实现服务自动发现,这样就可以不用手动指定后端的web容器了,更为灵活。
|
👑👑👑结束语👑👑👑