什么是微服务
顾名思义:指的是很小的独立服务。服务是什么呢?实现一个简单的业务逻辑既是一个服务。所以我们说微服务是指一个简单的业务逻辑用多个独立的小型服务实现。既然了解了什么是微服务,那我们今天就用docker按照微服务的设置思路来实现一个简单的业务逻辑。
业务逻辑
简单说:需要一个web展示页面,访问这个web可以输入名字,根据输入的名字动态生成一个简易的像素图标作为这个名字的头像。
复杂说:通过python Flask创建一个网页,要有输入框和提交按钮,通过Flask的response返回头像;当我们输入名字之后交于dnmonster容器处理,这个容器返回一个头像给Flask 网页;使用Redis缓存技术,当输入的名字已经在缓存中不再重新请求dnmonster容器,直接返回头像。
业务实现
编写python文件 identidock.py
mkdir -p identidock/app cd identidock/app vim identidock/app/identidock.py #! coding=utf-8 # 导入要用到的模块 from flask import Flask, Response, request import requests import hashlib import redis ? app = Flask(__name__) # 建立redis缓存,连接到redis cache = redis.StrictRedis(host='redis', port=6379, db=0) # 定义salt值,salted = salt + name salt = "UNIQUE_SALT" default_name = 'CGLS Blog' # 设置route支持get和post两种请求 @app.route('/', methods=['GET', 'POST']) def mainpage(): name = default_name # 提交姓名 if request.method == 'POST': name = request.form['name'] salted_name = salt + name # 对姓名进行SHA256加密运算 name_hash = hashlib.sha256(salted_name.encode()).hexdigest() header = '<html><head><title>Identidock</title></head><body>' body = '''<form method="POST"> Hello <input type="text" name="name" value="{0}"> <input type="submit" value="submit"> </form> <p>You look like a: <img src="/monster/{1}"/> '''.format(name, name_hash) footer = '</body></html>' # 返回web页面 return header + body + footer ? @app.route('/monster/<name>') def get_identicon(name): # 检查姓名是否在缓存中 image = cache.get(name) if image is None: print ("Cache miss", flush=True) # 获取相应的头像 r = requests.get('http://dnmonster:8080/monster/' + name + '?size=80') image = r.content # 将姓名和头像一起写到缓存中 cache.set(name, image) # 返回头像 return Response(image, mimetype='image/png') ? if __name__ == '__main__': app.run(debug=True, host='0.0.0.0')
编写cmd.sh文件
vim identidock/cmd.sh #!/bin/bash set -e ? if [ "$ENV" = 'DEV' ]; then echo "Running Development Server" exec python "identidock.py" else echo "Running Production Server" exec uwsgi --http 0.0.0.0:9090 --wsgi-file /app/identidock.py --callable app --stats 0.0.0.0:9191
编写Dockerfile
vim Dockerfile FROM python:3.4 ? RUN groupadd -r uwsgi && useradd -r -g uwsgi uwsgi RUN pip install Flask==0.10.1 uWSGI requests==2.5.1 redis==2.10.3 WORKDIR /app COPY app /app COPY cmd.sh / RUN chmod +x /cmd.sh EXPOSE 9090 9191 USER uwsgi ? CMD ["/cmd.sh"]
编写docker-compose.yml
vim docker-compose.yml identidock: build: . ports: - "5000:5000" environment: ENV: DEV volumes: - ./app:/app links: - dnmonster - redis ? dnmonster: image: amouat/dnmonster:1.0 ? redis: image: redis:3.0
简单说一下上面几个文件之间的关系
docker-compose.yml自动化管理Dockerfile创建docker identidock镜像并控制运行identidock容器,dnmonster容器,redis容器。Dockerfile是为了创建identidock镜像,它用到了cmd.sh脚本,并且使用了identidock.py文件。cmd.sh文件是判断环境是调试环境还是生产环境,根据环境不同启用不同的命令。identidock.py文件是为了实现web页面,并使用redis容器的缓存存储功能和dnmonster容器的返回头像功能。
接下来就是生成容器集群了:
# 创建需要的identidock镜像 cd identidock docker-compose build # 生成并启动容器集群 docker-compose up -d # 查看自己的集群,如果你开启了防火墙记得打开5000端口 docker-compose ps 浏览器访问http://<localhost_ip>:5000
总结
我们创建的业务逻辑应用,使用到了三个微型服务,分别是web服务提供web页面;nodejs服务提供返回头像;redis服务提供缓存存储。通过docker自动化工具docker-compose进行管理,根据实际情况我们可以对这几个服务进行动态扩展。