pengkobe / reading-notes

:stars: to record daily reading notes. I build an issue blog to record daily FE study notes. suggestion and comments are welcomed.
https://github.com/pengkobe/reading-notes/issues
MIT License
13 stars 1 forks source link

使用 Python ZeroMQ 与 Docker 搭建微服务架构 #482

Open pengkobe opened 5 years ago

pengkobe commented 5 years ago

原文: Setup Microservices Architecture in Python with ZeroMQ & Docker

什么是微服务

微服务是一种把多个独立服务连接起来的架构模式,其具有高拓展性。各个服务之间实现了解耦,每个服务独享系统资源独立运行,各服务之间则通过网络进行通讯和协作。
与传统客户端-服务端架构的区别是,传统的服务端包含了所有的业务逻辑,而微服务架构则强调业务分离,这种架构模式使得运维、拓展、系统弹性、容错率都得到了提升,这种架构模式实现难度比传统架构大,设计不好时,会让系统变得难以调试和维护。

微服务架构示例

这里以在电商网站上卖 iPhone 作为示例,一般来说,会在产品详情页展示这些信息

在微服务模式中,数据会在多个服务中进行流转,在这个场景中,可能会涉及到如下服务

那么这些服务是如何被访问的呢?
解决方案是通过 API 网关进行访问,它作为所有客户端的访问入口,可以根据数据需求来调用特定的服务,NetFlix API 就是通过这种方式实现的,他们使用多个 API 端来满足不同设备的访问需求,具体可以参见这里 .

微服务构建示例

实现方式那就太多了,这篇文章,我们使用 ZeroMQ 来实现进程间的通信,ZeroMQ 提供了构建单元来开发基于套接字的分布式系统,首先,它很安全,使用了椭圆曲线加密( 版本4+)而且提供了非常棒的通信模式(译者表示并不懂)。
MQ 指的是线程消息队列,其可以用来实现异步运行,这篇文章也不便多说,建议你读读 working with zeromq messaingdistributed systems with zeromq.
我们需要使用的另外一个工具是 Docker,希望各位已经了解过 Docker 了
ZeroMQ 有很多的通信模式,这里我们从基于 ZeroMQ 与 Flask 的 PUB-SUB 模式讲起,插图展示了组件间的关系。 microservices-docker-python-apcelent

构建服务端Building the Server

Dockerfile 内容如下

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get install -y --force-yes python python-dev python-setuptools software-properties-common gcc python-pip
RUN apt-get clean all

RUN pip install pyzmq

RUN pip install Flask

ADD zmqserver.py /tmp/zmqserver.py

# Flask Port
EXPOSE 5000

# Zmq Sub Server
EXPOSE 4444

CMD ["python","/tmp/zmqserver.py"]

我们选用 Ubuntu 14.04 作为容器操作系统并安装了一些基本库. 使用 pip 安装 pyzmq ( zmq 对应的 python 库)和 Flask. 然后我们使用 5000 端口发布 flask 服务端,4444 端口发布 ZMQ publisher, 同时,我们拷贝 zmqserver.py 脚本并执行,其包含了所有 flask 与 zeromq 运行需要的代码。

zmqserver.py 内容如下

# server.py
import time
import zmq

HOST = '127.0.0.1'
PORT = '4444'

_context = zmq.Context()
_publisher = _context.socket(zmq.PUB)
url = 'tcp://{}:{}'.format(HOST, PORT)

def publish_message(message):

    try:
    _publisher.bind(url)
    time.sleep(1)
    _publisher.send(message)

    except Exception as e:
    print "error {}".format(e)

    finally:
    _publisher.unbind(url)

from flask import Flask
from flask import request
app = Flask(__name__)

@app.route("/downcase/", methods=['GET'])
def lowerString():

    _strn = request.args.get('param')
    response = 'lower case of {} is {}'.format(_strn, _strn.lower())
    publish_message(response)
    return response

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False)

ZMQ 运行在 4444 端口. 我们创建了上下文,指定了 URL,运行 flask 应用,它包含一个 URL /downcase/,它能够将 GET 请求的参数转换为小写,返回的字符串被作为消息进行发布,并且作为响应返回到浏览器端。
为了构建上述 docker 镜像,我们执行以下命令:

sudo docker build -t docker-zmq-pub

执行下述命令则可以运行起来:

docker run --name docker-pub-server -p 5000:5000 -p 4444:4444 -t docker-zmq-pub

我们将端口 5000 和 4444 映射到机器主机,从而使得无论客户端在哪,都能够订阅消息发布器。

订阅客户端

# client.py
import zmq
import sys
import time
import logging
import os

HOST = '127.0.0.1'
PORT = '4444'

logging.basicConfig(filename='subscriber.log', level=logging.INFO)

class ZClient(object):

    def __init__(self, host=HOST, port=PORT):
    """Initialize Worker"""
    self.host = host
    self.port = port
    self._context = zmq.Context()
    self._subscriber = self._context.socket(zmq.SUB)
    print "Client Initiated"

    def receive_message(self):
    """Start receiving messages"""
    self._subscriber.connect('tcp://{}:{}'.format(self.host, self.port))
    self._subscriber.setsockopt(zmq.SUBSCRIBE, b"")

    while True:
        print 'listening on tcp://{}:{}'.format(self.host, self.port)
        message = self._subscriber.recv()
        print message
        logging.info(
            '{}   - {}'.format(message, time.strftime("%Y-%m-%d %H:%M")))

if __name__ == '__main__':
    zs = ZClient()
    zs.receive_message()

我们指定发布器的 IP 地址和端口,目前发布器和订阅者运行在一台机器上,因为指定为 127 即可,我们监听地址 tcp://IP:PORT. 一旦受到消息就把对应的时间戳和消息内容写入到 subscriber.log 文件中,你只需要执行 python.py 文件就能让客户端运行起来,基于以上架构,你可以实现实时日志系统。

我已经在 Ubuntu 机器上测试了上述代码,代码也搬到了 github 上,这篇文章只讲述了 ZMQ、docker、python 服务器的基本配置和使用,在下篇文章我们将基于这篇文章的内容来搭建一个微服务示例。

希望这篇文章对你有所帮助