速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

Zato——基于 Python 的 ESB 和后端应用服务器

  • 2013-09-27
  • 本文字数:8023 字

    阅读完需:约 26 分钟

概述

Zato 是一个用 Python 编写的开源 ESB 和应用服务器。按照设计,它用于构建后端应用程序(即仅是 API)和在 SOA 中整合系统。

查看 Zato 的项目文档点击这里,查看其GitHub 页点击这里

Zato 的目标用户是使用 Python 或者 Ruby 和 PHP 等其它动态语言的开发人员,或者是那些考虑在工作中尝试动态语言的技术团队,后者或是因为看到动态语言在其它地方使用,或是因为愿意尝试用其中一种动态语言编写的非前端系统。

该平台是轻量级但完整的,它涵盖了架构师、程序员或者系统管理员的所有视角,对许多特性提供开箱即用的支持,包括 HTTP、SON、SOAP、SQL、AMQP、JMS WebSphere MQ、ZeroMQ、Redis NoSQL、FTP、基于浏览器的 GUI、CLI、API、安全、统计、作业调度、负载均衡和热部署。另外,它还提供了大量指南和参考样式方面的文档。

它的最初版本于 2013 年 5 月 18 日发布,最新的 1.1 版在 6 月初发布。

体系结构

Zato 环境是一个或者多个集群的集合。每个集群由多个共享同一个 SQL 和 Redis 数据库的服务器构成。这些服务器的前端是集群专属的 HA HTTP 负载均衡器。

所有的服务器始终处于活动状态,并且总是运行同一组服务。为了实现 active-standby 设定,负载均衡器可以根据需要把任意服务器离线。

负载均衡器是一个嵌入式的 HAProxy 实例,管理员通过命令行或者通过 GUI 调用 SSL XML-RPC 对其进行远程控制,该过程可以用也可以不用客户端证书。用户可以给服务器赋予权重,以及使用 HAProxy 自身提供的其它功能,如连接 ACL 或速率限制。

服务器基于 gunicorn / gevent 项目构建。该项目是一个联合体,它使用 libevent 来选择每个平台支持的最佳异步事件通知库,如 Linux 平台上的 epoll

为了充分利用单台计算机能够提供的所有 CPU,Zato 按照设定好的数值预先生成一定数量的工作进程,每个进程使用选定的异步网络连接库来处理连接,所有进程监听相同的套接字。负载均衡器用于在不同的计算机之间分配负载及提供 HA。

集群中的一台服务器担当启动 AMQP/JMS WebSphere MQ/ZeroMQ 资源调度器和连接器的角色。如果这台服务器意外宕机,那么始终处于活动状态的 ping 机制可以保证另外一台服务器接管这个角色。

应用程序可以使用多种协议进行集成,包括HTTP(对JSON/SOAP 和纯XML 有特殊支持)、FTP、AMQP、JMS WebSphere MQ(用于实现与现有的MQ Java 应用程序之间的无缝互通性)、Redis 和SQL。其中,HTTP 协议是同步调用Zato 服务的唯一方式。这种情况下,请求应用程序会进入阻塞状态等待响应。

程序员可以使用任何Python 库。如果Zato 自身尚未提供某个功能,也可以使用其它技术实现,如 XML-RPC 或者 SMTP ,该过程仅是一个导入 Python 内置包的问题而已。

集群管理使用基于浏览器的 GUI CLI 。前者主要用于管理处于运行状态的集群,后者则用于在操作系统中安装 Zato 组件,如服务器。

集群配置信息存储在 Redis 和 SQL 操作型数据库中。Redis 存储快速变化和频繁更新的数据,如统计信息或用户的运行时信息,而 SQL ODB 存储可以简单地映射成关系结构的数据。

虽然主要使用 GUI 进行环境配置,但也可以将集群的配置信息以 JSON 格式导出/ 导入,而且导出结果可以存储到一个外部的配置版本库,从而可以对其进行版本管理、标记或者版本间差异比较。

带有GUI 的内置调度器可以用于一次性作业或者循环作业(也可以用Cron 语法)。

服务器和服务只通过Redis 和SQL ODB 进行状态共享。没有自定义的协议或者数据格式用于保持服务器状态的一致性。

Zato 使用超过 160 个自带的管理服务来进行自我管理,其中每一项都可以通过命令行或者在HTTP 上以JSON/SOAP 方式调用公共API 获得。GUI 和CLI 工具本身都是这些服务的客户端。

Zato 已经为 Python 应用程序创建了方便的客户端,所以用 Python 编写的应用程序在与 Zato 暴露的服务进行通信时还是只能使用 Python 对象。

服务

Zato 服务是实现了单个特定方法的 Python 类。它可以接收输入和产生输出,也可以只接收输入或者只产生输出。

服务可以从 GUI 或者命令行以静态的或者热部署的方式安装。安装过程会自动将服务编译成字节码。

服务可以使用任何数据格式,但是Zato 对JSON、SOAP 和普通XML 提供更多支持。如果使用了其中任何一种,序列化和反序列化都会在后台完成,开发人员只需通过点号就可以使用纯Python 对象,而不必基于诸如XSD 那样的模式创建Bean/ 模型/ 存根/ 类——尽管这意味着将没有代码完成。

同一服务可以在HTTP、AMQP、JMS WebSphere MQ、ZeroMQ 和调度器上暴露,而不需要修改任何代码,也不需要重启服务器。特别地,只有在HTTP 上暴露的服务可以进行同步调用。

SimpleIO(SIO)是一种声明式语法,用于表示简单的请求和响应。选用该语法,服务可以在不修改代码的情况下通过 JSON 或者 XML/SOAP 暴露。SIO 不能处理复杂文档,它不接受任意嵌套的结构。任何结构的任何文档都可以用于 Zato, 只是有时不能用于 SIO。

下面是一个基础服务的示例,该服务使用 Yahoo YQL/JSON Google’s XML API 获取一家公司的市场资本总额。

该服务接收一个股票代码(例如 GOOG 或 RHT),发出两个 HTTP 请求,然后清理响应并把它们组合成一个通用格式。根据请求格式的不同,组合结果以 JSON 或 XML 格式返回。

复制代码
# anyjson
from anyjson import loads
# bunch
from bunch import bunchify
# decimal
from decimal import Decimal
# lxml
from lxml.objectify import fromstring
# Zato
from zato.server.service import Service
class GetMarketCap(Service):
""" 根据公司股票代码返回其市场资本总额,单位是 10 亿 USD。
{1}
"""
class SimpleIO:
response_elem = 'market_cap'
input_required = ('symbol',)
output_required = ('provider', 'value')
def handle(self):
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# Yahoo
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# 通过名称获取到 Y! 的连接
yahoo = self.outgoing.plain_http.get('Yahoo! YQL')
# 创建用于 YQL 查询的 URL 参数。
q = 'select * from yahoo.finance.quotes where symbol="{}"'.format(
self.request.input.symbol)
url_params = {'q':q, 'format':'json',
'env':'http://datatables.org/alltables.env'}
# 调用 Y!,并从 JSON 响应创建一个 bunch 实例,这样就可以用点号
# 引用这些元素。
yahoo_response = bunchify(loads(yahoo.conn.get(self.cid, url_params).text))
# 清理 Y! 的响应——如果有业务响应,就去掉最后一个字符。
# 假设响应总是以 10 亿为单位。
if yahoo_response.query.results.quote:
value1 = yahoo_response.query.results.quote.MarketCapitalization
value1 = Decimal(value1[:-1]) if value1 else 'n/a'
else:
value1 = 'n/a'
# 一个新的响应条目会附加到条目列表,根据服务调用方式的不同,
#Zato 会把它序列化为 JSON 或者 XML。
item1 = {'provider':'Yahoo!', 'value': str(value1)}
self.response.payload.append(item1)
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# Google
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# 通过名称获取到 Google 的连接
google = self.outgoing.plain_http.get('Google Finance')
# 创建用于调用 Google 的 URL 参数
url_params = {'stock':self.request.input.symbol}
# 调用 Google 并从 XML 响应创建一个 Objectify 实例,这样就可以
# 用点号引用这些元素。
google_response = fromstring(google.conn.get(self.cid,
url_params).text)
# 清理 Google 的响应——如果有业务响应,就将百万转换成十亿。
if hasattr(google_response.finance, 'market_cap'):
value2 = Decimal(google_response.finance.market_cap.get('data')) / 1000
else:
value2 = 'n/a'
# 此外,将一个纯 Python 字典 (hashmap) 附加到响应对象,并由 Zato
# 完成序列化
item2 = {'provider':'Google', 'value': str(value2)}
self.response.payload.append(item2)

这是一个非常简单的集成示例,而并不是所有的场景都允许使用 SIO,但是不管服务多复杂,有一点需要强调,就是不应该回避使用 Python 进行编码。除了可执行外,从许多方面看来,它都非常像伪代码——这里更多使用示例可以说明这一点

事实上,这正是使用 Python 创建 Zato 的原因——作为一种十分高级的语言,Python 非常令人满意,它尽可能的减少麻烦和语言怪癖,使开发人员可以专注于集成。同时,它还是一种真正通用的编程语言,而不是一种有局限性、可能图形化和领域专属的第四代语言。

回到上面的例子,可以使用 GUI 创建需要的资源——本例中是“Yahoo!YQL”和“Google 财经”的传出连接。也可以从命令行使用 JSON 配置完成上述操作,但还是会显示图形界面。

这些独有的 API 不需要安全性保证,但是如果需要,则可以使用“HTTP 基础认证(HTTP Basic Auth)”、“WS-Security 用户名令牌(WS-Security Username Tokens)”或者技术账户(与 HTTP 基础认证类似,但是不需要 BASE64)。

现在,服务可以通过 GUI 或者命令行进行热部署了。此处使用后者:

复制代码
$ cp stockmarket.py /opt/server1/pickup-dir

确认信息会写到服务器日志:

复制代码
2013-06-20 19:25:16,115 - INFO - Uploaded package id:[53],
payload_name:[stockmarket.py]

接下来,可以使用 Zato 的 CLI 从命令行调用它,也可以从 GUI 调用它。这里采用前一种方法,并使用 JSON 和纯 HTML 两种格式:

复制代码
$ zato service invoke /opt/server1 stockmarket.get-market-cap \
--payload '{"symbol":"GOOG"}'
{u'market_cap': [
{u'value': u'298.8', u'provider': u'Yahoo!'},
{u'value': u'298.81505', u'provider': u'Google'}
]}
$
复制代码
$ zato service invoke /opt/server1/ stockmarket.get-market-cap --data-format
xml \
--transport soap --payload '\
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" \
xmlns:zato="https://zato.io/ns/20130518"> \
<soapenv:Body> \
<zato:request> \
<zato:symbol>IBM</zato:symbol> \
</zato:request> \
</soapenv:Body> \
</soapenv:Envelope>'
<market_cap>
<zato_env>
<cid>K255124128065587321859442392853212603320</cid>
<result>ZATO_OK</result>
</zato_env>
<item_list>
<item>
<provider>Yahoo!</provider>
<value>8.763</value>
</item>
<item>
<provider>Google</provider>
<value>8.76324</value>
</item>
</item_list>
</market_cap>
$

CLI 只是一种管理员或者开发人员快速访问服务的方式,而实际上,服务现在已经加载到一个安全的 HTTP 通道上,客户端应用程序可以通过该通道访问服务。服务器不需要重启。

Zato 1.1 其它特性速览

服务

服务使用 Python 编写,但如果需要,也可以使用 C 或 C++ 创建服务。

服务已从传输层解耦,因此,除非开发人员坚持深入研究底层细节,否则他们可以专注于数据校验、扩展、转换、路由或者调用其它服务。服务管理可以使用基于浏览器的 GUI、CLI 或者 JSON 配置。

Zato 还将服务与安全机制隔离——服务遵循这样的假设,如果它们被调用,那么前一层已经处理了授权 / 认证。

一个服务可以同时通过多种通道暴露,每一个通道使用不同的数据格式、安全定义或传输协议。

如果使用 JSON/XML/SOAP,服务会收到一个美观的 Python 对象作为输入,程序员可以通过常规的点号访问该对象(例如,request.customer.payment.date),而不需要手动序列化 / 反序列化。如果使用 SimpleIO(SIO),不管使用哪种数据格式,都会产生相同的对象,所以相同的服务可以通过多种通道暴露给客户端应用程序,并且每种通道都可以使用三种数据格式中的任意一种。

“钩子(Hook)”可以用来影响服务的生命周期,实现跨服务的代码共用(这是除 Python 类继承之外的另一种代码共用方式)。

任何同步调用都发生在同一操作系统级别的进程和线程,因此,操作系统可以捕获服务抛出的任何异常,并进行现场回溯(堆栈跟踪)。

异步调用需要通过 Redis 路由。消息首先发布到 Redis 上,另一个服务——可能在另一台服务器上——取得该请求。这也是调度器的工作原理,作业(服务)运行请求发布到 Redis 上,目标服务接收该请求作为输入。

有一点需要注意,所有围绕数据来源、格式和传输协议的抽象编程仅仅是为开发人员提供方便。例如,如果有一个需求,需要实现一个 Zato 自身没有提供的功能,那么开发人员总是可以直接访问原始的字节 / 字符串消息。

在活动集群上所做的几乎所有操作,如部署或重新配置,都不需要重启服务器和中断消息流。

GUI

GUI 是在 Django 中使用手写 HTML/CSS/jQuery 的方式编写而成。开发过程遵循诸如 Stephen Few 那样的信息设计和可用性专家所制定的指南。

它有如下主要特征:

  • 集群管理——包含指向关键组件的快速链接,具有向负载均衡器的配置中添加 / 删除服务器,及以服务器和负载均衡器的视角检查服务器是否运行正常的能力

  • 负载均衡器——包含用于更改负载均衡器基础数据的 GUI 和 HAProxy 的配置源代码视图,也可以通过它远程执行 HAProxy 命令及访问统计信息

  • 服务

    • 服务热部署
    • 服务以及请求频率、平均响应时间等基本统计信息列表(也有图表)
    • 查看特定服务的信息,包括服务的暴露通道、所在服务器和服务的基本统计信息
    • 可以从浏览器运行服务的服务调用程序
    • 具有语法高亮显示功能的源代码浏览器,可用于查看服务器上到底安装了什么(因为服务以源代码的形式部署,所以总是可以取得源代码,字节码是在部署过程中生成的)
    • 上传 / 下载 WSDL 文件(虽然 Zato 自身并不用它来验证请求),并使它可以通过公共的 URL 访问
    • 存储和访问请求 / 响应抽样信息(每 N 次请求进行一次抽样)
    • 存储和访问速度慢的请求 / 响应信息(超过设定阀值)
  • 安全——增加和删除安全定义,这些定义可以在通道和传出连接之间重用

  • 通道和传出连接——前者包括 AMQP JMS WebSphere MQ plain HTTP SOAP ZeroMQ ,后者包括 AMQP FTP JMS WebSphere MQ plain HTTP SOAP SQL ZeroMQ 。创建这些类的新对象或者更新已有对象,几乎从不需要重启和编码。

  • Redis NoSQL——一个用于远程执行 Redis 命令的 GUI。同时,它还具有指定数据字典及映射的能力。所谓映射是要表达这样一种对照关系,例如,在 ISO 4217 字符集中美元符号是 USD,但是它的数字码是 840。

  • 用于创建、更新或者手动执行作业的调度器。运行一个作业意味着执行一项服务,并且可以为该服务选择一个静态有效负载作为输入。

  • 在 GUI 中有用颜色标记集群的选项,例如,生产总是蓝色,测试总是绿色及开发总是灰色,这样可以避免“胖手指”综合征。

  • 可用于快速回答下面两个问题的统计信息——哪个服务最慢和哪个服务在给定时间范围内(小时 / 天 / 月 / 年或者任意一个时间段)使用最多。用户可以在浏览器中比较这些数据,也可以导出成 CVS 格式的文件(还可以通过 API 获取)。负载均衡器也会提供它自己的运行时统计信息。

CLI

命令行接口可以用于执行一系列管理操作,包括创建集群组件、对组件进行完整性检查、启动、停止或更新组件或管理加密资料。

下文会对两个命令进行说明。第一个针对正在运行的组件取得其操作系统级的信息。另一个用于创建完整的工作环境,该环境将包含两个服务器、Web 管理界面和一个负载均衡器,每个组件均使用随机产生的加密资料,所有的组件都已经完成配置和设置工作。

复制代码
$ zato info /opt/z1/load-balancer
+--------------------------------+--------------------------------+
| Key | Value |
+=========================+================+
| component_details | {"created_user_host": |
| | "dev1@box1", "version": |
| | "1.1", "component": |
| | "LOAD_BALANCER", "created_ts": |
| | "2013-06-19T14:55:42.027946"} |
+--------------------------------+--------------------------------+
| component_full_path | /opt/z1/load-balancer |
+--------------------------------+--------------------------------+
| component_host | box1/box1 |
+--------------------------------+--------------------------------+
| component_running | True |
+--------------------------------+--------------------------------+
| current_time | 2013-06-20T15:05:12.078273 |
+--------------------------------+--------------------------------+
| current_time_utc | 2013-06-20T13:05:12.078289 |
+--------------------------------+--------------------------------+
| master_proc_connections | [connection(fd=4, family=2, |
| | type=1, |
| | local_address=('127.0.0.1', |
| | 20151), remote_address=(), |
| | status='LISTEN')] |
+--------------------------------+--------------------------------+
| master_proc_create_time | 2013-06-20T13:04:15.440000 |
+--------------------------------+--------------------------------+
| master_proc_create_time_utc | 2013-06-20T11:04:15.440000+00: |
| | 00 |
+--------------------------------+--------------------------------+
| master_proc_name | python |
+--------------------------------+--------------------------------+
| master_proc_pid | 10793 |
+--------------------------------+--------------------------------+
| master_proc_username | dev1 |
+--------------------------------+--------------------------------+
| master_proc_workers_no | 0 |
+--------------------------------+--------------------------------+
| master_proc_workers_pids | [] |
+--------------------------------+--------------------------------+
$
{1}
复制代码
zato quickstart create /opt/qs-1 postgresql localhost 5432 zato1 zato1
localhost 6379
ODB database password (will not be echoed):
Enter the odb_password again (will not be echoed):
Key/value database password (will not be echoed):
Enter the kvdb_password again (will not be echoed):
[1/8] Certificate authority created
[2/8] ODB schema created
[3/8] ODB initial data created
[4/8] server1 created
[5/8] server2 created
[6/8] Load-balancer created
Superuser created successfully.
[7/8] Web admin created
[8/8] Management scripts created
Quickstart cluster quickstart-309837 created
Web admin user:[admin], password:[hita-yabe-yenb-ounm]
Start the cluster by issuing the /opt/qs-1/zato-qs-start.sh command
Visit https://zato.io/support for more information and support options
$

API

Zato 自带的管理服务有文档说明。客户端应用程序可以通过 JSON 或 SOAP 方式调用这些服务,为开发人员或管理员创建可供选择的工具或 GUI。实际上,Zato 提供的基于 Django 的 Web 管理界面就是这样的应用程序——所有的操作都是通过 API 执行,Web 控制台从不直接访问任何配置数据存储区。

总结

Zato 1.1 是个轻量级但完整的 ESB 应用服务器,已经可以用于很多任务。随着时间的推移,会加入更多的功能。具体而言,除了会在工具和 GUI 方面增加一组新内容外,接下来的几个版本将重点提供开箱即用的业务 API,用于连接具体的系统或应用程序。同时,还将为开发人员提供一个开发工具包,使他们可以创建自己的 API。在编写和支持其它集成模式方面,也会完成更多的工作。

关于作者

Dariusz Suchojad有 12 年的企业级架构和软件工程经验,其中 8 年在电信和银行领域从事 EAI/ESB/SOA/BPM/SSO 方面的工作。在剖析专用协议、系统集成开发和洽谈业务等三个方面,以及介于这三者之间的任何方面,他都同样出色。然而,每天不得不使用的低劣解决方案致使他花了太多的夜晚来灭火。于是,他辞掉工作,并在两年间用 16 个月的时间创建了 Zato ——一个基于 Python 的集成和后端服务器平台。

查看英文原文: Zato - Python-based ESB and Backend Application Server

2013-09-27 00:4111843
用户头像

发布了 256 篇内容, 共 86.3 次阅读, 收获喜欢 12 次。

关注

评论

发布
暂无评论
发现更多内容

WorkPlus移动应用平台集成单点登录,实现统一门户解决方案

WorkPlus

企业内部通讯软件—WorkPlus适配信创即时通讯软件

WorkPlus

移动应用平台—WorkPlus企业级移动应用平台解决方案

WorkPlus

多功能文档编辑工具Author for Mac v9.2版

Mac相关知识分享

Mac 软件 #Mac

硬盘健康检查预警软件Drive Scope for mac v2.0.1版

Mac相关知识分享

Mac 软件 #Mac

浅析MySQL 8.0直方图原理

华为云开发者联盟

MySQL 数据库 华为云 华为云开发者联盟 企业号2024年5月PK榜

未来科技潮流:区块链、物联网与虚拟现实的融合与创新

区块链开发团队DappNetWork

即时通讯平台是什么?

WorkPlus

记录线上数据库飙升到60的性能优化

奔跑吧!

性能优化 后端 二级缓存 架构优化 Java线上优化经验

Linux设备驱动系列(13) —— 系统中断编程

Linux内核拾遗

Linux内核 中断 设备驱动

内网通讯软件–WorkPlus私有化内网通讯软件解决方案

WorkPlus

代码的安全检视

Tom(⊙o⊙)

Intel HDSLB 高性能四层负载均衡器 — 基本原理和部署配置

云物互联

嘿,同学,你要的 Java 内存模型 (JMM) 来了

冰羽

解读注意力机制原理,教你使用Python实现深度学习模型

华为云开发者联盟

Python 人工智能 华为云 华为云开发者联盟 企业号2024年5月PK榜

即时通讯平台—WorkPlus私有化企业内部通讯软件

WorkPlus

Java语言开发集成环境 IntelliJ IDEA 2024 for Mac v2024.1.2版

Mac相关知识分享

Mac 软件 java #Mac

什么是Token?为什么大模型要计算Token数

华为云开发者联盟

人工智能 华为云 大模型 华为云开发者联盟 企业号2024年5月PK榜

低代码与人工智能:改变软件开发的未来

天津汇柏科技有限公司

低代码 低代码平台 人工智能’

区块链Polygon:以太坊的扩展先锋

dappweb

区块链技术

Zato——基于Python的ESB和后端应用服务器_Python_Dariusz Suchojad_InfoQ精选文章