@Container容器技术大会将于6月4日在上海光大会展中心国际大酒店举办,来自携程、PPTV、蚂蚁金服、京东、浙江移动、海尔电器、唯品会、eBay、道富银行、麻袋理财等公司的技术负责人将带来实践经验分享,3月21日之前购票只需238元,欢迎感兴趣的同学抢购。

微服务是什么?

微服务是一种架构风格,它包括多个彼此间进行通信的独立进程。在设计上,这些进程具有高度的可扩展性、相互解耦而且一次只完成一个较小的任务。这些服务都拥有自己的资源以及通过网络实现彼此间通信的进程。

相比于靠后端的单体结构来封装所有服务器逻辑的传统客户端-服务器架构(C/S架构)而言,微服务架构的差异性体现在关注点分离(Separation of concern)。这种设计模式更易于维护,使得灵活性、可扩展性及容错能力更强。但是这种分布式架构所的不足之处体现在如果设计不合理就会使得排错及维护变得复杂。

一个简单微服务的例子

让我们来分析这样的一个场景:你正在使用微服务模式构建一个电子商务网店。

对于一个电商网店上的常见商品,好比说iPhone,其详情页会显示:

  • 产品的及基本信息
  • 你的购买历史
  • 哪些人买了iPhone也买了手机套
  • 与苹果手机相关的优惠和折扣
  • 店家的数据
  • 送货方式
  • 推荐商品等等

此外,这个简单的产品详情页的接口将有多个版本的来匹配Web、移动端以及用于第三方应用程序的REST API。

在微服务模式中数据分布在多个服务之间。在这个例子中,服务包括:

  • 产品详情服务
  • 商家服务
  • 支付服务
  • 优惠及折扣服务
  • 库存服务
  • 定价服务
  • 回顾服务
  • 推荐服务

这些独立的服务是如何被访问的呢?

解决办法是使用一个API网管,它作为所有客户端的单一入口并且根据需求调用分布在整个基础架构中的特定微服务。以上模式的行业应用案例是NetFlix API网关,它具有支持不同设备的多个API客户端。你可以点击此处了解更多

构建一个简单的微服务

目前有很多方法可以用于构建你的微服务。

在本文中我们将使用ZeroMQ来创建两个进程之间的通信。ZeroMQ提供了用于在套接字之上开发可扩展、分布式systed的构建块。它使用椭圆曲线密码体制(第四版)来实现安全性,并提供了即刻开启的通讯模式

关于ZMQ,还有很多优点。MQ即是针对异步工作而设计的线程化消息队列。谈论太多zeroMQ的内容已经超出了本文的范畴,你可以阅读使用zeromq以及zeromq用于分布式系统

我们要使用的另一个工具是Docker。本文假设读者对Docker已经有了基础的了解。

ZeroMQ有很多种通讯模式,为了开始我们的工作,让我们用ZeroMQ和Flask来配置一个简单的PUB-SUB。下图展示了组件之间的关系和数据流。

  • 1&3 - 一个flask服务器运行在5000端口上而且其URL是/downcase/。该URL用来接受(GET)请求,而所有格式为的请求将收到回应:答谢字符将会转换为小写字符并返回。
  • 2 - 回应的消息也被发送给同一个容器中的ZMQ发布者(Publisher)
  • 4,5 - ZMQ订阅者(subscriber)持续监听并将来自ZMQ服务器的消息保存到名为subscriber.log的文件中

创建服务器

首先看一下我们的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(zeromq的Python绑定)同时也安装了Flask。接着我们导出端口5000(flask服务器)和4444(发布者运行的端口)。此外,我们复制了包含所有flask及zeromq pythond代码的脚本文件zmqserver.py并运行它。

现在我们来看一下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端口上。我们创建了一个context并且声明了URL。我们运行了flask app,它通过URL /downcase/把GET获得的参数Param转换成小写字符,这就是服务的应答。应答的字符串是published,它作为一个消息把相同的字符串返回给浏览器。

为了构建以上的Docker映像(image),我们执行以下的命令:
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开头。我们在URL tcp://IP:PORT上进行监听。一旦我们收到一个消息,就将其附上时间戳后记录到名为subscriber.log的文件中。运行客户端要做的所有工作就是执行 python <name_of_client_file>.py。如果你在以上的架构上进行构建,它可以很好地充当近实时的日志聚合引擎。

我在Unbuntu主机上对以上的代码进行了测试。这里所用的代码保管在GitHub上。这是一个如何配置ZMQ、Docker和Python服务器的基础讲解,在我的下一片文章中我们会使用我们已经学习的东西构建简单的微服务。

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

最新文章

  1. thinkphp vendor
  2. CentOS6.6安装virtualbox4.1.44
  3. 【转】关于编写性能高效的javascript事件的技术
  4. 有效提高win7电脑网速50倍
  5. archlinux 学习笔记
  6. python项目练习3:万能的XML
  7. (转)mongoDB 禁用大内存页面 transparent_hugepage=never
  8. 一个free的问题
  9. Java中的IO学习总结
  10. Android 使用 intent 实现简单登陆页面
  11. HDU2451:Simple Addition Expression
  12. windows 下安装Python
  13. db2 表关联查询
  14. java面向对象基础(二)
  15. monkeyrunner_获取apk的包名和activity名
  16. SQLSERVER 聚集一个表的字段2008及以后,要求支持XML
  17. css缩放的坑
  18. 请给Array本地对象增加一个原型方法,它用于删除数组条目中重复的条目(可能有多个),返回值是一个包含被删除的重复条目的新数组。
  19. 利用ONENET平台控制MPC
  20. BZOJ5047 空间传送装置 2017年9月月赛 最短路 SPFA

热门文章

  1. Ubuntu 14 如何解压 .zip、.rar 文件
  2. 四:DRF项目开发的准备
  3. 用jQuery实现参数自定义的文字跑马灯效果
  4. Windows下命令行怎样登录MySQL
  5. guxh的python笔记四:迭代
  6. python中得公有和私有——私有函数和公开函数_补充完整
  7. VUE + vue-cli + webpack 创建新项目
  8. 微信小程序textarea组件在fixed定位中随页面滚动
  9. react+classnames
  10. 4 Django应用 第3部分(视图部分)