【云原生 | 53】Docker三剑客之Docker Compose应用案例一:Web负载均衡

博主简介
        云计算领域优质创作者
        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("  

HA Webpage Visit Results

"); 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("

#"+ str(request[pair] [1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+" > to WebServer <"+pair[1]+" >

") else: file.write("

#"+ str(request[pair] [1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+ "> to WebServer <"+pair[1]+ ">

") file.write(" "); 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镜像:

【云原生 | 53】Docker三剑客之Docker Compose应用案例一:Web负载均衡_第1张图片

$ 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容器了,更为灵活。

结束语

你可能感兴趣的:(云原生,docker,容器)