用 Python、 RabbitMQ 和 Nameko 实现微服务

"微服务是一股新浪潮" - 现如今,将项目拆分成多个独立的、可扩展的服务是保障代码演变的最好选择。在 Python 的世界里,有个叫做 “Nameko” 的框架,它将微服务的实现变得简单并且强大。

微服务

在最近的几年里,“微服务架构”如雨后春笋般涌现。它用于描述一种特定的软件应用设计方式,这种方式使得应用可以由多个独立部署的服务以服务套件的形式组成。 - M. Fowler

推荐各位读一下 Fowler 的文章 以理解它背后的原理。

好吧,那它究竟意味着什么呢?

简单来说,微服务架构可以将你的系统拆分成多个负责不同任务的小的(单一上下文内)功能块responsibilities blocks,它们彼此互无感知,各自只提供用于通讯的通用指向common point。这个指向通常是已经将通讯协议和接口定义好的消息队列。

这里给大家提供一个真实案例

案例的代码可以通过 github: http://github.com/rochacbruno/nameko-example 访问,查看 service 和 api 文件夹可以获取更多信息。

想象一下,你有一个 REST API ,这个 API 有一个端点(LCTT 译注:REST 风格的 API 可以有多个端点用于处理对同一资源的不同类型的请求)用来接受数据,并且你需要将接收到的数据进行一些运算工作。那么相比阻塞接口调用者的请求来说,异步实现此接口是一个更好的选择。你可以先给用户返回一个 "OK - 你的请求稍后会处理" 的状态,然后在后台任务中完成运算。

同样,如果你想要在不阻塞主进程的前提下,在计算完成后发送一封提醒邮件,那么将“邮件发送”委托给其他服务去做会更好一些。

场景描述

用代码说话

让我们将系统创建起来,在实践中理解它:

环境

我们需要的环境:

  • 运行良好的 RabbitMQ(LCTT 译注:RabbitMQ 是一个流行的消息队列实现)
  • 由 VirtualEnv 提供的 Services 虚拟环境
  • 由 VirtualEnv 提供的 API 虚拟环境

Rabbit

在开发环境中使用 RabbitMQ 最简单的方式就是运行其官方的 docker 容器。在你已经拥有 Docker 的情况下,运行:


  1. docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

在浏览器中访问 http://localhost:15672 ,如果能够使用 guest:guest 验证信息登录 RabbitMQ 的控制面板,说明它已经在你的开发环境中运行起来了。

服务环境

现在让我们创建微服务来满足我们的任务需要。其中一个服务用来执行计算任务,另一个用来发送邮件。按以下步骤执行:

在 Shell 中创建项目的根目录


  1. $ mkdir myproject
  2. $ cd myproject

用 virtualenv 工具创建并且激活一个虚拟环境(你也可以使用 virtualenv-wrapper)


  1. $ virtualenv service_env
  2. $ source service_env/bin/activate

安装 nameko 框架和 yagmail


  1. (service_env)$ pip install nameko
  2. (service_env)$ pip install yagmail

服务的代码

现在我们已经准备好了 virtualenv 所提供的虚拟环境(可以想象成我们的服务是运行在一个独立服务器上的,而我们的 API 运行在另一个服务器上),接下来让我们编码,实现 nameko 的 RPC 服务。

我们会将这两个服务放在同一个 python 模块中,当然如果你乐意,也可以把它们放在单独的模块里并且当成不同的服务运行:

在名为 service.py 的文件中


  1. import yagmail
  2. from nameko.rpc import rpc, RpcProxy
  3. class Mail(object):
  4. name = "mail"
  5. @rpc
  6. def send(self, to, subject, contents):
  7. yag = yagmail.SMTP('myname@gmail.com', 'mypassword')
  8. # 以上的验证信息请从安全的地方进行读取
  9. # 贴士: 可以去看看 Dynaconf 设置模块
  10. yag.send(to=to.encode('utf-8),
  11. subject=subject.encode('utf-8),
  12. contents=[contents.encode('utf-8)])
  13. class Compute(object):
  14. name = "compute"
  15. mail = RpcProxy('mail')
  16. @rpc
  17. def compute(self, operation, value, other, email):
  18. operations = {'sum': lambda x, y: int(x) + int(y),
  19. 'mul': lambda x, y: int(x) * int(y),
  20. 'div': lambda x, y: int(x) / int(y),
  21. 'sub': lambda x, y: int(x) - int(y)}
  22. try:
  23. result = operations[operation](value, other)
  24. except Exception as e:
  25. self.mail.send.async(email, "An error occurred", str(e))
  26. raise
  27. else:
  28. self.mail.send.async(
  29. email,
  30. "Your operation is complete!",
  31. "The result is: %s" % result
  32. )
  33. return result

现在我们已经用以上代码定义好了两个服务,下面让我们将 Nameko RPC service 运行起来。

注意:我们会在控制台中启动并运行它。但在生产环境中,建议大家使用 supervisord 替代控制台命令。

在 Shell 中启动并运行服务


  1. (service_env)$ nameko run service --broker amqp://guest:guest@localhost
  2. starting services: mail, compute
  3. Connected to amqp://guest:**@127.0.0.1:5672//
  4. Connected to amqp://guest:**@127.0.0.1:5672//

测试

在另外一个 Shell 中(使用相同的虚拟环境),用 nameko shell 进行测试:


  1. (service_env)$ nameko shell --broker amqp://guest:guest@localhost
  2. Nameko Python 2.7.9 (default, Apr 2 2015, 15:33:21)
  3. [GCC 4.9.2] shell on linux2
  4. Broker: amqp://guest:guest@localhost
  5. >>>

现在你已经处在 RPC 客户端中了,Shell 的测试工作是通过 n.rpc 对象来进行的,它的使用方法如下:


  1. >>> n.rpc.mail.send("name@email.com", "testing", "Just testing")

上边的代码会发送一封邮件,我们同样可以调用计算服务对其进行测试。需要注意的是,此测试还会附带进行异步的邮件发送。


  1. >>> n.rpc.compute.compute('sum', 30, 10, "name@email.com")
  2. 40
  3. >>> n.rpc.compute.compute('sub', 30, 10, "name@email.com")
  4. 20
  5. >>> n.rpc.compute.compute('mul', 30, 10, "name@email.com")
  6. 300
  7. >>> n.rpc.compute.compute('div', 30, 10, "name@email.com")
  8. 3

在 API 中调用微服务

在另外一个 Shell 中(甚至可以是另外一台服务器上),准备好 API 环境。

用 virtualenv 工具创建并且激活一个虚拟环境(你也可以使用 virtualenv-wrapper)


  1. $ virtualenv api_env
  2. $ source api_env/bin/activate

安装 Nameko、 Flask 和 Flasgger


  1. (api_env)$ pip install nameko
  2. (api_env)$ pip install flask
  3. (api_env)$ pip install flasgger

注意: 在 API 中并不需要 yagmail ,因为在这里,处理邮件是服务的职责

创建含有以下内容的 api.py 文件:


  1. from flask import Flask, request
  2. from flasgger import Swagger
  3. from nameko.standalone.rpc import ClusterRpcProxy
  4. app = Flask(__name__)
  5. Swagger(app)
  6. CONFIG = {'AMQP_URI': "amqp://guest:guest@localhost"}
  7. @app.route('/compute', methods=['POST'])
  8. def compute():
  9. """
  10. Micro Service Based Compute and Mail API
  11. This API is made with Flask, Flasgger and Nameko
  12. ---
  13. parameters:
  14. - name: body
  15. in: body
  16. required: true
  17. schema:
  18. id: data
  19. properties:
  20. operation:
  21. type: string
  22. enum:
  23. - sum
  24. - mul
  25. - sub
  26. - div
  27. email:
  28. type: string
  29. value:
  30. type: integer
  31. other:
  32. type: integer
  33. responses:
  34. 200:
  35. description: Please wait the calculation, you'll receive an email with results
  36. """
  37. operation = request.json.get('operation')
  38. value = request.json.get('value')
  39. other = request.json.get('other')
  40. email = request.json.get('email')
  41. msg = "Please wait the calculation, you'll receive an email with results"
  42. subject = "API Notification"
  43. with ClusterRpcProxy(CONFIG) as rpc:
  44. # asynchronously spawning and email notification
  45. rpc.mail.send.async(email, subject, msg)
  46. # asynchronously spawning the compute task
  47. result = rpc.compute.compute.async(operation, value, other, email)
  48. return msg, 200
  49. app.run(debug=True)

在其他的 shell 或者服务器上运行此文件


  1. (api_env) $ python api.py
  2. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

然后访问 http://localhost:5000/apidocs/index.html 这个 url,就可以看到 Flasgger 的界面了,利用它可以进行 API 的交互并可以发布任务到队列以供服务进行消费。

注意: 你可以在 shell 中查看到服务的运行日志,打印信息和错误信息。也可以访问 RabbitMQ 控制面板来查看消息在队列中的处理情况。

原文发布时间为:2016-07-17

本文来自合作伙伴“Linux中国”

时间: 2024-10-23 14:58:18

用 Python、 RabbitMQ 和 Nameko 实现微服务的相关文章

使用RabbitMQ的事件驱动微服务

本文讲的是使用RabbitMQ的事件驱动微服务[编者的话]从传统的HTTP调用迁移到基于事件驱动的微服务架构改变了我们以往的思维方式,其有助于服务的解耦和伸缩,该文介绍了使用RabbitMQ作为消息基础设施实现的事件驱动系统以及处理队列的一些模式. 在微服务之间使用正确的模式进行通信有助于应用程序的伸缩以及解决大多数分布式系统的问题.我们一开始是采用直接的HTTP调用来通信的,但后来决定迁移到事件驱动系统上了.该系统改变了我们对于服务之间交互的思维方式,迫使我们采用可伸缩的模式并且提高了我们的适

服务的协作:服务间的消息传递——《微服务设计》读书笔记

很多开发者都表示他们基于HTTP的API是RESTful的.但是,如同Fielding在他的博客中所说,这些API可能并不都是RESTful的.Leonard Richardson为REST定义了一个成熟度模型,具体包含以下4个层次(摘自IBM): 第一个层次(Level 0)的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式.SOAP 和 XML-RPC 都属于此类. 第二个层次(Level 1)的 Web 服务引入了资源的概念.每个资源有对应的标

基于微服务的软件架构模式

今天阅读了两篇关于微服务的文章,总结一些笔记,不敢贸然翻译:一是因为水平不够,翻译的过程会丢掉作者的原意:二是因为技术翻译是一个略微吃力不讨好的活. 微服务(micro services)这个概念不是新概念,很多公司已经在实践了,例如亚马逊.Google.FaceBook,Alibaba.微服务架构模式(Microservices Architecture Pattern)的目的是将大型的.复杂的.长期运行的应用程序构建为一组相互配合的服务,每个服务都可以很容易得局部改良. Micro这个词意味

微服务(Microservices)—Martin Flower【翻译】【转载】

本文转载自:http://www.cnblogs.com/liuning8023/p/4493156.html ---------------------------------------------------------------------------- 原文是 Martin Flower 于 2014 年 3 月 25 日写的<Microservices>. 本文内容 微服务 微服务风格的特性 组件化(Componentization )与服务(Services) 围绕业务功能的组

无服务器的微服务

在 2015年的LinuxCon/ContainerCon 上我呈现了一次演示驱动的演讲,标题叫做"没有服务器的微型服务". 其中,我创建了一个图片处理的微型服务,将其部署到了多个区域,构建了一个移动 app 并使用它(译者注:指的是这个微型服务)作为后台,添加了一个使用了 Amazon API 网关的基于 HTTP 的 API 和一个网站,并且对它进行了单元和负载测试,所有这些都没有用到任何服务器. 这篇博文对演讲的细节进行了重制,为你逐步完成所有必要的比周,并深入到了架构中去.而高

如何在Ruby中编写微服务?

[编者按]本文作者为 Pierpaolo Frasa,文章通过详细的案例,介绍了在Ruby中编写微服务时所需注意的方方面面.系国内 ITOM 管理平台 OneAPM 编译呈现. 最近,大家都认为应当采用微服务架构.但是,又有多少相关教程呢?我们来看看这篇关于用Ruby编写微服务的文章吧. 人人都在讨论微服务,但我至今也没见过几篇有关用Ruby编写微服务的.像样的教程.这可能是因为许多Ruby开发人员仍然最喜欢Rails架构(这没什么不好,Rails本身也没什么不好,但是Ruby可以做到的事还有很

12年互联网产品开发人眼中的微服务架构云端应用

微服务架构很热,讨论的文章非常多.但如果提到微服务架构的云端应用,可以深入分析的还比较少.本篇来自中生代技术群(FreshmanTechnology)第二期,好雨云创始人兼CEO刘凡的分享.其曾任澳客网 CTO和CEO职位.拥有超过12年互联网产品开发和管理经验,专注于互联网技术架构设计,对产品设计.敏捷开发.安全.OKRs.大数据等领域有深入研究.现推崇反应式编程(http://www.reactivemanifesto.org/),并在多个产品中成功应用. 下为正文: 微服务架构(Micro

简述 Microservices(微服务)

自 2014 年始,Microservices(微服务)一词越来越火爆,不谈 Microservices 彷佛就 out 了.那么什么是 Microservices?Microservices 架构与传统的架构有什么区别?何时应该采用 Microservices?如何构建 Microservices? 本文,就针对上述提到的问题,来简单介绍下 Microservices. 什么是 Microservices 微服务的诞生并非偶然: 领域驱动设计指导我们如何分析并模型化复杂的业务:敏捷方法论帮助我

基于Nginx搭建一个安全的、快速的微服务架构

本文讲的是基于Nginx搭建一个安全的.快速的微服务架构[编者的话]本文改编自Chris Stetson发表在nginx.conf 2016上的一个有关如今的微服务以及如何使用Nginx构建一个快速的.安全的网络系统的演讲,大家可以在YourTube上回看此次演讲. 0:00 - 自我介绍 Chris Stetson:Hi,我的名字是Chris Stetson,我在Nginx带领专业服务部门,同时也领导微服务实践. 今天我们要谈论微服务以及如何使用Nginx构建一个快速的.安全的网络系统.在我们