遇见Marathon:打造大规模容器生产环境

dataman 发表了文章 • 0 个评论 • 825 次浏览 • 2016-02-24 17:23 • 来自相关话题

小数点分享:Marathon 视为数据中心操作系统(简称DCOS)中的一款“杀手级应用”。它属于核心服务之一,被预装在 DCOS 当中,而且目前已经被三星、Yelp、Verizon、迪士尼、Autodesk 以及其它众多知名厂商应用于生产环境当中。这些企业利用 Marathon 立足于公有云环境、内部数据中心乃至跨越多混合云环境管理着成百上千节点之上的大量容器。Marathon 支撑着一切基于容器应用程序的部署工作,从持续集成到物联网再到托管云服务可谓无所不包。
 
容器技术如今可谓如日中天,不少从业者甚至预测认为容器的广泛普及将给 IT 行业带来超越云计算的深远变革。相较于此前专门用于改进运营及开发效率的各类技术方案,容器技术能够真正提供极为出色的资源利用率、易配置性、更高部署速度以及更加灵活的开发流程。

不过如同单一虚拟机一样,单一容器本身并不足以承担如此重任。这意味着我们需要一套容器编排平台以部署并管理特定数量的容器系统。举例来说,一款采用微服务架构的现代应用程序可能包含有数十甚至上百套容器系统,这些容器跨越数十个物理节点以及彼此依存的容器化服务。在将大量组件与一套持续集成与交付系统相集成后,我们还需要一套集群作为其运行载体,并在日常代码测试工作当中每天启动并移除数百万的容器实例。

如果没有理想的容器编排平台作为辅助,那么实现这项目标绝对是一条漫长而艰难的道路。当然,随着容器数量的不断攀升,整套体系对于可扩展能力与传输带宽的要求也将随之增长。而且与 IT 结构中的其它事物一样,容器当中也存在着许多值得关注的核心要素,我们需要利用它们完成技术方案由开发到生产的整个推进流程。

希望在生产环境下运行容器的企业用户需要对大量炒作与夸张说辞进行分析,从而找到真正适合自己且值得信赖的容器业务流程平台。就目前而言,已经有一部分技术成果建立起庞大的开发者基础并以 GitHub 为平台进行传播。另一些成果则已经开始运行在生产环境当中,并被一部分全球规模最大的企业与极具创新能力的初创厂商用于支持下一代应用程序。我们的开源 Marathon 技术恰好属于后一种分类。







遇见 Marathon

我们将Marathon视为数据中心操作系统(简称DCOS)中的一款“杀手级应用”。它属于核心服务之一,被预装在 DCOS 当中,而且目前已经被三星、Yelp、Verizon、迪士尼、Autodesk 以及其它众多知名厂商应用于生产环境当中。这些企业利用 Marathon 立足于公有云环境、内部数据中心乃至跨越多混合云环境管理成百上千节点之上的大量容器。Marathon 支撑着一切基于容器应用程序的部署工作,从持续集成到物联网再到托管云服务可谓无所不包。

各家企业利用 Marathon 管理自身容器环境的具体方式也有所区别:
 
三星公司利用 Marathon 支撑其 SAMI 联网设备平台的开发经验。Autodesk 公司利用 Marathon 为其持续增长的云服务套件建立一套流事件平台。Yelp 公司以 Marathon 为核心构建起了自己的一套完整生产性平台即服务(简称PaaS)环境。在该平台(简称为PaaSTA)与另一名为Seagull 的基于 Marathon 项目之间,Yelp 公司得以每天启动超过100万套 Docker 容器。

Marathon 以云为目标进行构建

最近推出的一系列强化也使得云服务供应商得以利用Marathon交付自己的交钥匙容器服务。举例来说,我们目前正与微软公司就其Azure Container Service(简称ACS)开展协作,其利用 Marathon 交付生产就绪型容器编排方案。Azure Container Service 在2015年9月发布的一篇官方博文当中提到:Azure Container Service 的默认配置包含 “Marathon、Chronos 以及Apache Mesos,旨在确保这些应用能够被扩展至数千甚至数万容器系统级别。”

目前,微软公司发布了 ACS 的公共预览版,这意味着任何 Azure 用户都能够访问该服务并将其与 Mesos 及 Marathon 一道纳入自身业务流程。希望直接在 Azure 实例或者其它云平台之上部署 DCOS 的企业客户也已经能够切实达成目标。

Marathon 为 DCOS 提供支持

不过着眼于 Marathon,其最大的亮点可能正是其与 DCOS 的结合。尽管容器编排已经成为一项愈发重要的能力,但其还仅仅是推动现代应用程序更加强大、更具可扩展能力且更为可靠道路上的一个侧面。有鉴于此,DCOS也做出相应调整以简化对高复杂性系统的安装、规模伸缩与管理,具体包括分布式数据库、大数据流水线以及持续集成平台等等——这一切都将同消费级 Web 应用程序与微服务一道运行在一套共享式集群之上。

伴随着每个新的DCOS版本,我们都会在其中围绕安全性、弹性、监控能力、管理能力以及其它要素添加新的能力。







Marathon 在行动

正如之前所提到,Marathon 帮助用户克服了一系列以可靠及可扩展方式开发并运营容器化工作负载时所出现的严峻挑战。对于初学者,Marathon 能够轻松利用自动化流程完成很多以往只能以手动形式解决的问题。富 Web UI 允许用户更便捷地启动并监控任何 Docker 镜像,同时对正处于运行当中的应用程序进行配置更新。

不过 Marathon 的适用范围并不局限于 Docker。事实上,它能够承载几乎任何现有应用程序,例如基于 JVM 的应用、Ruby 脚本或者简单的Bsh shell 脚本。这能够切实帮助用户完成从传统架构到全面容器化工作负载的过渡。(传统应用多数能够通过运行在向外扩展平台内商用硬件之上获得收益。)

在典型设置当中,DevOps 人员需要以脚本化模式使用 REST API,从而将存在依赖性的多款应用乃至应用群组作为单一单元进行启动。考虑到Marathon 利用 Apache Mesos 在设备集群当中启动应用程序,因此其必须能够以自动化方式实现各集群节点对接并将负载扩散至某应用程序的多个实例当中。Marathon 能够直接完成这两项任务,同时利用 Mesos-DNS 实现服务发现、通过 Marathon-lb 实现负载均衡。

Marathon 的其它重要特性还包括:
 
支持零停机时间部署,包括滚动部署、蓝绿部署与金丝雀部署模式。基于 HTTP、TCP 以及命令之应用程序运行状态检查。指标发送与收集集成(包括 Graphite、DataDog 以及StatsD)。具备一套强大的事件总线,使得 DevOps 人员以编程化方式通过定制化模式实现应用程序变更响应。具备用于应对网络与节点故障的弹性,且同时适用于 Marathon 本身及其管理的应用程序。包括用户认证以及基于角色访问控制在内的多种安全功能。采用一套灵活的插件架构,使得插件能够被定制化集成至现有企业IT环境当中。

特别值得强调的是,Marathon 能够轻松实现容器实例规模扩展。在去年8月召开的 MesosCon 大会上,DCOS 客户 Verizon 在现场做出了演示,其中 Marathon 在一分钟之内成功启动了5万套 Docker 容器系统。

正因为如此,当我们谈及将 DCOS 引入企业级生产环境并针对庞大规模Docker 容器作为可扩展管理选项时,我们对其能力充满信心。







Marathon 还将迎来更多值得期待的发展

之前说了这么多,介绍的主要是 Marathon 技术团队过去几年内通过辛勤努力实现的平台可靠性与功能集改进。展望未来,Marathon团队已经制定出极具野心的发展路线图——包括即将实现的数据库等状态化应用程序支持能力——旨在确保Marathon项目能够继续成为企业将容器化战略引入生产环境时的首选平台。

原文链接: MEET MARATHON: PRODUCTION-READY CONTAINER ORCHESTRATION AT SCALE 查看全部
小数点分享:Marathon 视为数据中心操作系统(简称DCOS)中的一款“杀手级应用”。它属于核心服务之一,被预装在 DCOS 当中,而且目前已经被三星、Yelp、Verizon、迪士尼、Autodesk 以及其它众多知名厂商应用于生产环境当中。这些企业利用 Marathon 立足于公有云环境、内部数据中心乃至跨越多混合云环境管理着成百上千节点之上的大量容器。Marathon 支撑着一切基于容器应用程序的部署工作,从持续集成到物联网再到托管云服务可谓无所不包。
 
容器技术如今可谓如日中天,不少从业者甚至预测认为容器的广泛普及将给 IT 行业带来超越云计算的深远变革。相较于此前专门用于改进运营及开发效率的各类技术方案,容器技术能够真正提供极为出色的资源利用率、易配置性、更高部署速度以及更加灵活的开发流程。

不过如同单一虚拟机一样,单一容器本身并不足以承担如此重任。这意味着我们需要一套容器编排平台以部署并管理特定数量的容器系统。举例来说,一款采用微服务架构的现代应用程序可能包含有数十甚至上百套容器系统,这些容器跨越数十个物理节点以及彼此依存的容器化服务。在将大量组件与一套持续集成与交付系统相集成后,我们还需要一套集群作为其运行载体,并在日常代码测试工作当中每天启动并移除数百万的容器实例。

如果没有理想的容器编排平台作为辅助,那么实现这项目标绝对是一条漫长而艰难的道路。当然,随着容器数量的不断攀升,整套体系对于可扩展能力与传输带宽的要求也将随之增长。而且与 IT 结构中的其它事物一样,容器当中也存在着许多值得关注的核心要素,我们需要利用它们完成技术方案由开发到生产的整个推进流程。

希望在生产环境下运行容器的企业用户需要对大量炒作与夸张说辞进行分析,从而找到真正适合自己且值得信赖的容器业务流程平台。就目前而言,已经有一部分技术成果建立起庞大的开发者基础并以 GitHub 为平台进行传播。另一些成果则已经开始运行在生产环境当中,并被一部分全球规模最大的企业与极具创新能力的初创厂商用于支持下一代应用程序。我们的开源 Marathon 技术恰好属于后一种分类。

20160224-marathon.jpg



遇见 Marathon

我们将Marathon视为数据中心操作系统(简称DCOS)中的一款“杀手级应用”。它属于核心服务之一,被预装在 DCOS 当中,而且目前已经被三星、Yelp、Verizon、迪士尼、Autodesk 以及其它众多知名厂商应用于生产环境当中。这些企业利用 Marathon 立足于公有云环境、内部数据中心乃至跨越多混合云环境管理成百上千节点之上的大量容器。Marathon 支撑着一切基于容器应用程序的部署工作,从持续集成到物联网再到托管云服务可谓无所不包。

各家企业利用 Marathon 管理自身容器环境的具体方式也有所区别:
 
  • 三星公司利用 Marathon 支撑其 SAMI 联网设备平台的开发经验
  • Autodesk 公司利用 Marathon 为其持续增长的云服务套件建立一套流事件平台。
  • Yelp 公司以 Marathon 为核心构建起了自己的一套完整生产性平台即服务(简称PaaS)环境。在该平台(简称为PaaSTA)与另一名为Seagull 的基于 Marathon 项目之间,Yelp 公司得以每天启动超过100万套 Docker 容器。


Marathon 以云为目标进行构建

最近推出的一系列强化也使得云服务供应商得以利用Marathon交付自己的交钥匙容器服务。举例来说,我们目前正与微软公司就其Azure Container Service(简称ACS)开展协作,其利用 Marathon 交付生产就绪型容器编排方案。Azure Container Service 在2015年9月发布的一篇官方博文当中提到:Azure Container Service 的默认配置包含 “Marathon、Chronos 以及Apache Mesos,旨在确保这些应用能够被扩展至数千甚至数万容器系统级别。”

目前,微软公司发布了 ACS 的公共预览版,这意味着任何 Azure 用户都能够访问该服务并将其与 Mesos 及 Marathon 一道纳入自身业务流程。希望直接在 Azure 实例或者其它云平台之上部署 DCOS 的企业客户也已经能够切实达成目标。

Marathon 为 DCOS 提供支持

不过着眼于 Marathon,其最大的亮点可能正是其与 DCOS 的结合。尽管容器编排已经成为一项愈发重要的能力,但其还仅仅是推动现代应用程序更加强大、更具可扩展能力且更为可靠道路上的一个侧面。有鉴于此,DCOS也做出相应调整以简化对高复杂性系统的安装、规模伸缩与管理,具体包括分布式数据库、大数据流水线以及持续集成平台等等——这一切都将同消费级 Web 应用程序与微服务一道运行在一套共享式集群之上。

伴随着每个新的DCOS版本,我们都会在其中围绕安全性、弹性、监控能力、管理能力以及其它要素添加新的能力。

20160224-dcos.jpg



Marathon 在行动

正如之前所提到,Marathon 帮助用户克服了一系列以可靠及可扩展方式开发并运营容器化工作负载时所出现的严峻挑战。对于初学者,Marathon 能够轻松利用自动化流程完成很多以往只能以手动形式解决的问题。富 Web UI 允许用户更便捷地启动并监控任何 Docker 镜像,同时对正处于运行当中的应用程序进行配置更新。

不过 Marathon 的适用范围并不局限于 Docker。事实上,它能够承载几乎任何现有应用程序,例如基于 JVM 的应用、Ruby 脚本或者简单的Bsh shell 脚本。这能够切实帮助用户完成从传统架构到全面容器化工作负载的过渡。(传统应用多数能够通过运行在向外扩展平台内商用硬件之上获得收益。)

在典型设置当中,DevOps 人员需要以脚本化模式使用 REST API,从而将存在依赖性的多款应用乃至应用群组作为单一单元进行启动。考虑到Marathon 利用 Apache Mesos 在设备集群当中启动应用程序,因此其必须能够以自动化方式实现各集群节点对接并将负载扩散至某应用程序的多个实例当中。Marathon 能够直接完成这两项任务,同时利用 Mesos-DNS 实现服务发现、通过 Marathon-lb 实现负载均衡。

Marathon 的其它重要特性还包括:
 
  • 支持零停机时间部署,包括滚动部署、蓝绿部署与金丝雀部署模式。
  • 基于 HTTP、TCP 以及命令之应用程序运行状态检查。
  • 指标发送与收集集成(包括 Graphite、DataDog 以及StatsD)。
  • 具备一套强大的事件总线,使得 DevOps 人员以编程化方式通过定制化模式实现应用程序变更响应。
  • 具备用于应对网络与节点故障的弹性,且同时适用于 Marathon 本身及其管理的应用程序。
  • 包括用户认证以及基于角色访问控制在内的多种安全功能。
  • 采用一套灵活的插件架构,使得插件能够被定制化集成至现有企业IT环境当中。


特别值得强调的是,Marathon 能够轻松实现容器实例规模扩展。在去年8月召开的 MesosCon 大会上,DCOS 客户 Verizon 在现场做出了演示,其中 Marathon 在一分钟之内成功启动了5万套 Docker 容器系统。

正因为如此,当我们谈及将 DCOS 引入企业级生产环境并针对庞大规模Docker 容器作为可扩展管理选项时,我们对其能力充满信心。

20160224-demo.jpg



Marathon 还将迎来更多值得期待的发展

之前说了这么多,介绍的主要是 Marathon 技术团队过去几年内通过辛勤努力实现的平台可靠性与功能集改进。展望未来,Marathon团队已经制定出极具野心的发展路线图——包括即将实现的数据库等状态化应用程序支持能力——旨在确保Marathon项目能够继续成为企业将容器化战略引入生产环境时的首选平台。

原文链接: MEET MARATHON: PRODUCTION-READY CONTAINER ORCHESTRATION AT SCALE

容器圈 | 基于 DCOS 的微软 Azure 容器服务正式发布

laura 发表了文章 • 0 个评论 • 533 次浏览 • 2016-02-23 18:13 • 来自相关话题

小数点分享:开源技术 Docker 的轻量化、敏捷性以及可移植性的优点,使其在全球IT领域广受瞩目,并将在 2016 年迎来全面爆发。微软对于 Mesos 的支持,我们期待未来 Windows 生态环境也能被纳入 Mesos+Docker 的范畴。近日,微软对外发布了 Azure 容器服务公共预览版。这意味着所有 Azure 用户都可以在一个生产级环境中尝试微服务和大规模容器部署服务。
同时,Mesosphere 和微软在 Azure 容器服务(ACS)方面进行了广泛技术合作。微软 Azure 的容器编排系统就是基于 Mesosphere DCOS。
Mesosphere 重点的 Apache Mesos 和 Marathon 两项开源技术将微软的 ACS 与其他云容器服务提供商区分开来。与其他技术不同,Mesos 和 Marathon 已经在众多世界级公司的大规模生产环境中成功部署实施。这两项技术与企业级云服务 Azure 结合,可为客户提供一个久经考验的高弹性生产级容器编排平台。

Marathon:DCOS 的杀手级应用

Marathon 是 一个开源容器编排引擎。可与 Mesos 原生集成,也是 DCOS 的重要基础组件之一。通过 Marathon 可以很方便的部署和管理 Docker 应用、容器化的微服务架构应用、以及 Java,Rails 这样的传统服务应用。此外,Marathon 还可以实现上万规模的快速扩容,并保证服务的高可用。

Marathon 是目前最成熟的容器编排引擎,微软正是看中了这点才选择了与 Mesosphere合作。 有大量的企业在生产环境中使用 Marathon,从持续集成/持续交付(CI/CD)环境到自建的 PaaS 平台等多种使用场景均有所涉及。以下是一些使用 Marathon 来管理大规模 Docker 生产环境的用户:

三星、Yelp、Verizon、Autodesk、Disney、Bloomberg、Mattermark、Orbitz

为新应用而生的新基础架构

基于容器技术的 Azure 容器服务和 DCOS 都倡导一种的新的应用开发和部署形式。就像我们之前所说,这是一种新形式的应用。这些应用普遍是基于分布式环境的,由众多微服务组成,有的甚至包含数千个 需要自动化管理的动态模块。通过使用 DCOS 和 Azure 容器服务这样的平台,企业就可以快速采用这种全新的应用开发和部署形式,从而在 21 世纪继续保持竞争优势,而不用头疼的去思考"Next big things"的问题。

所以说,这不仅仅是让开发者更容易地使用容器,而是让更灵活更弹性的微服务架构成为可能。这不仅仅是让容器和云计算更有效地使用计算资源,而是让企业可以快速扩展大流量数据的 IoT 应用,而不是被有限资源或传统采购流程所束缚。

DCOS 的设计初衷就是为了让微服务和分布式大数据系统这样的现代应用组件变得更容易部署、运行和管理。创建一个共享和可扩展的资源池,让运维人员和开发者不用再考虑底层上千台的服务器,而是把整个集群当成一台巨大的逻辑服务器来使用。

除 此之外,Mesosphere 和微软之前还有很多技术合作。如:统一管理 Azure 和本地数据中心组成的混合云,在 Windows 上运行 Apache Mesos 等。我们都希望达到一个目标:让客户可以自由的选择他们所需要的基础设施、架构和工具,从而可以做出满足不同需求的各种类型的应用。

原文链接:https://mesosphere.com/blog/2016/02/17/azure-container-service-dcos-mesosphere/ 查看全部

小数点分享:开源技术 Docker 的轻量化、敏捷性以及可移植性的优点,使其在全球IT领域广受瞩目,并将在 2016 年迎来全面爆发。微软对于 Mesos 的支持,我们期待未来 Windows 生态环境也能被纳入 Mesos+Docker 的范畴。近日,微软对外发布了 Azure 容器服务公共预览版。这意味着所有 Azure 用户都可以在一个生产级环境中尝试微服务和大规模容器部署服务。
同时,Mesosphere 和微软在 Azure 容器服务(ACS)方面进行了广泛技术合作。微软 Azure 的容器编排系统就是基于 Mesosphere DCOS。


Mesosphere 重点的 Apache Mesos 和 Marathon 两项开源技术将微软的 ACS 与其他云容器服务提供商区分开来。与其他技术不同,Mesos 和 Marathon 已经在众多世界级公司的大规模生产环境中成功部署实施。这两项技术与企业级云服务 Azure 结合,可为客户提供一个久经考验的高弹性生产级容器编排平台。

Marathon:DCOS 的杀手级应用

Marathon 是 一个开源容器编排引擎。可与 Mesos 原生集成,也是 DCOS 的重要基础组件之一。通过 Marathon 可以很方便的部署和管理 Docker 应用、容器化的微服务架构应用、以及 Java,Rails 这样的传统服务应用。此外,Marathon 还可以实现上万规模的快速扩容,并保证服务的高可用。

Marathon 是目前最成熟的容器编排引擎,微软正是看中了这点才选择了与 Mesosphere合作。 有大量的企业在生产环境中使用 Marathon,从持续集成/持续交付(CI/CD)环境到自建的 PaaS 平台等多种使用场景均有所涉及。以下是一些使用 Marathon 来管理大规模 Docker 生产环境的用户:

三星、Yelp、Verizon、Autodesk、Disney、Bloomberg、Mattermark、Orbitz

为新应用而生的新基础架构

基于容器技术的 Azure 容器服务和 DCOS 都倡导一种的新的应用开发和部署形式。就像我们之前所说,这是一种新形式的应用。这些应用普遍是基于分布式环境的,由众多微服务组成,有的甚至包含数千个 需要自动化管理的动态模块。通过使用 DCOS 和 Azure 容器服务这样的平台,企业就可以快速采用这种全新的应用开发和部署形式,从而在 21 世纪继续保持竞争优势,而不用头疼的去思考"Next big things"的问题。

所以说,这不仅仅是让开发者更容易地使用容器,而是让更灵活更弹性的微服务架构成为可能。这不仅仅是让容器和云计算更有效地使用计算资源,而是让企业可以快速扩展大流量数据的 IoT 应用,而不是被有限资源或传统采购流程所束缚。

DCOS 的设计初衷就是为了让微服务和分布式大数据系统这样的现代应用组件变得更容易部署、运行和管理。创建一个共享和可扩展的资源池,让运维人员和开发者不用再考虑底层上千台的服务器,而是把整个集群当成一台巨大的逻辑服务器来使用。

除 此之外,Mesosphere 和微软之前还有很多技术合作。如:统一管理 Azure 和本地数据中心组成的混合云,在 Windows 上运行 Apache Mesos 等。我们都希望达到一个目标:让客户可以自由的选择他们所需要的基础设施、架构和工具,从而可以做出满足不同需求的各种类型的应用。

原文链接:https://mesosphere.com/blog/2016/02/17/azure-container-service-dcos-mesosphere/

【干货分享】10个精选的容器应用案例

宁静胡同 发表了文章 • 0 个评论 • 685 次浏览 • 2016-02-22 17:23 • 来自相关话题

本书由十个国内外精选的容器应用案例构成,既包括了国内互联网巨头如京东、腾讯、去哪儿网等的技术实践,也有国内传统企业诸如浙江移动的DCOS实践,充分展示了Docker及相关技术在构建企业级应用的巨大优势。案例中丰富的技术细节和经验分享,具有非常高的参考和学习价值。相信随着时间的推移,容器技术将会在越来越多的企业生产环境中得到应用,全面开启云计算的新时代。

本书由InfoQ出品,数人云独家赞助,数人云CEO王璞致卷首语。


卷首语

数人云CEO 王璞

​自2013年Docker诞生以来,该技术在业界迅速掀起一股热潮。短短几年时间内,Docker生态系统迅猛发展,在企业中的应用遍地开花。Docker为企业级应用的构建、交付和运行带来了革命性的便利,它屏蔽了各种复杂的异构环境,真正做到了"Build Once, Run Anywhere",极大地降低了企业应用开发者和运维人员的工作复杂度。Docker的火热,也推动了相关技术生态的快速成长。企业的应用需求纷繁复杂,Docker不可能解决企业客户的所有需求,因此Docker相关技术层出不穷,进一步带动了Docker在企业的落地,丰富了Docker的生态圈。

比如,针对Docker的调度,就涌现出了Mesos、Kubernetes等优秀的开源项目。当企业运行成百上千个Docker应用程序的时候,靠人工来调度管理这么多的Docker程序是不现实的,企业需要对Docker程序进行自动化调度管理,而这就是Mesos和Kubernetes显身手的地方。Mesos源自加州伯克利大学的AMP实验室,是Apache旗下的顶级开源项目,其在Twitter、Airbnb、Apple等国外IT巨头已经有大规模应用,Twitter最大的Mesos集群已经有上万台服务器之多。Kubernetes源自Google,虽然诞生时间很短,仅有一两年的时间,但是因为Google巨大的影响力,Kubernetes也受到了广泛的关注和应用。

本书列举了十个Docker及Docker相关技术Mesos和Kubernetes的应用案例,充分展示了这些技术在构建企业级应用的巨大优势:一方面是这些技术在弹性计算方面的优势,诸如蘑菇街和京东案例;另一方面是这些技术在构建PaaS平台方面的优势,诸如阿里百川和SAE的案例。特别需要指出的是,Docker、Mesos和Kubernetes等技术,不仅在国外受到热捧,在国内也得到了广泛关注。本书列举的十个Docker案例,除了Apple来自美国,其它九个都是源自国内的案例。而且,这九个国内的案例,不仅有来自国内互联网巨头,更有来自浙江移动这样的传统企业,这充分显示了国内对于热点新技术的追踪和应用已经不输于国外。相信在不久的未来,国内在Docker的相关领域必将出现新的技术,超越国外同行,引领这些领域的发展方向。

目录
中国移动浙江公司数据中心操作系统(DCOS)实践蘑菇街11.11:私有云平台的Docker应用实践Apple使用Apache Mesos重建Siri后端服务阿里百川:全架构PaaS TAE 2.0的Docker实践大众点评容器云平台:运营超一年,承载大部分业务京东618:Docker扛大旗,弹性伸缩成重点腾讯游戏如何使用DockerDocker在蚂蚁金融云平台中的探索与实践Mesos在去哪儿网的实践之路基于Kubernetes打造SAE容器云




下载此书请点击链接10个精选的容器应用案例 查看全部

本书由十个国内外精选的容器应用案例构成,既包括了国内互联网巨头如京东、腾讯、去哪儿网等的技术实践,也有国内传统企业诸如浙江移动的DCOS实践,充分展示了Docker及相关技术在构建企业级应用的巨大优势。案例中丰富的技术细节和经验分享,具有非常高的参考和学习价值。相信随着时间的推移,容器技术将会在越来越多的企业生产环境中得到应用,全面开启云计算的新时代。

本书由InfoQ出品,数人云独家赞助,数人云CEO王璞致卷首语。




卷首语

数人云CEO 王璞

​自2013年Docker诞生以来,该技术在业界迅速掀起一股热潮。短短几年时间内,Docker生态系统迅猛发展,在企业中的应用遍地开花。Docker为企业级应用的构建、交付和运行带来了革命性的便利,它屏蔽了各种复杂的异构环境,真正做到了"Build Once, Run Anywhere",极大地降低了企业应用开发者和运维人员的工作复杂度。Docker的火热,也推动了相关技术生态的快速成长。企业的应用需求纷繁复杂,Docker不可能解决企业客户的所有需求,因此Docker相关技术层出不穷,进一步带动了Docker在企业的落地,丰富了Docker的生态圈。

比如,针对Docker的调度,就涌现出了Mesos、Kubernetes等优秀的开源项目。当企业运行成百上千个Docker应用程序的时候,靠人工来调度管理这么多的Docker程序是不现实的,企业需要对Docker程序进行自动化调度管理,而这就是Mesos和Kubernetes显身手的地方。Mesos源自加州伯克利大学的AMP实验室,是Apache旗下的顶级开源项目,其在Twitter、Airbnb、Apple等国外IT巨头已经有大规模应用,Twitter最大的Mesos集群已经有上万台服务器之多。Kubernetes源自Google,虽然诞生时间很短,仅有一两年的时间,但是因为Google巨大的影响力,Kubernetes也受到了广泛的关注和应用。

本书列举了十个Docker及Docker相关技术Mesos和Kubernetes的应用案例,充分展示了这些技术在构建企业级应用的巨大优势:一方面是这些技术在弹性计算方面的优势,诸如蘑菇街和京东案例;另一方面是这些技术在构建PaaS平台方面的优势,诸如阿里百川和SAE的案例。特别需要指出的是,Docker、Mesos和Kubernetes等技术,不仅在国外受到热捧,在国内也得到了广泛关注。本书列举的十个Docker案例,除了Apple来自美国,其它九个都是源自国内的案例。而且,这九个国内的案例,不仅有来自国内互联网巨头,更有来自浙江移动这样的传统企业,这充分显示了国内对于热点新技术的追踪和应用已经不输于国外。相信在不久的未来,国内在Docker的相关领域必将出现新的技术,超越国外同行,引领这些领域的发展方向。

目录
  • 中国移动浙江公司数据中心操作系统(DCOS)实践
  • 蘑菇街11.11:私有云平台的Docker应用实践
  • Apple使用Apache Mesos重建Siri后端服务
  • 阿里百川:全架构PaaS TAE 2.0的Docker实践
  • 大众点评容器云平台:运营超一年,承载大部分业务
  • 京东618:Docker扛大旗,弹性伸缩成重点
  • 腾讯游戏如何使用Docker
  • Docker在蚂蚁金融云平台中的探索与实践
  • Mesos在去哪儿网的实践之路
  • 基于Kubernetes打造SAE容器云





下载此书请点击链接10个精选的容器应用案例

数据处理平台架构中的SMACK组合:Spark、Mesos、Akka、Cassandra以及Kafka

宁静胡同 发表了文章 • 0 个评论 • 780 次浏览 • 2016-02-16 18:56 • 来自相关话题

在今天的文章中,我们将着重探讨如何利用SMACK(即Spark、Mesos、Akka、Cassandra以及Kafka)堆栈构建可扩展数据处理平台。虽然这套堆栈仅由数个简单部分组成,但其能够实现大量不同系统设计。除了纯粹的批量或者流处理机制之外,我们亦可借此实现复杂的Lambda以及Kappa架构。

基于Mesos技术的数人云可以快速部署和运行Spark、Akka、Cassandra以及Kafka,也欢迎大家在数人云上进行体验和实践,感受它们强大功能带来的便利。在本文开始阐述之前,让我们首先立足于已有生产项目经验从设计与示例入手进行说明。
 综述






Spark - 一套高速通用型引擎,用于实现分布式大规模数据处理任务。

Mesos - 集群资源管理系统,能够立足于分布式应用程序提供行之有效的资源隔离与共享能力。

Akka - 一套用于在JVM之上构建高并发、分布式及弹性消息驱动型应用程序的工具包与运行时。

Cassandra - 一套分布式高可用性数据库,旨在跨越多座数据中心处理大规模数据。

Kafka -一套高吞吐能力、低延迟、分布式消息收发系统/提交日志方案,旨在处理实时数据供给。


存储层: Cassandra








Cassandra一直以其高可用性与高吞吐能力两大特性而备受瞩目,其同时能够处理极为可观的写入负载并具备节点故障容错能力。以CAP原则为基础,Cassandra能够为业务运营提供可调整的一致性/可用性水平。


更有趣的是,Cassandra在处理数据时拥有线性可扩展能力(即可通过向集群当中添加节点的方式实现负载增容)并能够提供跨数据中心复制(简称XDCR)能力。事实上,跨数据中心复制功能除了数据复制,同时也能够实现以下各类扩展用例:
地理分布式数据中心处理面向特定区域或者客户周边位置之数据。在不同数据中心之间者数据迁移,从而实现故障后恢复或者将数据移动至新数据中心。对运营工作负载与分析工作负载加以拆分。

但上述特性也都有着自己的实现成本,而对于Cassandra而言这种成本体现为数据模型——这意味着我们需要通过聚类对分区键及入口进行分组/分类,从而实现嵌套有序映射。以下为简单示例:CREATE TABLE campaign(   id uuid,
year int,
month int,
day int,
views bigint,
clicks bigint,
PRIMARY KEY (id, year, month, day)
);

INSERT INTO campaign(id, year, month, day, views, clicks)
VALUES(40b08953-a…,2015, 9, 10, 1000, 42);

SELECT views, clicks FROM campaign
WHERE id=40b08953-a… and year=2015 and month>8;


为了获取某一范围内的特定数据,我们必须指定全键,且不允许除列表内最后一列之外的其它任何范围划定得以执行。这种限制用于针对不同范围进行多重扫描限定,否则其可能带来随机磁盘访问并拖慢整体性能表现。这意味着该数据模型必须根据读取查询进行认真设计,从而限制读取/扫描量——但这同时也会导致对新查询的支持灵活性有所下降。

那么如果我们需要将某些表加入到其它表当中,又该如何处理?让我们考虑下一种场景:针对特定月份对全部活动进行总体访问量计算。CREATE TABLE event(
id uuid,
ad_id uuid,
campaign uuid,
ts bigint,
type text,
PRIMARY KEY(id)
);
在特定模型之下,实现这一目标的惟一办法就是读取全部活动、读取全部事件、汇总各属性值(其与活动id相匹配)并将其分配给活动。实现这类应用程序操作显然极具挑战,因为保存在Casandra中的数据总量往往非常庞大,内存容量根本不足以加以容纳。因此我们必须以分布式方式对此类数据加以处理,而Spark在这类用例中将发挥重要作用。

处理层: Spark







Spark的抽象核心主要涉及RDD(即弹性分布式数据集,一套分布式元素集合)以及由以下四个主要阶段构成的工作流:
 
RDD操作(转换与操作)以DAG(即有向无环图)形式进行DAG会根据各任务阶段进行拆分,并随后被提交至集群管理器各阶段无需混洗/重新分配即可与任务相结合任务运行在工作程序之上,而结果随后返回至客户端


以下为我们如何利用Spark与Cassandra解决上述问题:val sc = new SparkContext(conf)

case class Event(id: UUID, ad_id: UUID, campaign: UUID, ts: Long, `type`: String)

sc.cassandraTable[Event]("keyspace", "event")
.filter(e => e.`type` == "view" && checkMonth(e.ts))
.map(e => (e.campaign, 1))
.reduceByKey(_ + _)
.collect()指向Cassandra的交互通过Spark-Cassandra-连接器负责执行,其能够让整个流程变得更为直观且简便。另有一个非常有趣的选项能够帮助大家实现对NoSQL存储内容的交互——SparkSQL,其能够将SQL语句翻译成一系列RDD操作。case class CampaignReport(id: String, views: Long, clicks: Long)

sql("""SELECT campaign.id as id, campaign.views as views,
campaign.clicks as clicks, event.type as type
FROM campaign
JOIN event ON campaign.id = event.campaign
""").rdd
.groupBy(row => row.getAs[String]("id"))
.map{ case (id, rows) =>
val views = rows.head.getAs[Long]("views")
val clicks = rows.head.getAs[Long]("clicks")

val res = rows.groupBy(row => row.getAs[String]("type")).mapValues(_.size)
CampaignReport(id, views = views + res("view"), clicks = clicks + res("click"))

}.saveToCassandra(“keyspace”, “campaign_report”)
通过几行代码,我们已经能够实现原生Lambda设计——其复杂度显然较高,但这一示例表明大家完全有能力以简单方式实现既定功能。

类MapReduce解决方案:拉近处理与数据间的距离

Spark-Cassandra连接器拥有数据位置识别能力,并会从集群内距离最近的节点处读取数据,从而最大程度降低数据在网络中的传输需求。为了充分发挥Spark-C*连接器的数据位置识别能力,大家应当让Spark工作程序与Cassandra节点并行协作。







除了Spark与Cassandra的协作之外,我们也有理由将运营(或者高写入强度)集群同分析集群区分开来,从而保证:
不同集群能够独立进行规模伸缩数据由Cassandra负责复制,而无需其它机制介入分析集群拥有不同的读取/写入负载模式分析集群能够容纳额外数据(例如词典)与处理结果Spark对资源的影响只局限于单一集群当中




下面让我们再次回顾Spark的应用程序部署选项:






目前我们拥有三种主要集群资源管理器选项可供选择:
单独使用Spark——Spark作为主体,各工作程序以独立应用程序的形式安装并执行(这明显会增加额外资源负担,且只支持为每工作程序分配静态资源)如果大家已经拥有Hadoop生态系统,那么YARN绝对是个不错的选项Mesos自诞生之初就在设计中考虑到对集群资源的动态分配,而且除了Hadoop应用程序之外,同时也适合处理各类异构工作负载

Mesos架构







Mesos集群由各主节点构成,它们负责资源供应与调度,而各从节点则实际承担任务执行负载。在HA模式当中,我们利用多个主ZooKeeper节点负责进行主节点选择与服务发现。Mesos之上执行的各应用程序被称为“框架(Framework)”,并利用API处理资源供应及将任务提交至Mesos。总体来讲,其任务执行流程由以下几个步骤构成:
从节点为主节点提供可用资源主节点向框架发送资源供应调度程序回应这些任务及每任务资源需求主节点将任务发送至从节点


将Spark、Mesos以及Cassandra加以结合


正如之前所提到,Spark工作程序应当与Cassandra节点协作,从而实现数据位置识别能力以降低网络流量与Cassandra集群负载。下图所示为利用Mesos实现这一目标的可行部署场景示例:





Mesos主节点与ZooKeeper协作Mesos从节点与Cassandra节点协作,从而为Spark提供更理想的数据位置Spark二进制文件部署至全部工作节点当中,而spark-env.sh则配置以合适的主端点及执行器jar位置park执行器JAR被上传至S3/HDFS当中



根据以上设置流程Spark任务可利用简单的spark-submit调用从任意安装有Spark二进制文件并上传有包含实际任务逻辑jar的工作节点被提交至集群中。spark-submit --class io.datastrophic.SparkJob /etc/jobs/spark-jobs.jar
由于现有选项已经能够运行Docker化Spark,因此我们不必将二进制文件分发至每个单一集群节点当中。


定期与长期运行任务之执行机制


每套数据处理系统迟早都要面对两种必不可少的任务运行类别:定期批量汇聚型定期/阶段性任务以及以数据流处理为代表的长期任务。这两类任务的一大主要要求在于容错能力——各任务必须始终保持运行,即使集群节点发生故障。Mesos提供两套出色的框架以分别支持这两种任务类别。


Marathon是一套专门用于实现长期运行任务高容错性的架构,且支持与ZooKeeper相配合之HA模式。其能够运行Docker并提供出色的REST API。以下shell命令示例为通过运行spark-submit实现简单任务配置:








Chronos拥有与Marathon相同的特性,但其设计目标在于运行定期任务,而且总体而言其分布式HA cron支持任务图谱。以下示例为利用简单的bash脚本实现S3压缩任务配置:







目前已经有多种框架方案可供选择,或者正处于积极开发当中以对接各类系统中所广泛采用的Mesos资源管理功能。下面列举其中一部分典型代表:
HadoopCassandraKafkaMyriad: YARN on MesosStormSamza


数据提取

到目前为止可谓一切顺利:存储层已经设计完成,资源管理机制设置妥当,而各任务亦经过配置。接下来惟一要做的就是数据处理工作了。






假定输入数据将以极高速率涌来,这时端点要顺利应对就需要满足以下要求:
提供高吞吐能力/低延迟具备弹性可轻松实现规模扩展支持背压


背压能力并非必需,不过将其作为选项来应对负载峰值是个不错的选择。

Akka能够完美支持以上要求,而且基本上其设计目标恰好是提供这套功能集。下面来看Akka的特性:
JVM面向JVM的角色模型实现能力基于消息且支持异步架构强制执行非共享可变状态可轻松由单一进程扩展至设备集群利用自上而下之监督机制实现角色层级不仅是并发框架:akka-http、akka-stream以及akka-persistence


以下简要示例展示了三个负责处理JSON HttpRequest的角色,它们将该请求解析为域模型例类,并将其保存在Cassandra当中:class HttpActor extends Actor {
def receive = {
case req: HttpRequest =>
system.actorOf(Props[JsonParserActor]) ! req.body
case e: Event =>
system.actorOf(Props[CassandraWriterActor]) ! e
}
}

class JsonParserActor extends Actor {
def receive = {
case s: String => Try(Json.parse(s).as[Event]) match {
case Failure(ex) => //error handling code
case Success(event) => sender ! event
}
}
}

class CassandraWriterActor extends Actor with ActorLogging {
//for demo purposes, session initialized here
val session = Cluster.builder()
.addContactPoint("cassandra.host")
.build()
.connect()

override def receive: Receive = {
case event: Event =>
val statement = new SimpleStatement(event.createQuery)
.setConsistencyLevel(ConsistencyLevel.QUORUM)

Try(session.execute(statement)) match {
case Failure(ex) => //error handling code
case Success => sender ! WriteSuccessfull
}
}
}
看起来只需几行代码即可实现上述目标,不过利用Akka向Cassandra当中写入原始数据(即事件)却有可能带来以下问题:
Cassandra的设计思路仍然偏重高速交付而非批量处理,因此必须对输入数据进行预汇聚。汇聚/汇总所带来的计算时间会随着数据总量的增长而逐步加长。由于采用无状态设计模式,各角色并不适合用于执行汇聚任务。微批量机制能够在一定程度上解决这个难题。仍然需要为原始数据提供某种可靠的缓冲机制

Kafka充当输入数据之缓冲机制






为了保留输入数据并对其进行预汇聚/处理,我们也可以使用某种类型的分布式提交日志机制。在以下用例中,消费程序将批量读取数据,对其进行处理并将其以预汇聚形式保存在Cassandra当中。该示例说明了如何利用akka-http通过HTTP将JSON数据发布至Kafka当中:val config = new ProducerConfig(KafkaConfig())
lazy val producer = new KafkaProducer[A, A](config)
val topic = “raw_events”

val routes: Route = {
post{
decodeRequest{
entity(as[String]){ str =>
JsonParser.parse(str).validate[Event] match {
case s: JsSuccess[String] => producer.send(new KeyedMessage(topic, str))
case e: JsError => BadRequest -> JsError.toFlatJson(e).toString()
}
}
}
}
}

object AkkaHttpMicroservice extends App with Service {
Http().bindAndHandle(routes, config.getString("http.interface"), config.getInt("http.port"))
}



数据消费:Spark Streaming

尽管Akka也能够用于消耗来自Kafka的流数据,但将Spark纳入生态系统以引入Spark Streaming能够切实解决以下难题:

其支持多种数据源提供“至少一次”语义可在配合Kafka Direct与幂等存储实现“仅一次”语义








以下代码示例阐述了如何利用Spark Streaming消费来自Kinesis的事件流:val ssc = new StreamingContext(conf, Seconds(10))

val kinesisStream = KinesisUtils.createStream(ssc,appName,streamName,
endpointURL,regionName, InitialPositionInStream.LATEST,
Duration(checkpointInterval), StorageLevel.MEMORY_ONLY)
}

//transforming given stream to Event and saving to C*
kinesisStream.map(JsonUtils.byteArrayToEvent)
.saveToCassandra(keyspace, table)

ssc.start()
ssc.awaitTermination()
故障设计:备份与补丁安装


通常来讲,故障设计是任何系统当中最为枯燥的部分,但其重要性显然不容质疑——当数据中心不可用或者需要对崩溃状况加以分析时,尽可能保障数据免于丢失可谓至关重要。







那么为什么要将数据存储在Kafka/Kinesis当中?截至目前,Kinesis仍然是惟一在无需备份的情况下能够确保全部处理结果丢失后保留数据的解决方案。虽然Kafka也能够支持数据长期保留,但硬件持有成本仍是个需要认真考虑的问题,因为S3存储服务的使用成本要远低于支持Kafka所需要的大量实例——另外,S3也提供非常理想的服务水平协议。

除了备份能力,恢复/补丁安装策略还应当考虑到前期与测试需求,从而保证任何与数据相关的问题能够得到迅速解决。程序员们在汇聚任务或者重复数据删除操作中可能不慎破坏计算结果,因此修复这类错误的能力就变得非常关键。简化这类操作任务的一种简便方式在于在数据模型当中引入幂等机制,这样同一操作的多次重复将产生相同的结果(例如SQL更新属于幂等操作,而计数递增则不属于)。

以下示例为Spark任务读取S3备份并将其载入至Cassandra:val sc = new SparkContext(conf)

sc.textFile(s"s3n://bucket/2015/*/*.gz")
.map(s => Try(JsonUtils.stringToEvent(s)))
.filter(_.isSuccess).map(_.get)
.saveToCassandra(config.keyspace, config.table)
宏观构成

利用SMACK构建数据平台顶层设计





 
纵观全文,SMACK堆栈的卓越能力包括:
简明的工具储备以解决范围极广的各类数据处理场景软件方案久经考验且拥有广泛普及度,背后亦具备强大的技术社区易于实现规模伸缩与数据复制,且提供较低延迟水平统一化集群管理以实现异构负载可面向任意应用程序类型的单一平台面向不同架构设计(批量、流数据、Lambda、Kappa)的实现平台出色的产品发布速度(例如用于MVP验证)


  查看全部

在今天的文章中,我们将着重探讨如何利用SMACK(即Spark、Mesos、Akka、Cassandra以及Kafka)堆栈构建可扩展数据处理平台。虽然这套堆栈仅由数个简单部分组成,但其能够实现大量不同系统设计。除了纯粹的批量或者流处理机制之外,我们亦可借此实现复杂的Lambda以及Kappa架构。

基于Mesos技术的数人云可以快速部署和运行Spark、Akka、Cassandra以及Kafka,也欢迎大家在数人云上进行体验和实践,感受它们强大功能带来的便利。在本文开始阐述之前,让我们首先立足于已有生产项目经验从设计与示例入手进行说明。


 综述

1.jpg


Spark - 一套高速通用型引擎,用于实现分布式大规模数据处理任务。

Mesos - 集群资源管理系统,能够立足于分布式应用程序提供行之有效的资源隔离与共享能力。

Akka - 一套用于在JVM之上构建高并发、分布式及弹性消息驱动型应用程序的工具包与运行时。

Cassandra - 一套分布式高可用性数据库,旨在跨越多座数据中心处理大规模数据。

Kafka -一套高吞吐能力、低延迟、分布式消息收发系统/提交日志方案,旨在处理实时数据供给。


存储层: Cassandra


2.png



Cassandra一直以其高可用性与高吞吐能力两大特性而备受瞩目,其同时能够处理极为可观的写入负载并具备节点故障容错能力。以CAP原则为基础,Cassandra能够为业务运营提供可调整的一致性/可用性水平。


更有趣的是,Cassandra在处理数据时拥有线性可扩展能力(即可通过向集群当中添加节点的方式实现负载增容)并能够提供跨数据中心复制(简称XDCR)能力。事实上,跨数据中心复制功能除了数据复制,同时也能够实现以下各类扩展用例:
  • 地理分布式数据中心处理面向特定区域或者客户周边位置之数据。
  • 在不同数据中心之间者数据迁移,从而实现故障后恢复或者将数据移动至新数据中心。
  • 对运营工作负载与分析工作负载加以拆分。


但上述特性也都有着自己的实现成本,而对于Cassandra而言这种成本体现为数据模型——这意味着我们需要通过聚类对分区键及入口进行分组/分类,从而实现嵌套有序映射。以下为简单示例:CREATE TABLE campaign(  
 id uuid,
year int,
month int,
day int,
views bigint,
clicks bigint,
PRIMARY KEY (id, year, month, day)
);

INSERT INTO campaign(id, year, month, day, views, clicks)
VALUES(40b08953-a…,2015, 9, 10, 1000, 42);

SELECT views, clicks FROM campaign
WHERE id=40b08953-a… and year=2015 and month>8;


为了获取某一范围内的特定数据,我们必须指定全键,且不允许除列表内最后一列之外的其它任何范围划定得以执行。这种限制用于针对不同范围进行多重扫描限定,否则其可能带来随机磁盘访问并拖慢整体性能表现。这意味着该数据模型必须根据读取查询进行认真设计,从而限制读取/扫描量——但这同时也会导致对新查询的支持灵活性有所下降。

那么如果我们需要将某些表加入到其它表当中,又该如何处理?让我们考虑下一种场景:针对特定月份对全部活动进行总体访问量计算。
CREATE TABLE event(  
id uuid,
ad_id uuid,
campaign uuid,
ts bigint,
type text,
PRIMARY KEY(id)
);
在特
定模型之下,实现这一目标的惟一办法就是读取全部活动、读取全部事件、汇总各属性值(其与活动id相匹配)并将其分配给活动。实现这类应用程序操作显然极具挑战,因为保存在Casandra中的数据总量往往非常庞大,内存容量根本不足以加以容纳。因此我们必须以分布式方式对此类数据加以处理,而Spark在这类用例中将发挥重要作用。

处理层: Spark

3.png



Spark的抽象核心主要涉及RDD(即弹性分布式数据集,一套分布式元素集合)以及由以下四个主要阶段构成的工作流:
 
  • RDD操作(转换与操作)以DAG(即有向无环图)形式进行
  • DAG会根据各任务阶段进行拆分,并随后被提交至集群管理器
  • 各阶段无需混洗/重新分配即可与任务相结合
  • 任务运行在工作程序之上,而结果随后返回至客户端



以下为我们如何利用Spark与Cassandra解决上述问题:
val sc = new SparkContext(conf)

case class Event(id: UUID, ad_id: UUID, campaign: UUID, ts: Long, `type`: String)

sc.cassandraTable[Event]("keyspace", "event")
.filter(e => e.`type` == "view" && checkMonth(e.ts))
.map(e => (e.campaign, 1))
.reduceByKey(_ + _)
.collect()
指向Cassandra的交互通过Spark-Cassandra-连接器负责执行,其能够让整个流程变得更为直观且简便。另有一个非常有趣的选项能够帮助大家实现对NoSQL存储内容的交互——SparkSQL,其能够将SQL语句翻译成一系列RDD操作。
case class CampaignReport(id: String, views: Long, clicks: Long)

sql("""SELECT campaign.id as id, campaign.views as views,
campaign.clicks as clicks, event.type as type
FROM campaign
JOIN event ON campaign.id = event.campaign
""").rdd
.groupBy(row => row.getAs[String]("id"))
.map{ case (id, rows) =>
val views = rows.head.getAs[Long]("views")
val clicks = rows.head.getAs[Long]("clicks")

val res = rows.groupBy(row => row.getAs[String]("type")).mapValues(_.size)
CampaignReport(id, views = views + res("view"), clicks = clicks + res("click"))

}.saveToCassandra(“keyspace”, “campaign_report”)

通过几行代码,我们已经能够实现原生Lambda设计——其复杂度显然较高,但这一示例表明大家完全有能力以简单方式实现既定功能。

类MapReduce解决方案:拉近处理与数据间的距离

Spark-Cassandra连接器拥有数据位置识别能力,并会从集群内距离最近的节点处读取数据,从而最大程度降低数据在网络中的传输需求。为了充分发挥Spark-C*连接器的数据位置识别能力,大家应当让Spark工作程序与Cassandra节点并行协作。


4.png


除了Spark与Cassandra的协作之外,我们也有理由将运营(或者高写入强度)集群同分析集群区分开来,从而保证:
  • 不同集群能够独立进行规模伸缩
  • 数据由Cassandra负责复制,而无需其它机制介入
  • 分析集群拥有不同的读取/写入负载模式
  • 分析集群能够容纳额外数据(例如词典)与处理结果
  • Spark对资源的影响只局限于单一集群当中





下面让我们再次回顾Spark的应用程序部署选项:

5.png


目前我们拥有三种主要集群资源管理器选项可供选择:
  • 单独使用Spark——Spark作为主体,各工作程序以独立应用程序的形式安装并执行(这明显会增加额外资源负担,且只支持为每工作程序分配静态资源)
  • 如果大家已经拥有Hadoop生态系统,那么YARN绝对是个不错的选项
  • Mesos自诞生之初就在设计中考虑到对集群资源的动态分配,而且除了Hadoop应用程序之外,同时也适合处理各类异构工作负载


Mesos架构


6.png


Mesos集群由各主节点构成,它们负责资源供应与调度,而各从节点则实际承担任务执行负载。在HA模式当中,我们利用多个主ZooKeeper节点负责进行主节点选择与服务发现。Mesos之上执行的各应用程序被称为“框架(Framework)”,并利用API处理资源供应及将任务提交至Mesos。总体来讲,其任务执行流程由以下几个步骤构成:
  • 从节点为主节点提供可用资源
  • 主节点向框架发送资源供应
  • 调度程序回应这些任务及每任务资源需求
  • 主节点将任务发送至从节点



将Spark、Mesos以及Cassandra加以结合


正如之前所提到,Spark工作程序应当与Cassandra节点协作,从而实现数据位置识别能力以降低网络流量与Cassandra集群负载。下图所示为利用Mesos实现这一目标的可行部署场景示例:

7.png

  • Mesos主节点与ZooKeeper协作
  • Mesos从节点与Cassandra节点协作,从而为Spark提供更理想的数据位置
  • Spark二进制文件部署至全部工作节点当中,而spark-env.sh则配置以合适的主端点及执行器jar位置
  • park执行器JAR被上传至S3/HDFS当中




根据以上设置流程Spark任务可利用简单的spark-submit调用从任意安装有Spark二进制文件并上传有包含实际任务逻辑jar的工作节点被提交至集群中。
spark-submit --class io.datastrophic.SparkJob /etc/jobs/spark-jobs.jar  

由于现有选项已经能够运行Docker化Spark,因此我们不必将二进制文件分发至每个单一集群节点当中。


定期与长期运行任务之执行机制


每套数据处理系统迟早都要面对两种必不可少的任务运行类别:定期批量汇聚型定期/阶段性任务以及以数据流处理为代表的长期任务。这两类任务的一大主要要求在于容错能力——各任务必须始终保持运行,即使集群节点发生故障。Mesos提供两套出色的框架以分别支持这两种任务类别。


Marathon是一套专门用于实现长期运行任务高容错性的架构,且支持与ZooKeeper相配合之HA模式。其能够运行Docker并提供出色的REST API。以下shell命令示例为通过运行spark-submit实现简单任务配置:


8.jpg



Chronos拥有与Marathon相同的特性,但其设计目标在于运行定期任务,而且总体而言其分布式HA cron支持任务图谱。以下示例为利用简单的bash脚本实现S3压缩任务配置:

9.jpg



目前已经有多种框架方案可供选择,或者正处于积极开发当中以对接各类系统中所广泛采用的Mesos资源管理功能。下面列举其中一部分典型代表:
  • Hadoop
  • Cassandra
  • Kafka
  • Myriad: YARN on Mesos
  • Storm
  • Samza



数据提取

到目前为止可谓一切顺利:存储层已经设计完成,资源管理机制设置妥当,而各任务亦经过配置。接下来惟一要做的就是数据处理工作了。

10.png


假定输入数据将以极高速率涌来,这时端点要顺利应对就需要满足以下要求:
  • 提供高吞吐能力/低延迟
  • 具备弹性
  • 可轻松实现规模扩展
  • 支持背压



背压能力并非必需,不过将其作为选项来应对负载峰值是个不错的选择。

Akka能够完美支持以上要求,而且基本上其设计目标恰好是提供这套功能集。下面来看Akka的特性:
  • JVM面向JVM的角色模型实现能力
  • 基于消息且支持异步架构
  • 强制执行非共享可变状态
  • 可轻松由单一进程扩展至设备集群
  • 利用自上而下之监督机制实现角色层级
  • 不仅是并发框架:akka-http、akka-stream以及akka-persistence



以下简要示例展示了三个负责处理JSON HttpRequest的角色,它们将该请求解析为域模型例类,并将其保存在Cassandra当中:
class HttpActor extends Actor {  
def receive = {
case req: HttpRequest =>
system.actorOf(Props[JsonParserActor]) ! req.body
case e: Event =>
system.actorOf(Props[CassandraWriterActor]) ! e
}
}

class JsonParserActor extends Actor {
def receive = {
case s: String => Try(Json.parse(s).as[Event]) match {
case Failure(ex) => //error handling code
case Success(event) => sender ! event
}
}
}

class CassandraWriterActor extends Actor with ActorLogging {
//for demo purposes, session initialized here
val session = Cluster.builder()
.addContactPoint("cassandra.host")
.build()
.connect()

override def receive: Receive = {
case event: Event =>
val statement = new SimpleStatement(event.createQuery)
.setConsistencyLevel(ConsistencyLevel.QUORUM)

Try(session.execute(statement)) match {
case Failure(ex) => //error handling code
case Success => sender ! WriteSuccessfull
}
}
}

看起来只需几行代码即可实现上述目标,不过利用Akka向Cassandra当中写入原始数据(即事件)却有可能带来以下问题:
  • Cassandra的设计思路仍然偏重高速交付而非批量处理,因此必须对输入数据进行预汇聚。
  • 汇聚/汇总所带来的计算时间会随着数据总量的增长而逐步加长。
  • 由于采用无状态设计模式,各角色并不适合用于执行汇聚任务。
  • 微批量机制能够在一定程度上解决这个难题。
  • 仍然需要为原始数据提供某种可靠的缓冲机制


Kafka充当输入数据之缓冲机制

11.png


为了保留输入数据并对其进行预汇聚/处理,我们也可以使用某种类型的分布式提交日志机制。在以下用例中,消费程序将批量读取数据,对其进行处理并将其以预汇聚形式保存在Cassandra当中。该示例说明了如何利用akka-http通过HTTP将JSON数据发布至Kafka当中:
val config = new ProducerConfig(KafkaConfig())  
lazy val producer = new KafkaProducer[A, A](config)
val topic = “raw_events”

val routes: Route = {
post{
decodeRequest{
entity(as[String]){ str =>
JsonParser.parse(str).validate[Event] match {
case s: JsSuccess[String] => producer.send(new KeyedMessage(topic, str))
case e: JsError => BadRequest -> JsError.toFlatJson(e).toString()
}
}
}
}
}

object AkkaHttpMicroservice extends App with Service {
Http().bindAndHandle(routes, config.getString("http.interface"), config.getInt("http.port"))
}



数据消费:Spark Streaming

尽管Akka也能够用于消耗来自Kafka的流数据,但将Spark纳入生态系统以引入Spark Streaming能够切实解决以下难题:

  • 其支持多种数据源
  • 提供“至少一次”语义
  • 可在配合Kafka Direct与幂等存储实现“仅一次”语义




12.png


以下代码示例阐述了如何利用Spark Streaming消费来自Kinesis的事件流:
val ssc = new StreamingContext(conf, Seconds(10))

val kinesisStream = KinesisUtils.createStream(ssc,appName,streamName,
endpointURL,regionName, InitialPositionInStream.LATEST,
Duration(checkpointInterval), StorageLevel.MEMORY_ONLY)
}

//transforming given stream to Event and saving to C*
kinesisStream.map(JsonUtils.byteArrayToEvent)
.saveToCassandra(keyspace, table)

ssc.start()
ssc.awaitTermination()

故障设计:备份与补丁安装


通常来讲,故障设计是任何系统当中最为枯燥的部分,但其重要性显然不容质疑——当数据中心不可用或者需要对崩溃状况加以分析时,尽可能保障数据免于丢失可谓至关重要。


13.png


那么为什么要将数据存储在Kafka/Kinesis当中?截至目前,Kinesis仍然是惟一在无需备份的情况下能够确保全部处理结果丢失后保留数据的解决方案。虽然Kafka也能够支持数据长期保留,但硬件持有成本仍是个需要认真考虑的问题,因为S3存储服务的使用成本要远低于支持Kafka所需要的大量实例——另外,S3也提供非常理想的服务水平协议。

除了备份能力,恢复/补丁安装策略还应当考虑到前期与测试需求,从而保证任何与数据相关的问题能够得到迅速解决。程序员们在汇聚任务或者重复数据删除操作中可能不慎破坏计算结果,因此修复这类错误的能力就变得非常关键。简化这类操作任务的一种简便方式在于在数据模型当中引入幂等机制,这样同一操作的多次重复将产生相同的结果(例如SQL更新属于幂等操作,而计数递增则不属于)。

以下示例为Spark任务读取S3备份并将其载入至Cassandra:
val sc = new SparkContext(conf)

sc.textFile(s"s3n://bucket/2015/*/*.gz")
.map(s => Try(JsonUtils.stringToEvent(s)))
.filter(_.isSuccess).map(_.get)
.saveToCassandra(config.keyspace, config.table)

宏观构成

利用SMACK构建数据平台顶层设计

14.png

 
纵观全文,SMACK堆栈的卓越能力包括:
  • 简明的工具储备以解决范围极广的各类数据处理场景
  • 软件方案久经考验且拥有广泛普及度,背后亦具备强大的技术社区
  • 易于实现规模伸缩与数据复制,且提供较低延迟水平
  • 统一化集群管理以实现异构负载
  • 可面向任意应用程序类型的单一平台
  • 面向不同架构设计(批量、流数据、Lambda、Kappa)的实现平台
  • 出色的产品发布速度(例如用于MVP验证)



 

Marathon 0.15: 更稳定 更多数据 更易用

宁静胡同 发表了文章 • 0 个评论 • 565 次浏览 • 2016-02-15 18:32 • 来自相关话题

Marathon 是数据中心操作系统(DCOS)上的原生容器编排和应用管理平台,正式推出的0.15版增加了许多新功能,并进一步提升了性能、监控和用户界面等方面的表现。
 
数人云基于Mesos技术,使用Marathon部署及监控长期运行的容器化应用程序,我们长期密切关注着Marathon的版本情况,并在第一时间进行跟进和更新。现在我们就来看看Marathon 0.15都有哪些新功能吧。
揭开Marathon 0.15的面纱

 1. 与 Mesos Fetcher Cache 集成
V2 REST API 已经支持 Mesos Fetcher Cache。这可以让用户配置资源URIs 列表(本地或外部资源均可),并在任务运行前将其复制到任务沙盒中。
 
2. 新的统计数据指标
添加了一些重要的新数据指标,包括:当前运行任务的数量,正在更新或排队等待更新的状态数量,应用配置更新或排队的数量等。
 
3. 重新设计了任务状态跟踪模块
用于保存任务状态的组件 TaskTracker,采用了新的基于actor的并行处理模型,从而让Marathon 更加稳定。
 
4. 优化API接口 /V2/Tasks
我们将请求效率提高了30%,从而满足一些服务发现解决方案的性能需求。
 
5. 改变了线程模型
我们使用了一种支持固定大小线程池的模型。只有线程被大量阻塞时,线程池才会扩容,从而提高线程的负载利用率。
 
6. Model验证
Marathon 现在采用一种新的方法(Accord)来做model验证,这可以让产生的错误信息更加友好。

Marathon 用户界面改进

1. 可以在应用列表页做更多的操作
在应用列表页添加了一个下拉菜单,这样不用进入到应用详情页,在列表页就可以对应用做扩容、销毁、暂定等操作了,也可以对整组的应用做扩容和删除操作。






2. 更好的反馈信息
重新设计了反馈对话框,通过修改按钮的文字和使用不同颜色标识info, warning, error 信息,让反馈信息更加一目了然。另外,取消了一些可能导致危险操作的默认选项(如:强制扩容)。
 
3. 应用健康状况
应用详情页可以分类显示应用健康状态了。






大家在使用Marathon的过程中有任何问题,可以在线留言与我们交流。
  查看全部

Marathon 是数据中心操作系统(DCOS)上的原生容器编排和应用管理平台,正式推出的0.15版增加了许多新功能,并进一步提升了性能、监控和用户界面等方面的表现。
 
数人云基于Mesos技术,使用Marathon部署及监控长期运行的容器化应用程序,我们长期密切关注着Marathon的版本情况,并在第一时间进行跟进和更新。现在我们就来看看Marathon 0.15都有哪些新功能吧。


揭开Marathon 0.15的面纱

 1. 与 Mesos Fetcher Cache 集成
V2 REST API 已经支持 Mesos Fetcher Cache。这可以让用户配置资源URIs 列表(本地或外部资源均可),并在任务运行前将其复制到任务沙盒中。
 
2. 新的统计数据指标
添加了一些重要的新数据指标,包括:当前运行任务的数量,正在更新或排队等待更新的状态数量,应用配置更新或排队的数量等。
 
3. 重新设计了任务状态跟踪模块
用于保存任务状态的组件 TaskTracker,采用了新的基于actor的并行处理模型,从而让Marathon 更加稳定。
 
4. 优化API接口 /V2/Tasks
我们将请求效率提高了30%,从而满足一些服务发现解决方案的性能需求。
 
5. 改变了线程模型
我们使用了一种支持固定大小线程池的模型。只有线程被大量阻塞时,线程池才会扩容,从而提高线程的负载利用率。
 
6. Model验证
Marathon 现在采用一种新的方法(Accord)来做model验证,这可以让产生的错误信息更加友好。

Marathon 用户界面改进

1. 可以在应用列表页做更多的操作
在应用列表页添加了一个下拉菜单,这样不用进入到应用详情页,在列表页就可以对应用做扩容、销毁、暂定等操作了,也可以对整组的应用做扩容和删除操作。

1.png


2. 更好的反馈信息
重新设计了反馈对话框,通过修改按钮的文字和使用不同颜色标识info, warning, error 信息,让反馈信息更加一目了然。另外,取消了一些可能导致危险操作的默认选项(如:强制扩容)。
 
3. 应用健康状况
应用详情页可以分类显示应用健康状态了。

2.png


大家在使用Marathon的过程中有任何问题,可以在线留言与我们交流。
 

微服务概念解析(下)

宁静胡同 发表了文章 • 0 个评论 • 588 次浏览 • 2016-02-04 16:21 • 来自相关话题

在上篇中我们讲到了微服务的几个架构特性,包括通过服务实现组件化、以业务功能为核心进行组织、产品而非项目、智能化端点与傻瓜式流程,在今天的微服务概念解析下篇中,我们将继续讲述微服务的特性,具体分析它的离散化治理、离散化数据管理、基础设施自动化、故障应对设计以及演进设计,并理性思考微服务作为一项新兴的技术成果,是否能够代表未来。

离散化治理

聚合型治理的一大影响在于使得单一技术平台上出现标准化趋势。经验表明这类方案具备收缩特性——意味着各个实际问题并不能够轻松与解决方案对应起来。我们更倾向于使用正确的工具执行正确的任务,而且虽然部分整体应用程序能够发挥不同编程语言的独特优势,但这种情况并不常见。

微服务与SOA
当我们探讨微服务时,经常出现的问题就是其到底是不是我们十年前就听说过的面向服务架构(简称SOA)的另一种表现形式?二者之间确实存在一定联系,因为微服务风格拥有与SOA相似的逻辑主张。然而问题在于,SOA的实际含义太过广泛,而且当我们提到所谓“SOA”时,实际所指的对象往往跟这里提到的微服务概念差之千里——具体来讲,其通常代表那些专注于利用ESB实现的集成化整体应用程序。

值得强调的是,我们也见证了大量表现糟糕的面向服务实现手段——从将复杂性隐藏在ESB当中[7]的作法,到投入多年以及数百万资金却毫无成效的尝试,再到以聚合型治理模式抑制变更,我们几乎看不到面向服务架构能够带来什么显著的积极影响。

诚然,微服务社区当中使用的不少技术成果都源自开发人员在大型企业当中积累到的集成化服务成果。Tolerant Reader模式正是其中的典型代表。对Web的运用确实带来可观回报,而使用简单协议正是经验积累的直接产物——这显然是为了解决标准汇聚所导致的高复杂性难题(无论何时,如果大家需要利用一种实体来管理其它实体,那么就意味着各位已经面临着大麻烦)。

SOA的这些弊端导致一部分微服务布道者很讨厌人们把SOA的标签加在微服务头上——尽管也有一些人认为微服务正是SOA的一种实现方式[8],或者说我们可以将微服务称为“面向服务的正确实现”。无论如何,事实上SOA含义的宽泛性意味着其更适合作为一种用于定义架构风格的术语,而非具体解决方案。

通过将整体应用程序的各组件拆分成服务,我们能够对各服务进行分别构建。各位可能希望利用Node.js建立一套简单报告页面?照此办理即可。打算利用C++构建特定的近实时组件?没问题。打算利用不同类型的数据库以匹配单一组件的读取行为?目前的技术方案已经能够实现这种独立重构需求。

当然,我们能够实现以上目标,并不代表我们必须这么做——但对系统进行拆分意味着大家能够拥有更多备用选项。

采用微服务架构的团队倾向于以不同的方式实现所谓标准。相较于以往编写一整套定义标准集的作法,他们更乐于开发实用工具并交付给其他开发人员,从而利用其解决自身面临的类似问题。这些工具通常能够在更为广泛的层面得到实现与共享,但同时又不至于转化为排他性内部开源模式。现在git与github都已经成为客观层面的版本控制系统选项,而开源实践也越来越多地成为内部环境中的常见组成部分。

Netflix公司就是个很好的例子,他们遵循的正是这样一种理念。将具备实用性且经过严格考验的代码作为库,并鼓励其他开发人员利用其以类似的方式解决的类似的问题,这就为各团队成员在必要时选择其它工具保留了空间。共享式库专注于数据存储、进程间通信以及我们在后文中将要探讨的基础设施自动化等问题的解决。

对于微服务社区而言,资源成本显然是种不受欢迎的因素。这并不是说该社区不承认服务协议的价值。恰恰相反,这是因为他们希望构建起大量服务协议。他们希望能够采用多种完全不同的方式对这些协议进行管理。像Tolerant Reader以及Consumer-Driven Contacts这样的模式在微服务架构中非常常见。这些服务协议也各自以独立方式不断演进。将消费者驱动型协议作为构建工作组成部分的作法能够显著增强参与者信心,同时快速获取服务功能能否确切实现的反馈意见。事实上,澳大利亚的某个团队就在积极利用消费者驱动型协议进行新服务构建。他们使用的简单工具确保其能够针对单一服务实现协议定义。其甚至在面向新服务的代码被编写出来之前就已经成为自动化构建流程中的一部分。这意味着服务只有在切实满足该协议要求的前提下才能够实现构建——这就有效解决了构建新软件时经常出现的“YAGNI”[9]难题。这些技术与工具成果围绕协议而生,并通过降低不同服务间的耦合性限制了其对中央协议管理机制的依赖。

多种语言,多种选项

JVM作为平台的快速发展已经成为多种语言混成于单一通用平台内的最新明证。这种作法已经成为一类常见实践,旨在充分发挥高级语言在过去数十年中发展所实现的种种高级抽象优势。其甚至以涓滴效应影响到裸机以及通过低级语言编写的性能敏感型代码。然而,众多整体应用程序并不需要这种级别的性能优化效果,亦非常见的DSL与高级别抽象开发成果。相反,整体应用程序往往使用单一语言,这也严重限制了其能够使用的技术手段。[10]

也许离散化治理的人气正是源自Amazon方面提出的“谁构建,谁运行”原则。各团队需要为其构建的软件的各个方面承担责任,包括为软件提供24/7全天候运维支持。这种程度的责任下放当然还没有成为常态,不过我们已经看到越来越多的企业开始将责任交付至开发团队。Netflix公司亦是另一家采取这种理念[11]的企业。为了不至于在凌晨三点被紧急来电叫醒,开发人员们当然会全力以赴提升所编写代码的质量水平。这些思路与传统的集中化治理模式明显相去甚远。

离散化数据管理

数据管理离散化拥有多种不同的表现形式。从最为抽象的级别来看,这意味着全局概念模型将在不同系统之间有所区别。这种问题常见于解决方案在大型企业当中的部署,毕竟销售团队对于客户概念的理解方式必须不同于技术支持团队的理解方式。被销售人员视为客户的对象也许根本不会出现的技术支持团队的视野当中。不同属性甚至是相同属性的不同理解方式都可能在语义层面产生细微的差异。

实践性规范与执行标准

这种态度实际有点二分法的意味:微服务团队倾向于回避由企业架构部门制定的硬性执行标准,但却乐于使用甚至积极推广HTTP、ATOM以及其它微格式开放标准。

二者之间的本质区别在于标准的开发方式以及执行方式。由IETF等组织管理的标准只会在得到广泛采用之后才能真正成为业界规范,而且其往往脱胎自成功的开源项目。

这些标准拥有与商业世界完全不同的立场与定位——事实上,商业标准的制定工作往往由那些几乎不具备编程经验的团队所负责,或者受到具体厂商的过度影响。

这一问题通常出现在不同应用程序之间甚至是应用程序之内,特别是在将应用程序拆分为多个独立组件的情况下。解决问题的一类可行思路在于基于背景边界化的区域驱动型设计(简称DDD)方案。DDD机制将一个复杂的区域拆分成多个具备边界的背景单元,并对各单元之间的关系加以映射。这种方式同时适用于整体与微服务架构,但服务与背景边界间的自然关联性有助于声明我们曾在业务功能章节中提到过的区分效果。

除了对概念模式进行离散化处理,微服务同时也能够拆分数据存储决策。尽管整体性应用程序倾向于使用单一逻辑数据库保存持久性数据,但企业通常更乐于利用单一数据库涵盖一系列应用程序——而且大多数此类决策立足于具体供应商提供的授权商业模式。微服务机制则选择由每项服务管理其自身数据库的方式,而非不同实例基于同一数据库技术或者完全使用多种不同数据库系统——这种方式亦被称为混合持久化。大家可以利用混合持久化方案打理整体应用程序,但其在微服务架构中的亮相频率明显更高一些。








对微服务架构内数据责任关系的离散化处理也影响到了更新管理工作。常见的更新处理方案是在更新多种资源时,利用事务处理机制来保证其一致性。这种方式通常被用于整体性应用程序汉中。

这种事务处理使用方式确实有助于保障一致性,但却会带来显著的临时性耦合效果,而这在跨越多项服务时会带来新的难题。分布式事务处理非常难以实现,因此微服务架构更强调服务之间的事务处理协调性,同时明确强调只需保障最终一致性并通过补偿运算解决其中的冲突问题。

利用这种方式管理一致性问题已经成为众多开发团队的新困境,但其却能够切实匹配业务实践。一般来讲,企业需要保留一定程度的不一致性以实现某种程度的逆转能力,从而利用快速响应处理错误状况。这种权衡有其必要性,只要确定失误成本要低于高一致性条件下可能造成的业务损失成本即可。

基础设施自动化

基础设施自动化技术在过去几年中得到了长足发展——而云与AWS的演进则显著降低了构建、部署及运维微服务架构所带来的复杂性水平。

大部分利用微服务机制构建的产品或者系统都是由具备丰富的持续交付及其前者——持续集成——经验的团队所完成。通过这种方式构建软件的团队能够充分发挥基础设施自动化技术成果的潜在能力。我们可以将整个流程整理成以下图表:







图五:基本构建流程

让正确决定更易于执行
 
作为一项连带效应,我们发现实现持续交付与部署能够帮助开发人员及运维人员创造出高实用性工具。这类工具能够创建artifact、管理代码库、建立简单服务或者实现标准监控与记录等常见功能。这方面最典型的实例当数Netflix公司发布的一系列开源工具,险些之外Dropwizard等方案亦得到广泛使用。

整体应用程序的构建、测试与推送流程能够在此类环境下顺利完成。事实证明,一旦大家利用自动化流程进行整体应用开发,那么部署更多应用程序也将成为顺理成章的轻松任务。请记住,持续交付的目标之一就是令部署变得无脑化,这意味着无论是一款应用还是三款,其实际部署流程都不会有什么区别[12]。

我们还发现,不少团队在利用这种广泛的基础设施自动化能力管理生产环境下的微服务架构。相较于前面提到的整体与微服务应用在部署层面并没有太大区别,实际运维环境下的具体条件则存在着巨大差异。







图六:模块部署的具体方式往往差别巨大

故障应对设计

将服务作为组件加以使用的结果之一在于,应用程序需要经过针对性设计以确保其具备服务故障容错能力。任何服务调用都有可能因为供应程序不可用而发生问题。在这种情况下,客户端必须要尽可能做出适当的回应。相较于整体应用程序来说,服务即组件机制会增加额外的处理复杂性,这也是微服务架构的一大弊端。在这种情况下,微服务团队需要不断审视服务故障对用户体验造成的影响。Netflix公司的“猴子军团”项目就专门负责在正常运营期间对服务进行破坏,甚至利用数据中心故障来测试应用程序的弹性及监控能力。

断路器与可交代生产环境之代码
 
断路器模式出现在Amazon的Release It!当中,其中提到的其它模式还包括隔板模式与超时模式等。在加以结合之后,这些模式将在构建通信应用方面发挥巨大作用。Netflix公司发布的一系列博文就很好地解释了他们对这些模式选项的具体使用方式。

这类自动化测试机制往往会令正等待周末下班的运维团队们感到不寒而慄。这并不是说整体架构风格就无法使用高复杂性监控机制——只不过这种情况确实不太常见。

由于服务随时可能发生故障,因此最重要的就是保持对故障的快速检测能力,并在可能的情况下对其进行自动恢复。微服务应用程序高度强调对应用程序的实时监控能力,同时不断对架构元素(数据库每秒钟接收到的请求数量)以及业务相关指标(例如每分钟收到的订单数量)进行记录。语义监控能够通过早期预警系统抢先一步做出警示,并引导开发团队对问题加以跟进与调查。

这一点对于微服务架构尤为重要,因为微服务更倾向于采用由编排及事件协作实现的应急处理方式。尽管很多专家都对应急处理方案偶尔带来的收益表示认同,但其实际上往往也是让事情变糟的罪魁祸首。为了及时阻断糟糕的应急处理并确保其拥有可恢复性,监控系统就变得极为重要。

同步调用殊不可取
 
无论何时时,一旦在不同服务之间进行多次同步调用,那么可能引发宕机的概率也会以乘法形式增长。简单来讲,系统的总体宕机时间为各单个部件宕机时间的乘积。这时我们就面临着具体选择,到底是以异步方式进行调用,还是以计划方式管理由同步调用带来的宕机时间。英国《卫报》网站在其全新平台上执行了一项简单的规则——每个用户请求对应一次同步调用,而Netflix公司所使用的API则经历重新设计,确保其结构内采用异步调用机制。

整体应用程序的构建方式可与微服务架构同样透明——事实上也本应如此。二者的区别在于,在面对整体应用时我们需要在确切了解其运行在不同进程中的服务何时发生断开。考虑到同一进程当中可能包含多套库,这种透明度水平实际上很难实现。

微服务团队需要利用复杂的监控与记录机制处理各项服务,例如通过仪表板显示上线/下线状态以及一系列运营与业务相关指标。另外,我们还需要面对断路器状态、当前数据吞吐量以及延迟等其它常见的衡量数据。

演进设计      
                 
微服务从业者通常都具备演进设计工作背景,并将服务拆分视为一种深入型工具,旨在帮助应用程序开发人员在无需拖慢变更速度的前提下实现面向应用程序的变更控制。变更控制并不一定意味着变更数量削减——配合正确的态度与工具,大家完全可以帮助软件提供快速、频繁且经过良好控制的变更。

当尝试将一套软件系统拆分为多个组件时,我们往往面临着与具体拆分工作相关的决策任务——即我们应该遵循怎样的方针对应用程序进行拆分?而组件中的关键属性则在于其独立替换与可升级特性[13]——这意味着我们要找到确切的平衡点,保证自身能够在不影响其它协作对象的前提下对单一组件进行重写。事实上,很多微服务团队会更进一步,直接清退某些服务而非对其进行长期升级。

英国《卫报》网站就是个很好的例子,其应用程序在设计与构建方面作为整体应用存在,但却在逐步面向微服务架构演进。该网站的核心部分仍然属于整体性项目,但他们更倾向于通过构建微服务利用整体API实现新功能添加。这套方案对于临时性功能的实现非常重要,例如加设专题页面以显示体育赛事报道。网站中的这类组成部分能够通过快速开发语言在短时间内编写完成,并在对应事件结束后立即下线。我们还发现其它一些金融机构亦采取类似的方式公布突发性市场波动,并在数周或者数月之后将其下线。

这也强调了可替换性在模块化设计中的重要地位,其主旨正在于将模块机制贯彻整个变更模式[14]。大家希望只变更其中必须变更的部分,而其它模块则继续保持原样。系统当中那些几乎很少变动的部分应该立足于不同于高变更频率组件的服务。如果大家发现自己经常需要同时对两项服务做出变更,那么明显应该将二者加以合并。

将组件纳入服务也让我们能够以更高的细粒度水平进行规划制定。在整体应用程序当中,任何一项变更都需要对应用整体进行重构与重新部署。但在微服务架构方面,我们只需要重新部署包含对应变更的服务。这能够显著简化并加快发布流程。不过其弊端在于,我们必须考虑针对单一服务的变更是否会影响到其它服务。传统的整体性方案能够通过版本控制解决这类难题,但微服务领域则倾向于将版本控制作为最后一种应急办法。我们可以通过设计保证服务拥有强大的容错能力,从而应对其供应程序中出现的各类代码修改。

微服务是否代表着未来?
我们撰写这篇文章的主要目的在于解释微服务架构的基本思路与原则。而在撰写过程当中,我们明确意识到微服务架构风格确实是一项值得重视的关键成果——企业级应用程序开发人员应当对其加以了解。我们最近利用该架构构建了多套系统,而且了解到亦有其它多家企业将其纳入业务体系。

我们了解到的微服务架构先驱企业包括Amazon、Netflix、英国《卫报》、英国政府数字化服务局、realestate.com.au、Forward以及comparethemarket.com等等。2013年召开的相关会议则公布了更多参与其中的重要厂商。除此之外,另有相当一部分企业一直在使用类似的实现思路——但却并没有使用‘微服务’这样的称谓。(其通常将其冠以SOA标签——不过正如我们之前提到,SOA是一类存在大量矛盾取向的概念组合。[15])

尽管拥有这些积极的经验,但我们仍然无法完全肯定微服务架构就代表着软件未来的发展方向。虽然我们的实际经历证明微服务架构截至目前仍拥有优于整体性应用程序的积极优势,但必须承认只有充分的时间积累才能帮助我们做出真正完整则准确的判断结论。







我们的同事Sam Newman曾于2014年倾尽心力撰写出这本关于我们如何构建微服务架构类应用的论著。如果大家希望进一步探讨这个议题,请千万不要错过。

通常来说,架构决策的实际影响可能需要几年之后才能逐步显现出来。我们已经看到不少优秀的团队带着巨大的热情与愿景而投入工作,但最终却构建起一套陈旧不堪的整体性架构。很多人认为同样的情况不太可能发生在微服务架构身上,因为其服务边界非常明确因此不太可能发生相互影响。但由于时间尚短且系统程度不足,我们目前还无法真正评估微服务架构的成熟度水平。

人们对微服务成熟度抱持的怀疑态度也有其理由。在任何组件化尝试工作当中,最终结果的成功与否都取决于该软件与拆分后组件的契合效果。我们目前仍然很难说明组件边界的选择原则。演进设计导致边界划分变得非常困难,因此最重要的是保证其重构的简易性。但一旦将组件作为服务处理以实现远程通信,那么其重构难度将远远高于进程内库。在不同服务边界之间进行代码移动难度极大,而任何接口变更都需要在不同相关服务间实现,同时添加层的向下兼容能力,这无疑会令测试工作更加复杂。

另一大问题在于,如果相关组件间的关系不够简洁,那么我们就相当于把组件内部的复杂性转移到了不同组件间的连接当中。这样做不仅会导致复杂性扩散,同时亦会导致其明确性缺失且难以控制。立足于小型、简单组件审视问题总是更为直观,而在不同服务间进行纵览则往往会错失关注点。

最后,团队的技能水平也将起到决定性作用。新型技术成果往往要求高水平技术团队加以实施。不过高水平团队能够顺畅利用的技术方案并不一定能够在低水平人员手中发挥作用。我们已经见证了众多低水平团队构建起的如一团乱麻般的整体架构,但仍需要时间来了解微服务架构是否会在同样的情况下引发同样的状况。诚然,糟糕的团队创建出的始终只能是糟糕的系统——但我们不知道微服务架构到底是会缓解这种状况,还是令状况更中惨不忍睹。

目前有一种较为理性的论调,认为我们不应将微服务架构作为起步方案。相反,大家可以从整体性开发风格出发,保证其结合模块化机制,并在整体性特征引发实际问题后逐步将其拆分为微服务形式。(不过这样的建议并非完全理想,因为良好的进程内接口往往并不能成为良好的服务接口。)

因此我们对此抱持谨慎的乐观态度。到目前为止,我们已经了解到关于微服务架构的方方面面,而且其应该能够成为一种极具价值的开发手段。虽然还不能做出最终判断,但软件开发工作的固有挑战之一,正是我们只能根据目前掌握的远称不上完美的信息做出决策。

脚注
7: 虽然无关紧要,但Jim Webber曾经将ESB解释成“Egregious Spaghetti Box”,也就是“恐怖意面盒”。

8: Netflix公司最近将其架构类型称为“细化SOA”。

9: “YAGNI”的全称是“You Aren’t Going To Need It(你根本不需要它)”,这是一项经典的用户体验原则,即不要自作聪明地添加非必要性功能。

10: 我们所宣称的整体型应用只支持单一语言确实有些不尽不实——在当下的Web系统构建过程中,大家可能需要掌握JavaScript、XHTML以及CSS,而在服务器端的语言选项则包括SQL以及某种ORM(即对象关系映射)衍生语言。没错,单一语言肯定玩不转,但我相信大家明白我想要强调的意思。

11: Adrian Cockcroft在2013年11月的Flowcon大会上作出了精彩演讲,并特别提到了“开发者自助服务”与“开发者应亲自运行所编写代码”的观点。

12: 我们在这里的说法并不准确。很明显,在更为复杂的拓扑结构中部署大量服务肯定要比在单一整体型架构内进行部署困难得多。幸运的是,各类模式能够显著降低这种复杂性——当然,在工具方面的投入仍然不可或缺。

13: 事实上,Dan North将这种类型称为“可替代式组件架构”而非微服务架构。由于其强调内容属于微服务架构的一类子集,所以我们更倾向于使用后一种表达方式。

14: Kent Beck将此作为其《实施模式》一文中的设计原则之一。

15: SOA几乎是此类架构的历史起源。我记得当SOA一词在本世纪初刚刚出现时,很多人表示“我们几年前就已经将其引入日常工作了”。也有意见认为这种架构类型似乎最早出现于早期企业计算当中,COBOL程序通过数据文件实现通信的处理机制。而在另一方面,也有人认为微服务架构与Erlang编程模型其实是同一回事,不过后者只被应用在企业应用程序当中。 查看全部

在上篇中我们讲到了微服务的几个架构特性,包括通过服务实现组件化、以业务功能为核心进行组织、产品而非项目、智能化端点与傻瓜式流程,在今天的微服务概念解析下篇中,我们将继续讲述微服务的特性,具体分析它的离散化治理、离散化数据管理、基础设施自动化、故障应对设计以及演进设计,并理性思考微服务作为一项新兴的技术成果,是否能够代表未来。



离散化治理

聚合型治理的一大影响在于使得单一技术平台上出现标准化趋势。经验表明这类方案具备收缩特性——意味着各个实际问题并不能够轻松与解决方案对应起来。我们更倾向于使用正确的工具执行正确的任务,而且虽然部分整体应用程序能够发挥不同编程语言的独特优势,但这种情况并不常见。

微服务与SOA
当我们探讨微服务时,经常出现的问题就是其到底是不是我们十年前就听说过的面向服务架构(简称SOA)的另一种表现形式?二者之间确实存在一定联系,因为微服务风格拥有与SOA相似的逻辑主张。然而问题在于,SOA的实际含义太过广泛,而且当我们提到所谓“SOA”时,实际所指的对象往往跟这里提到的微服务概念差之千里——具体来讲,其通常代表那些专注于利用ESB实现的集成化整体应用程序。

值得强调的是,我们也见证了大量表现糟糕的面向服务实现手段——从将复杂性隐藏在ESB当中[7]的作法,到投入多年以及数百万资金却毫无成效的尝试,再到以聚合型治理模式抑制变更,我们几乎看不到面向服务架构能够带来什么显著的积极影响。

诚然,微服务社区当中使用的不少技术成果都源自开发人员在大型企业当中积累到的集成化服务成果。Tolerant Reader模式正是其中的典型代表。对Web的运用确实带来可观回报,而使用简单协议正是经验积累的直接产物——这显然是为了解决标准汇聚所导致的高复杂性难题(无论何时,如果大家需要利用一种实体来管理其它实体,那么就意味着各位已经面临着大麻烦)。

SOA的这些弊端导致一部分微服务布道者很讨厌人们把SOA的标签加在微服务头上——尽管也有一些人认为微服务正是SOA的一种实现方式[8],或者说我们可以将微服务称为“面向服务的正确实现”。无论如何,事实上SOA含义的宽泛性意味着其更适合作为一种用于定义架构风格的术语,而非具体解决方案。

通过将整体应用程序的各组件拆分成服务,我们能够对各服务进行分别构建。各位可能希望利用Node.js建立一套简单报告页面?照此办理即可。打算利用C++构建特定的近实时组件?没问题。打算利用不同类型的数据库以匹配单一组件的读取行为?目前的技术方案已经能够实现这种独立重构需求。

当然,我们能够实现以上目标,并不代表我们必须这么做——但对系统进行拆分意味着大家能够拥有更多备用选项。

采用微服务架构的团队倾向于以不同的方式实现所谓标准。相较于以往编写一整套定义标准集的作法,他们更乐于开发实用工具并交付给其他开发人员,从而利用其解决自身面临的类似问题。这些工具通常能够在更为广泛的层面得到实现与共享,但同时又不至于转化为排他性内部开源模式。现在git与github都已经成为客观层面的版本控制系统选项,而开源实践也越来越多地成为内部环境中的常见组成部分。

Netflix公司就是个很好的例子,他们遵循的正是这样一种理念。将具备实用性且经过严格考验的代码作为库,并鼓励其他开发人员利用其以类似的方式解决的类似的问题,这就为各团队成员在必要时选择其它工具保留了空间。共享式库专注于数据存储、进程间通信以及我们在后文中将要探讨的基础设施自动化等问题的解决。

对于微服务社区而言,资源成本显然是种不受欢迎的因素。这并不是说该社区不承认服务协议的价值。恰恰相反,这是因为他们希望构建起大量服务协议。他们希望能够采用多种完全不同的方式对这些协议进行管理。像Tolerant Reader以及Consumer-Driven Contacts这样的模式在微服务架构中非常常见。这些服务协议也各自以独立方式不断演进。将消费者驱动型协议作为构建工作组成部分的作法能够显著增强参与者信心,同时快速获取服务功能能否确切实现的反馈意见。事实上,澳大利亚的某个团队就在积极利用消费者驱动型协议进行新服务构建。他们使用的简单工具确保其能够针对单一服务实现协议定义。其甚至在面向新服务的代码被编写出来之前就已经成为自动化构建流程中的一部分。这意味着服务只有在切实满足该协议要求的前提下才能够实现构建——这就有效解决了构建新软件时经常出现的“YAGNI”[9]难题。这些技术与工具成果围绕协议而生,并通过降低不同服务间的耦合性限制了其对中央协议管理机制的依赖。

多种语言,多种选项

JVM作为平台的快速发展已经成为多种语言混成于单一通用平台内的最新明证。这种作法已经成为一类常见实践,旨在充分发挥高级语言在过去数十年中发展所实现的种种高级抽象优势。其甚至以涓滴效应影响到裸机以及通过低级语言编写的性能敏感型代码。然而,众多整体应用程序并不需要这种级别的性能优化效果,亦非常见的DSL与高级别抽象开发成果。相反,整体应用程序往往使用单一语言,这也严重限制了其能够使用的技术手段。[10]

也许离散化治理的人气正是源自Amazon方面提出的“谁构建,谁运行”原则。各团队需要为其构建的软件的各个方面承担责任,包括为软件提供24/7全天候运维支持。这种程度的责任下放当然还没有成为常态,不过我们已经看到越来越多的企业开始将责任交付至开发团队。Netflix公司亦是另一家采取这种理念[11]的企业。为了不至于在凌晨三点被紧急来电叫醒,开发人员们当然会全力以赴提升所编写代码的质量水平。这些思路与传统的集中化治理模式明显相去甚远。

离散化数据管理

数据管理离散化拥有多种不同的表现形式。从最为抽象的级别来看,这意味着全局概念模型将在不同系统之间有所区别。这种问题常见于解决方案在大型企业当中的部署,毕竟销售团队对于客户概念的理解方式必须不同于技术支持团队的理解方式。被销售人员视为客户的对象也许根本不会出现的技术支持团队的视野当中。不同属性甚至是相同属性的不同理解方式都可能在语义层面产生细微的差异。

实践性规范与执行标准

这种态度实际有点二分法的意味:微服务团队倾向于回避由企业架构部门制定的硬性执行标准,但却乐于使用甚至积极推广HTTP、ATOM以及其它微格式开放标准。

二者之间的本质区别在于标准的开发方式以及执行方式。由IETF等组织管理的标准只会在得到广泛采用之后才能真正成为业界规范,而且其往往脱胎自成功的开源项目。

这些标准拥有与商业世界完全不同的立场与定位——事实上,商业标准的制定工作往往由那些几乎不具备编程经验的团队所负责,或者受到具体厂商的过度影响。

这一问题通常出现在不同应用程序之间甚至是应用程序之内,特别是在将应用程序拆分为多个独立组件的情况下。解决问题的一类可行思路在于基于背景边界化的区域驱动型设计(简称DDD)方案。DDD机制将一个复杂的区域拆分成多个具备边界的背景单元,并对各单元之间的关系加以映射。这种方式同时适用于整体与微服务架构,但服务与背景边界间的自然关联性有助于声明我们曾在业务功能章节中提到过的区分效果。

除了对概念模式进行离散化处理,微服务同时也能够拆分数据存储决策。尽管整体性应用程序倾向于使用单一逻辑数据库保存持久性数据,但企业通常更乐于利用单一数据库涵盖一系列应用程序——而且大多数此类决策立足于具体供应商提供的授权商业模式。微服务机制则选择由每项服务管理其自身数据库的方式,而非不同实例基于同一数据库技术或者完全使用多种不同数据库系统——这种方式亦被称为混合持久化。大家可以利用混合持久化方案打理整体应用程序,但其在微服务架构中的亮相频率明显更高一些。


1111.jpg



对微服务架构内数据责任关系的离散化处理也影响到了更新管理工作。常见的更新处理方案是在更新多种资源时,利用事务处理机制来保证其一致性。这种方式通常被用于整体性应用程序汉中。

这种事务处理使用方式确实有助于保障一致性,但却会带来显著的临时性耦合效果,而这在跨越多项服务时会带来新的难题。分布式事务处理非常难以实现,因此微服务架构更强调服务之间的事务处理协调性,同时明确强调只需保障最终一致性并通过补偿运算解决其中的冲突问题。

利用这种方式管理一致性问题已经成为众多开发团队的新困境,但其却能够切实匹配业务实践。一般来讲,企业需要保留一定程度的不一致性以实现某种程度的逆转能力,从而利用快速响应处理错误状况。这种权衡有其必要性,只要确定失误成本要低于高一致性条件下可能造成的业务损失成本即可。

基础设施自动化

基础设施自动化技术在过去几年中得到了长足发展——而云与AWS的演进则显著降低了构建、部署及运维微服务架构所带来的复杂性水平。

大部分利用微服务机制构建的产品或者系统都是由具备丰富的持续交付及其前者——持续集成——经验的团队所完成。通过这种方式构建软件的团队能够充分发挥基础设施自动化技术成果的潜在能力。我们可以将整个流程整理成以下图表:


222.jpg


图五:基本构建流程

让正确决定更易于执行
 

作为一项连带效应,我们发现实现持续交付与部署能够帮助开发人员及运维人员创造出高实用性工具。这类工具能够创建artifact、管理代码库、建立简单服务或者实现标准监控与记录等常见功能。这方面最典型的实例当数Netflix公司发布的一系列开源工具,险些之外Dropwizard等方案亦得到广泛使用。

整体应用程序的构建、测试与推送流程能够在此类环境下顺利完成。事实证明,一旦大家利用自动化流程进行整体应用开发,那么部署更多应用程序也将成为顺理成章的轻松任务。请记住,持续交付的目标之一就是令部署变得无脑化,这意味着无论是一款应用还是三款,其实际部署流程都不会有什么区别[12]。

我们还发现,不少团队在利用这种广泛的基础设施自动化能力管理生产环境下的微服务架构。相较于前面提到的整体与微服务应用在部署层面并没有太大区别,实际运维环境下的具体条件则存在着巨大差异。


333.jpg


图六:模块部署的具体方式往往差别巨大

故障应对设计

将服务作为组件加以使用的结果之一在于,应用程序需要经过针对性设计以确保其具备服务故障容错能力。任何服务调用都有可能因为供应程序不可用而发生问题。在这种情况下,客户端必须要尽可能做出适当的回应。相较于整体应用程序来说,服务即组件机制会增加额外的处理复杂性,这也是微服务架构的一大弊端。在这种情况下,微服务团队需要不断审视服务故障对用户体验造成的影响。Netflix公司的“猴子军团”项目就专门负责在正常运营期间对服务进行破坏,甚至利用数据中心故障来测试应用程序的弹性及监控能力。

断路器与可交代生产环境之代码
 
断路器模式出现在Amazon的Release It!当中,其中提到的其它模式还包括隔板模式与超时模式等。在加以结合之后,这些模式将在构建通信应用方面发挥巨大作用。Netflix公司发布的一系列博文就很好地解释了他们对这些模式选项的具体使用方式。

这类自动化测试机制往往会令正等待周末下班的运维团队们感到不寒而慄。这并不是说整体架构风格就无法使用高复杂性监控机制——只不过这种情况确实不太常见。

由于服务随时可能发生故障,因此最重要的就是保持对故障的快速检测能力,并在可能的情况下对其进行自动恢复。微服务应用程序高度强调对应用程序的实时监控能力,同时不断对架构元素(数据库每秒钟接收到的请求数量)以及业务相关指标(例如每分钟收到的订单数量)进行记录。语义监控能够通过早期预警系统抢先一步做出警示,并引导开发团队对问题加以跟进与调查。

这一点对于微服务架构尤为重要,因为微服务更倾向于采用由编排及事件协作实现的应急处理方式。尽管很多专家都对应急处理方案偶尔带来的收益表示认同,但其实际上往往也是让事情变糟的罪魁祸首。为了及时阻断糟糕的应急处理并确保其拥有可恢复性,监控系统就变得极为重要。

同步调用殊不可取
 
无论何时时,一旦在不同服务之间进行多次同步调用,那么可能引发宕机的概率也会以乘法形式增长。简单来讲,系统的总体宕机时间为各单个部件宕机时间的乘积。这时我们就面临着具体选择,到底是以异步方式进行调用,还是以计划方式管理由同步调用带来的宕机时间。英国《卫报》网站在其全新平台上执行了一项简单的规则——每个用户请求对应一次同步调用,而Netflix公司所使用的API则经历重新设计,确保其结构内采用异步调用机制。

整体应用程序的构建方式可与微服务架构同样透明——事实上也本应如此。二者的区别在于,在面对整体应用时我们需要在确切了解其运行在不同进程中的服务何时发生断开。考虑到同一进程当中可能包含多套库,这种透明度水平实际上很难实现。

微服务团队需要利用复杂的监控与记录机制处理各项服务,例如通过仪表板显示上线/下线状态以及一系列运营与业务相关指标。另外,我们还需要面对断路器状态、当前数据吞吐量以及延迟等其它常见的衡量数据。

演进设计      
                 
微服务从业者通常都具备演进设计工作背景,并将服务拆分视为一种深入型工具,旨在帮助应用程序开发人员在无需拖慢变更速度的前提下实现面向应用程序的变更控制。变更控制并不一定意味着变更数量削减——配合正确的态度与工具,大家完全可以帮助软件提供快速、频繁且经过良好控制的变更。

当尝试将一套软件系统拆分为多个组件时,我们往往面临着与具体拆分工作相关的决策任务——即我们应该遵循怎样的方针对应用程序进行拆分?而组件中的关键属性则在于其独立替换与可升级特性[13]——这意味着我们要找到确切的平衡点,保证自身能够在不影响其它协作对象的前提下对单一组件进行重写。事实上,很多微服务团队会更进一步,直接清退某些服务而非对其进行长期升级。

英国《卫报》网站就是个很好的例子,其应用程序在设计与构建方面作为整体应用存在,但却在逐步面向微服务架构演进。该网站的核心部分仍然属于整体性项目,但他们更倾向于通过构建微服务利用整体API实现新功能添加。这套方案对于临时性功能的实现非常重要,例如加设专题页面以显示体育赛事报道。网站中的这类组成部分能够通过快速开发语言在短时间内编写完成,并在对应事件结束后立即下线。我们还发现其它一些金融机构亦采取类似的方式公布突发性市场波动,并在数周或者数月之后将其下线。

这也强调了可替换性在模块化设计中的重要地位,其主旨正在于将模块机制贯彻整个变更模式[14]。大家希望只变更其中必须变更的部分,而其它模块则继续保持原样。系统当中那些几乎很少变动的部分应该立足于不同于高变更频率组件的服务。如果大家发现自己经常需要同时对两项服务做出变更,那么明显应该将二者加以合并。

将组件纳入服务也让我们能够以更高的细粒度水平进行规划制定。在整体应用程序当中,任何一项变更都需要对应用整体进行重构与重新部署。但在微服务架构方面,我们只需要重新部署包含对应变更的服务。这能够显著简化并加快发布流程。不过其弊端在于,我们必须考虑针对单一服务的变更是否会影响到其它服务。传统的整体性方案能够通过版本控制解决这类难题,但微服务领域则倾向于将版本控制作为最后一种应急办法。我们可以通过设计保证服务拥有强大的容错能力,从而应对其供应程序中出现的各类代码修改。

微服务是否代表着未来?
我们撰写这篇文章的主要目的在于解释微服务架构的基本思路与原则。而在撰写过程当中,我们明确意识到微服务架构风格确实是一项值得重视的关键成果——企业级应用程序开发人员应当对其加以了解。我们最近利用该架构构建了多套系统,而且了解到亦有其它多家企业将其纳入业务体系。

我们了解到的微服务架构先驱企业包括Amazon、Netflix、英国《卫报》、英国政府数字化服务局、realestate.com.au、Forward以及comparethemarket.com等等。2013年召开的相关会议则公布了更多参与其中的重要厂商。除此之外,另有相当一部分企业一直在使用类似的实现思路——但却并没有使用‘微服务’这样的称谓。(其通常将其冠以SOA标签——不过正如我们之前提到,SOA是一类存在大量矛盾取向的概念组合。[15])

尽管拥有这些积极的经验,但我们仍然无法完全肯定微服务架构就代表着软件未来的发展方向。虽然我们的实际经历证明微服务架构截至目前仍拥有优于整体性应用程序的积极优势,但必须承认只有充分的时间积累才能帮助我们做出真正完整则准确的判断结论。


4444.jpg


我们的同事Sam Newman曾于2014年倾尽心力撰写出这本关于我们如何构建微服务架构类应用的论著。如果大家希望进一步探讨这个议题,请千万不要错过。

通常来说,架构决策的实际影响可能需要几年之后才能逐步显现出来。我们已经看到不少优秀的团队带着巨大的热情与愿景而投入工作,但最终却构建起一套陈旧不堪的整体性架构。很多人认为同样的情况不太可能发生在微服务架构身上,因为其服务边界非常明确因此不太可能发生相互影响。但由于时间尚短且系统程度不足,我们目前还无法真正评估微服务架构的成熟度水平。

人们对微服务成熟度抱持的怀疑态度也有其理由。在任何组件化尝试工作当中,最终结果的成功与否都取决于该软件与拆分后组件的契合效果。我们目前仍然很难说明组件边界的选择原则。演进设计导致边界划分变得非常困难,因此最重要的是保证其重构的简易性。但一旦将组件作为服务处理以实现远程通信,那么其重构难度将远远高于进程内库。在不同服务边界之间进行代码移动难度极大,而任何接口变更都需要在不同相关服务间实现,同时添加层的向下兼容能力,这无疑会令测试工作更加复杂。

另一大问题在于,如果相关组件间的关系不够简洁,那么我们就相当于把组件内部的复杂性转移到了不同组件间的连接当中。这样做不仅会导致复杂性扩散,同时亦会导致其明确性缺失且难以控制。立足于小型、简单组件审视问题总是更为直观,而在不同服务间进行纵览则往往会错失关注点。

最后,团队的技能水平也将起到决定性作用。新型技术成果往往要求高水平技术团队加以实施。不过高水平团队能够顺畅利用的技术方案并不一定能够在低水平人员手中发挥作用。我们已经见证了众多低水平团队构建起的如一团乱麻般的整体架构,但仍需要时间来了解微服务架构是否会在同样的情况下引发同样的状况。诚然,糟糕的团队创建出的始终只能是糟糕的系统——但我们不知道微服务架构到底是会缓解这种状况,还是令状况更中惨不忍睹。

目前有一种较为理性的论调,认为我们不应将微服务架构作为起步方案。相反,大家可以从整体性开发风格出发,保证其结合模块化机制,并在整体性特征引发实际问题后逐步将其拆分为微服务形式。(不过这样的建议并非完全理想,因为良好的进程内接口往往并不能成为良好的服务接口。)

因此我们对此抱持谨慎的乐观态度。到目前为止,我们已经了解到关于微服务架构的方方面面,而且其应该能够成为一种极具价值的开发手段。虽然还不能做出最终判断,但软件开发工作的固有挑战之一,正是我们只能根据目前掌握的远称不上完美的信息做出决策。

脚注
7: 虽然无关紧要,但Jim Webber曾经将ESB解释成“Egregious Spaghetti Box”,也就是“恐怖意面盒”。

8: Netflix公司最近将其架构类型称为“细化SOA”。

9: “YAGNI”的全称是“You Aren’t Going To Need It(你根本不需要它)”,这是一项经典的用户体验原则,即不要自作聪明地添加非必要性功能。

10: 我们所宣称的整体型应用只支持单一语言确实有些不尽不实——在当下的Web系统构建过程中,大家可能需要掌握JavaScript、XHTML以及CSS,而在服务器端的语言选项则包括SQL以及某种ORM(即对象关系映射)衍生语言。没错,单一语言肯定玩不转,但我相信大家明白我想要强调的意思。

11: Adrian Cockcroft在2013年11月的Flowcon大会上作出了精彩演讲,并特别提到了“开发者自助服务”与“开发者应亲自运行所编写代码”的观点。

12: 我们在这里的说法并不准确。很明显,在更为复杂的拓扑结构中部署大量服务肯定要比在单一整体型架构内进行部署困难得多。幸运的是,各类模式能够显著降低这种复杂性——当然,在工具方面的投入仍然不可或缺。

13: 事实上,Dan North将这种类型称为“可替代式组件架构”而非微服务架构。由于其强调内容属于微服务架构的一类子集,所以我们更倾向于使用后一种表达方式。

14: Kent Beck将此作为其《实施模式》一文中的设计原则之一。

15: SOA几乎是此类架构的历史起源。我记得当SOA一词在本世纪初刚刚出现时,很多人表示“我们几年前就已经将其引入日常工作了”。也有意见认为这种架构类型似乎最早出现于早期企业计算当中,COBOL程序通过数据文件实现通信的处理机制。而在另一方面,也有人认为微服务架构与Erlang编程模型其实是同一回事,不过后者只被应用在企业应用程序当中。

微服务概念解析(上)

宁静胡同 发表了文章 • 0 个评论 • 1196 次浏览 • 2016-02-03 19:00 • 来自相关话题

探讨这一全新架构术语的确切定义
“微服务架构”概念的提出已经有很长一段时间了,但在最近几年却开始频繁地出现。微服务架构是一种特定的软件应用程序设计方式——将大型软件拆分为多个独立可部署服务组合而成的套件方案。虽然这种架构风格的确切定义还存在争议,但并不妨碍其在众多企业的实际应用中被实践,并体现出了具备通用特征的业务功能、自动化部署、端点智能化以及对语言与数据的离散化控制能力。
 
Docker 作为一种开源的应用容器引擎,帮助开发者将他们的应用以及依赖打包到一个可移植的容器中,便于应用的部署和扩展。而随之产生的微容器概念和微服务正好相辅相成,通过 Docker 封装的应用可以轻松运行在以扩容能力见长的云计算平台上。数人云作为专业的数据中心管理系统,提供了基于 Mesos 和 Docker 技术的企业级容器云生产环境,通过一键部署、横向扩展、持续集成等特性,助力微服务架构在企业应用环境的实践。
 
由于篇幅问题,本文将分上下两篇,下篇将于明天放送给大家。

“微服务”——目前可谓早已人满为患的软件架构领域的新兴名词。虽然我们对于这种新生事物往往带着一种先入为主的蔑视与忽略态度,但经过几年的历练,我们发现这种软件构建风格正变得越来越具有吸引力。过去几年中已经有诸多企业将其引入实际项目,而至今其结果仍然相当积极,这甚至促使很多同业人士开始将微服务架构作为企业级应用程序的默认开发途径。但遗憾的是,目前仍然缺乏一套系统的概念定义,告诉我们微服务到底是如何实现这些成效的。

简而言之,微服务架构风格[1]是一类将单一应用程序作为由众多小型服务构成之套件加以开发的方式,其中各项服务都拥有自己的进程并利用轻量化机制(通常为HTTP源API)实现通信。这些服务围绕业务功能建立而成,且凭借自动化部署机制实现独立部署。这些服务匹配一套最低限度的中央式管理机制,且各服务可通过不同编程语言编写而成并使用不同的数据存储技术。






要解释微服务风格,那么首先应当将其与整体风格进行比较:整体应用程序作为单一单元进行构建。企业级应用程序通常包含三个组成部分:一套客户端用户界面(由运行在用户设备上的浏览器中的HTML页面以及JavaScript代码构成)、一套后端数据库(将大量插入至数据库管理系统的大量表构成,通常采用关系数据库)以及一款服务器端应用程序。该服务器端应用程序将负责处理HTTP请求、执行域逻辑、对来自数据库的数据进行检索与更新,同时选定HTML视图并将其发送至浏览器端。此服务器端应用程序通常为单一的逻辑可执行文件[2]。任何针对该系统的变更都需要对该服务器端应用程序进行新版本构建与部署。

这样的整体服务器机制在构建此类系统中可谓不可或缺。我们用于处理请求的全部逻辑都运行在单一进程当中,允许大家使用语言中的基本功能以将该应用程序拆分为类、函数以及命名空间。通过这种方式,我们能够在开发人员的笔记本设备上运行并测试应用程序,同时利用一整套部署流程以确保全部变更都经过妥善测试而后被部署在生产环境当中。大家可以将大量实例运行在一套负载均衡方案之后,从而实现横向扩展能力。

这类整体应用程序当然能够切实起效,但人们却逐渐发现其中存在着诸多弊端——特别是在将大量应用程序部署在云环境当中的情况下。由于变更周期被大量集中于一处——即使仅仅指向应用程序中的一小部分,单一变更亦要求我们对应用程序整体进行重构与重新部署。随着时间推移,我们往往很难保证理想的模块化结构,这意味着本应只影响单一模块的变更往往会扩散至该模块之外。规模伸缩亦要求我们对整体应用程序进行规模调整,而非单纯为其中必要的部分进行资源扩容。







图一:整体型应用程序与微服务架构应用程序

正是这些弊端造就了如今的微服务架构风格:即以服务套件的形式构建应用程序。除了各服务能够单独进行部署与规模伸缩之外,每项服务还具备牢固的模块边界,甚至允许我们在不同的服务当中使用不同的编程语言进行代码编写。另外,各服务亦可由不同团队负责管理。

我们认为微服务风格并不算什么新鲜事物或者创新成果,其历史至少可以追溯至Unix设计时代。但我们同时亦坚信,微服务架构一直未能受到足够的重视,而其确实能够帮助大家更好地完成软件开发工作。

微服务架构之特性

我们无法给微服务架构风格出具一条确切的定义,但我们却可以根据该架构表现出的各类共同特性对其加以描述。正如各类根据共同特性做出的定义一样,并不是所有微服务架构都符合这些特性,但可以肯定的是具备这些特性的微服务架构占据大部分比例。尽管我们各部分内容的作者仅仅是相关技术社区中的活跃成员,但制作这份文档是为了对采用微服务架构的工作流程及成果做出总结,而且其中仍有相当一部分表述并非严格定义——只应作为常见情况考量。

通过服务实现组件化

长久以来,我们一直参与软件行业之内并意识到人们对利用组件整合方式构建系统的渴望——这种思路与我们在物理世界中采取的构建机制非常相似。而在过去几十年当中,我们发现已经有大量公共库渗透到多数语言平台当中并成为其坚实的组成部分。

在谈到我们所使用的组件时,大家可能会发现不同群体对组件的定义也有所区别。我们对组件做出的定义是,其属于软件中的一类单元,且具备可更替性与可升级性。

微服务架构会使用这些库,但其实现组件化的主要手段则是将软件拆分成多个服务。我们将“库”定义为与程序相对接且可通过内存内函数调用发挥作用的组件,而“服务”则为进程之外的组件,其可通过Web服务请求或者远程程序调用等方式实现通信。(这里的服务概念与多数OO程序中的服务对象概念有所区别[3])。

将服务作为组件加以使用(而非库)的一大原因在于,服务具备独立可部署能力。如果大家的应用程序[4]由单一进程中的多个库构成,那么指向任何单一组件的变更都会致使该应用程序必须进行重新部署。但如果该应用程序被拆分成多项服务,那么单一服务变更将只会致使该服务进行重新部署。虽然这并非绝对,例如某些变更会导致服务接口受到影响,但一套优秀的微服务架构旨在尽可能少地对服务协议中的服务边界及演进机制产生干扰。

将服务作为组件的另一个理由在于实现更为明确的组件接口。大多数编程语言并不具备用于定义明确发布接口的良好机制。一般来讲,其只会提供说明文档及规则以防止用户打破组件封装,但这同时亦会导致不同组件之间的耦合程度过高。利用明确的远程调用机制,服务能够轻松避免此类难题。

但以这种方式使用服务亦存在一定弊端。远程调用在资源需求方面往往远高于进程内调用,因此远程API需要采取粗粒度设计,但这亦会增加API的使用难度。如果大家需要更改不同组件间的职能分配,那么这类需求在跨越进程边界时往往不易实现。

通过粗略观察,我们往往会发现这些服务会与各运行时进程相映射——但这仅仅只是第一印象。一项服务可能由多个进程构成,且各进程始终共同进行开发与部署——这方面实例包括只由单一服务所使用的应用程序进程以及数据库。

围绕业务功能构建组织

当着眼于将单一大型应用程序拆分成多个组成部分时,管理人员通常更重视技术层,其中具体包括UI团队、服务器端逻辑团队以及数据库团队。当这些团队据此进行拆分时,即使是最简单的变更也将给项目造成跨团队协作负担,并因此导致时间与预算的双重支出。睿智的团队会对此进行优化,同时采取两害相权取其轻的办法——即强制要求逻辑存在于一切与之相对接的应用程序当中。换言之,也就是实现逻辑的普遍存在性。这正是所谓康威法则[5]的一种实际表现形式。

任何组织在设计一套系统(广义层面的系统)时,其设计成果都会直接体现该组织所使用的沟通结构。
--梅尔文·康威,1967年







图二:康威定律的实际体现

微服务方案对于各部门而言是一种不同于以往,且以业务功能为核心的服务拆分及组织途径。此类服务采用软件方案在业务层面中的广泛实现堆栈,具体包括用户界面、持久性存储以及任何外部协作机制。因此,各团队将拥有跨职能特性,包括开发过程当中要求的全部技能组合:用户体验、数据库以及项目管理等等。







图三:由团队边界决定的服务边界

微服务架构有多“微”?
尽管“微服务”早已成为一种极具人气的架构类型,但这一名称却并不能准确反映服务的实际规模——换言之,“微”服务并不一定微。在与众多微服务从业者的交流当中,我们发现服务的具体规模可谓多种多样。其中规模最大的成果源自Amazon公司旗下的“两块披萨”团队(即整个团队只需两块披萨即可填饱肚子),这意味着其总人数在十位左右。而规模较小的团队则由六人组成,负责支持六项服务。

那么这就带来了新的问题:这种十二人对单项服务的机制同一人对单项服务之间存在着怎样的差别?二者也许不可一概而论。就目前而言,我们姑且认为双方属于同类团队结构,但随着对微服务认识的持续深入,也许我们未来将抱持新的观点。

采取此类组织方式的企业实例可参见www.comparethemarket.com,其各职能团队共同负责构建并运营每款产品,而每款产品则被拆分为一系列独立的服务——且各服务间通过一套消息收发总线实现通信。   

大型整体应用程序亦可以始终围绕业务功能实际模块化,不过这种状况并不常见。诚然,我们都听说过由大型团队构建的单一整体应用程序根据自身业务线进行设计与划分。然而在这类情况下,最大的问题在于整体应用程序在组织当中需要考虑太多背景信息。如果其整体范畴当中包含太多模块边界,那么团队中的单一成员将很难通过短期记忆对其进行管理。除此之外,我们发现这种模块化业务线的维护工作还要求相关人员具备极高的专业技能水平。相比之下,服务组件能够令拆分方式更为明确,从而大大简化团队边界的设定与认知。

产品而非项目

大部分应用程序开发工作都会遵循项目模式:其目标在于交付软件方案中的特定部分,并拥有直观的完成指标。在软件开发工作完成后,其会被传递至运维部门,这时负责构建该软件的团队也将即刻解散。

微服务的支持者们则认为这种模式并不可取——他们的主张是相关团队应该伴随产品走过整个生命周期。这方面最典型的例子应该是Amazon公司提出的“谁构建,谁运行”原则,其中开发团队需要对生产环境下的软件成果承担全部责任。这就要求开发人员在日常工作中全程关注其软件的生产运行情况,同时掌握来自用户的反馈意见,意味着他们需要在一定程度上为用户提供技术支持服务。

产品的定位应始终与业务功能相协调。相较于以往将软件视为一整套已经完成的功能集的心态,微服务架构要求我们全程与之保持关联,并思考该软件能够如何协助用户加强业务功能。

当然,我们完全可以将同样的思路引入整体应用程序当中,不过大量小型服务集合能够显著简化服务开发人员与及用户之间的个人联系。

智能化端点与傻瓜式流程

在跨越不同进程构建通信结构时,我们发现很多产品及方案会直接把智能化机制塞进通信机制本体当中。这方面的典型实例就是企业服务总线(简称ESB),ESB产品当中通常包含复杂度极高的消息跌幅、编排、转换以及业务规则应用等机制。

微服务社区则倾向于使用另一种实现方式:智能化端点与傻瓜式流程。采用微服务架构的应用程序旨在尽可能实现解耦化与关联性——它们各自拥有自己的域逻辑,而且在经典Unix场景下的运作方式更像是过滤器机制——接收请求、应用合适的逻辑并生成响应。这一切都通过简单的REST类协议实现编排,而非经由WS-Choreography或者BPEL等复杂协议以及中央编排工具实现。

目前最常用的两类协议为配合源API的HTTP请求-响应与轻量化消息收发协议[6]。对于前者,最简练而准确的说明是:

立足于Web,而非居于Web背后。
-- Ian Robinson

微服务团队采用的正是万维网(在很大程度上亦包括Unix在内)所遵循的原则与协议。一般来讲,其使用的资源能够为开发人员或者运维人员轻松实现缓存处理。

第二类作法则是立足于轻量化消息总线实现消息收发。这类基础设施选项通常具备傻瓜式特性(这种傻瓜特性体现在实现操作上,即只需匹配消息路由机制,再无其它)——以RabbitMQ或者ZeroMQ为代表的简单实现方案仅仅需要提供一套可靠的异步结构,而服务的全部智能化元素仍然存在于端点当中并负责消息的生成与消费。

在整体应用程序当中,各组件在进程内执行并通过方法调用或者函数调用的方式实现彼此通信。将整体应用程序转化为微服务形式的最大难题在于改变这种通信模式。由内存内方法调用指向PC通信机制的简单转换往往无法良好起效。相反,大家需要利用粗粒度方式取代原本的细粒度通信机制。

脚注
1: “微服务”一词最早被威尼斯附近的一个软件架构师小组于2011年5月首次提及,当时他们用这个词汇来描述自己近期研究项目当中所涉及的通用性架构机制。2012年5月,该小组作出最终决议,认为“微服务”是最适合的架构名称。2012年3月,James在《微服务-Java以及Unix方式》当中就此发表了一篇案例研究报告,而Fred George也几乎在同一时间进行了相同的工作。Netflix公司的Adrian Cockcroft将微服务架构称为“细化SOA”,并认为这是一套在Web规模下具备开创意义的架构类型。Joe Walnes、Dan North、Evan Botcher以及Graham Tackley也分别在这篇文章中对此作出了评论。

2: 文章中所使用的“整体”一词长久以来一直被Unix业界所使用。其首次出现在《Unix编程艺术》一书中,用于描述那些过于庞大的系统方案。

3: 很多面向对象设计人员,也包括我们自己,都会在域驱动设计当中使用“服务对象”这一表述,专指那些并不具备实质性联系但却拥有重要作用的对象。这与我们在本文中所使用的“服务”一词在表意上完全不同。遗憾的是,服务这个词汇同时具备两种含义,而我们对这种多义词也没有更好的处理办法。

4: 我们将一款应用程序视为一套社会性体系,其中融合了代码库、函数组以及供应主体。

5: 大家可以查看梅尔文 康韦网站上的原文论述。

6: 对于规模极为庞大的应用体系,企业通常会采用二进制协议——例如protobufs。使用二进制协议的系统仍然符合智能化端点与傻瓜式通道的特性——并为了规模化而在透明度方面作出妥协。不过大多数Web方案与绝大多数企业不需要在这方面考虑太多——一般来讲,透明度越高、效果就越好。
  查看全部
探讨这一全新架构术语的确切定义

“微服务架构”概念的提出已经有很长一段时间了,但在最近几年却开始频繁地出现。微服务架构是一种特定的软件应用程序设计方式——将大型软件拆分为多个独立可部署服务组合而成的套件方案。虽然这种架构风格的确切定义还存在争议,但并不妨碍其在众多企业的实际应用中被实践,并体现出了具备通用特征的业务功能、自动化部署、端点智能化以及对语言与数据的离散化控制能力。
 
Docker 作为一种开源的应用容器引擎,帮助开发者将他们的应用以及依赖打包到一个可移植的容器中,便于应用的部署和扩展。而随之产生的微容器概念和微服务正好相辅相成,通过 Docker 封装的应用可以轻松运行在以扩容能力见长的云计算平台上。数人云作为专业的数据中心管理系统,提供了基于 Mesos 和 Docker 技术的企业级容器云生产环境,通过一键部署、横向扩展、持续集成等特性,助力微服务架构在企业应用环境的实践。
 
由于篇幅问题,本文将分上下两篇,下篇将于明天放送给大家。



“微服务”——目前可谓早已人满为患的软件架构领域的新兴名词。虽然我们对于这种新生事物往往带着一种先入为主的蔑视与忽略态度,但经过几年的历练,我们发现这种软件构建风格正变得越来越具有吸引力。过去几年中已经有诸多企业将其引入实际项目,而至今其结果仍然相当积极,这甚至促使很多同业人士开始将微服务架构作为企业级应用程序的默认开发途径。但遗憾的是,目前仍然缺乏一套系统的概念定义,告诉我们微服务到底是如何实现这些成效的。

简而言之,微服务架构风格[1]是一类将单一应用程序作为由众多小型服务构成之套件加以开发的方式,其中各项服务都拥有自己的进程并利用轻量化机制(通常为HTTP源API)实现通信。这些服务围绕业务功能建立而成,且凭借自动化部署机制实现独立部署。这些服务匹配一套最低限度的中央式管理机制,且各服务可通过不同编程语言编写而成并使用不同的数据存储技术。

1.jpg


要解释微服务风格,那么首先应当将其与整体风格进行比较:整体应用程序作为单一单元进行构建。企业级应用程序通常包含三个组成部分:一套客户端用户界面(由运行在用户设备上的浏览器中的HTML页面以及JavaScript代码构成)、一套后端数据库(将大量插入至数据库管理系统的大量表构成,通常采用关系数据库)以及一款服务器端应用程序。该服务器端应用程序将负责处理HTTP请求、执行域逻辑、对来自数据库的数据进行检索与更新,同时选定HTML视图并将其发送至浏览器端。此服务器端应用程序通常为单一的逻辑可执行文件[2]。任何针对该系统的变更都需要对该服务器端应用程序进行新版本构建与部署。

这样的整体服务器机制在构建此类系统中可谓不可或缺。我们用于处理请求的全部逻辑都运行在单一进程当中,允许大家使用语言中的基本功能以将该应用程序拆分为类、函数以及命名空间。通过这种方式,我们能够在开发人员的笔记本设备上运行并测试应用程序,同时利用一整套部署流程以确保全部变更都经过妥善测试而后被部署在生产环境当中。大家可以将大量实例运行在一套负载均衡方案之后,从而实现横向扩展能力。

这类整体应用程序当然能够切实起效,但人们却逐渐发现其中存在着诸多弊端——特别是在将大量应用程序部署在云环境当中的情况下。由于变更周期被大量集中于一处——即使仅仅指向应用程序中的一小部分,单一变更亦要求我们对应用程序整体进行重构与重新部署。随着时间推移,我们往往很难保证理想的模块化结构,这意味着本应只影响单一模块的变更往往会扩散至该模块之外。规模伸缩亦要求我们对整体应用程序进行规模调整,而非单纯为其中必要的部分进行资源扩容。


2.jpg


图一:整体型应用程序与微服务架构应用程序

正是这些弊端造就了如今的微服务架构风格:即以服务套件的形式构建应用程序。除了各服务能够单独进行部署与规模伸缩之外,每项服务还具备牢固的模块边界,甚至允许我们在不同的服务当中使用不同的编程语言进行代码编写。另外,各服务亦可由不同团队负责管理。

我们认为微服务风格并不算什么新鲜事物或者创新成果,其历史至少可以追溯至Unix设计时代。但我们同时亦坚信,微服务架构一直未能受到足够的重视,而其确实能够帮助大家更好地完成软件开发工作。

微服务架构之特性

我们无法给微服务架构风格出具一条确切的定义,但我们却可以根据该架构表现出的各类共同特性对其加以描述。正如各类根据共同特性做出的定义一样,并不是所有微服务架构都符合这些特性,但可以肯定的是具备这些特性的微服务架构占据大部分比例。尽管我们各部分内容的作者仅仅是相关技术社区中的活跃成员,但制作这份文档是为了对采用微服务架构的工作流程及成果做出总结,而且其中仍有相当一部分表述并非严格定义——只应作为常见情况考量。

通过服务实现组件化

长久以来,我们一直参与软件行业之内并意识到人们对利用组件整合方式构建系统的渴望——这种思路与我们在物理世界中采取的构建机制非常相似。而在过去几十年当中,我们发现已经有大量公共库渗透到多数语言平台当中并成为其坚实的组成部分。

在谈到我们所使用的组件时,大家可能会发现不同群体对组件的定义也有所区别。我们对组件做出的定义是,其属于软件中的一类单元,且具备可更替性与可升级性。

微服务架构会使用这些库,但其实现组件化的主要手段则是将软件拆分成多个服务。我们将“库”定义为与程序相对接且可通过内存内函数调用发挥作用的组件,而“服务”则为进程之外的组件,其可通过Web服务请求或者远程程序调用等方式实现通信。(这里的服务概念与多数OO程序中的服务对象概念有所区别[3])。

将服务作为组件加以使用(而非库)的一大原因在于,服务具备独立可部署能力。如果大家的应用程序[4]由单一进程中的多个库构成,那么指向任何单一组件的变更都会致使该应用程序必须进行重新部署。但如果该应用程序被拆分成多项服务,那么单一服务变更将只会致使该服务进行重新部署。虽然这并非绝对,例如某些变更会导致服务接口受到影响,但一套优秀的微服务架构旨在尽可能少地对服务协议中的服务边界及演进机制产生干扰。

将服务作为组件的另一个理由在于实现更为明确的组件接口。大多数编程语言并不具备用于定义明确发布接口的良好机制。一般来讲,其只会提供说明文档及规则以防止用户打破组件封装,但这同时亦会导致不同组件之间的耦合程度过高。利用明确的远程调用机制,服务能够轻松避免此类难题。

但以这种方式使用服务亦存在一定弊端。远程调用在资源需求方面往往远高于进程内调用,因此远程API需要采取粗粒度设计,但这亦会增加API的使用难度。如果大家需要更改不同组件间的职能分配,那么这类需求在跨越进程边界时往往不易实现。

通过粗略观察,我们往往会发现这些服务会与各运行时进程相映射——但这仅仅只是第一印象。一项服务可能由多个进程构成,且各进程始终共同进行开发与部署——这方面实例包括只由单一服务所使用的应用程序进程以及数据库。

围绕业务功能构建组织

当着眼于将单一大型应用程序拆分成多个组成部分时,管理人员通常更重视技术层,其中具体包括UI团队、服务器端逻辑团队以及数据库团队。当这些团队据此进行拆分时,即使是最简单的变更也将给项目造成跨团队协作负担,并因此导致时间与预算的双重支出。睿智的团队会对此进行优化,同时采取两害相权取其轻的办法——即强制要求逻辑存在于一切与之相对接的应用程序当中。换言之,也就是实现逻辑的普遍存在性。这正是所谓康威法则[5]的一种实际表现形式。

任何组织在设计一套系统(广义层面的系统)时,其设计成果都会直接体现该组织所使用的沟通结构。
--梅尔文·康威,1967年



3.jpg


图二:康威定律的实际体现

微服务方案对于各部门而言是一种不同于以往,且以业务功能为核心的服务拆分及组织途径。此类服务采用软件方案在业务层面中的广泛实现堆栈,具体包括用户界面、持久性存储以及任何外部协作机制。因此,各团队将拥有跨职能特性,包括开发过程当中要求的全部技能组合:用户体验、数据库以及项目管理等等。


4.jpg


图三:由团队边界决定的服务边界

微服务架构有多“微”?
尽管“微服务”早已成为一种极具人气的架构类型,但这一名称却并不能准确反映服务的实际规模——换言之,“微”服务并不一定微。在与众多微服务从业者的交流当中,我们发现服务的具体规模可谓多种多样。其中规模最大的成果源自Amazon公司旗下的“两块披萨”团队(即整个团队只需两块披萨即可填饱肚子),这意味着其总人数在十位左右。而规模较小的团队则由六人组成,负责支持六项服务。

那么这就带来了新的问题:这种十二人对单项服务的机制同一人对单项服务之间存在着怎样的差别?二者也许不可一概而论。就目前而言,我们姑且认为双方属于同类团队结构,但随着对微服务认识的持续深入,也许我们未来将抱持新的观点。

采取此类组织方式的企业实例可参见www.comparethemarket.com,其各职能团队共同负责构建并运营每款产品,而每款产品则被拆分为一系列独立的服务——且各服务间通过一套消息收发总线实现通信。   

大型整体应用程序亦可以始终围绕业务功能实际模块化,不过这种状况并不常见。诚然,我们都听说过由大型团队构建的单一整体应用程序根据自身业务线进行设计与划分。然而在这类情况下,最大的问题在于整体应用程序在组织当中需要考虑太多背景信息。如果其整体范畴当中包含太多模块边界,那么团队中的单一成员将很难通过短期记忆对其进行管理。除此之外,我们发现这种模块化业务线的维护工作还要求相关人员具备极高的专业技能水平。相比之下,服务组件能够令拆分方式更为明确,从而大大简化团队边界的设定与认知。

产品而非项目

大部分应用程序开发工作都会遵循项目模式:其目标在于交付软件方案中的特定部分,并拥有直观的完成指标。在软件开发工作完成后,其会被传递至运维部门,这时负责构建该软件的团队也将即刻解散。

微服务的支持者们则认为这种模式并不可取——他们的主张是相关团队应该伴随产品走过整个生命周期。这方面最典型的例子应该是Amazon公司提出的“谁构建,谁运行”原则,其中开发团队需要对生产环境下的软件成果承担全部责任。这就要求开发人员在日常工作中全程关注其软件的生产运行情况,同时掌握来自用户的反馈意见,意味着他们需要在一定程度上为用户提供技术支持服务。

产品的定位应始终与业务功能相协调。相较于以往将软件视为一整套已经完成的功能集的心态,微服务架构要求我们全程与之保持关联,并思考该软件能够如何协助用户加强业务功能。

当然,我们完全可以将同样的思路引入整体应用程序当中,不过大量小型服务集合能够显著简化服务开发人员与及用户之间的个人联系。

智能化端点与傻瓜式流程

在跨越不同进程构建通信结构时,我们发现很多产品及方案会直接把智能化机制塞进通信机制本体当中。这方面的典型实例就是企业服务总线(简称ESB),ESB产品当中通常包含复杂度极高的消息跌幅、编排、转换以及业务规则应用等机制。

微服务社区则倾向于使用另一种实现方式:智能化端点与傻瓜式流程。采用微服务架构的应用程序旨在尽可能实现解耦化与关联性——它们各自拥有自己的域逻辑,而且在经典Unix场景下的运作方式更像是过滤器机制——接收请求、应用合适的逻辑并生成响应。这一切都通过简单的REST类协议实现编排,而非经由WS-Choreography或者BPEL等复杂协议以及中央编排工具实现。

目前最常用的两类协议为配合源API的HTTP请求-响应与轻量化消息收发协议[6]。对于前者,最简练而准确的说明是:

立足于Web,而非居于Web背后。
-- Ian Robinson


微服务团队采用的正是万维网(在很大程度上亦包括Unix在内)所遵循的原则与协议。一般来讲,其使用的资源能够为开发人员或者运维人员轻松实现缓存处理。

第二类作法则是立足于轻量化消息总线实现消息收发。这类基础设施选项通常具备傻瓜式特性(这种傻瓜特性体现在实现操作上,即只需匹配消息路由机制,再无其它)——以RabbitMQ或者ZeroMQ为代表的简单实现方案仅仅需要提供一套可靠的异步结构,而服务的全部智能化元素仍然存在于端点当中并负责消息的生成与消费。

在整体应用程序当中,各组件在进程内执行并通过方法调用或者函数调用的方式实现彼此通信。将整体应用程序转化为微服务形式的最大难题在于改变这种通信模式。由内存内方法调用指向PC通信机制的简单转换往往无法良好起效。相反,大家需要利用粗粒度方式取代原本的细粒度通信机制。

脚注
1: “微服务”一词最早被威尼斯附近的一个软件架构师小组于2011年5月首次提及,当时他们用这个词汇来描述自己近期研究项目当中所涉及的通用性架构机制。2012年5月,该小组作出最终决议,认为“微服务”是最适合的架构名称。2012年3月,James在《微服务-Java以及Unix方式》当中就此发表了一篇案例研究报告,而Fred George也几乎在同一时间进行了相同的工作。Netflix公司的Adrian Cockcroft将微服务架构称为“细化SOA”,并认为这是一套在Web规模下具备开创意义的架构类型。Joe Walnes、Dan North、Evan Botcher以及Graham Tackley也分别在这篇文章中对此作出了评论。

2: 文章中所使用的“整体”一词长久以来一直被Unix业界所使用。其首次出现在《Unix编程艺术》一书中,用于描述那些过于庞大的系统方案。

3: 很多面向对象设计人员,也包括我们自己,都会在域驱动设计当中使用“服务对象”这一表述,专指那些并不具备实质性联系但却拥有重要作用的对象。这与我们在本文中所使用的“服务”一词在表意上完全不同。遗憾的是,服务这个词汇同时具备两种含义,而我们对这种多义词也没有更好的处理办法。

4: 我们将一款应用程序视为一套社会性体系,其中融合了代码库、函数组以及供应主体。

5: 大家可以查看梅尔文 康韦网站上的原文论述。

6: 对于规模极为庞大的应用体系,企业通常会采用二进制协议——例如protobufs。使用二进制协议的系统仍然符合智能化端点与傻瓜式通道的特性——并为了规模化而在透明度方面作出妥协。不过大多数Web方案与绝大多数企业不需要在这方面考虑太多——一般来讲,透明度越高、效果就越好。
 

将 HDFS 搬上数人云:轻松实现集群的扩展收缩

宁静胡同 发表了文章 • 0 个评论 • 824 次浏览 • 2016-02-02 18:23 • 来自相关话题

HDFS 是 Hadoop Distributed File System 的简称,作为 Apache Hadoop Core 项目的一部分,提供了一个高度容错性的分布式文件系统,适合部署在廉价的机器上。HDFS 可以提供高吞吐量的数据访问,非常适合大规模数据集上的应用,很多大数据框架都已 HDFS 作为其存储方案,如 Hadoop、Spark、HBase 等。
 
作为分布式文件系统,HDFS 需要集群化部署,并会随着业务量的增加而不断扩展。但 HDFS 集群化部署并非易事,很多组织和项目都在尝试简化部署方法,网络上也存在着大量参差不齐的教程。这里介绍一种方式,通过数人云快速部署 HDFS 集群,并轻松实现集群的扩展和收缩,一起来体验一下吧!


第一步 镜像制作

数人云可以发布各种 Docker 应用,并进行统一管理和监控,因此,第一步是将 HDFS 集群的组件 Docker 化。

HDFS 集群有两种节点,以“管理者-工作者”的模式运行,一个 Namenode(管理者)和多个 Datanode(工作者)。Namenode 作为管理者,管理文件系统的命名空间,维护文件系统树及树内所有的文件和索引目录。Datanode 作为文件系统的工作者,存储并提供定位块的服务,并且定时向 Namenode 发送它们存储的块列表。用户通过 HDFS 客户端可以进行文件的读写操作,大致方式是通过 Namenode 获得Datanode 和存数块的信息,对 Datanode 进行数据写入或读取。其架构如下图所示。







如上图所示,一个 HDFS 集群至少需要两种 Docker 应用,Namenode 和 Datanode。

首先,Namenode 和 Datanode 都使用相同的 Hadoop 安装包,因此,先做一个安装了 Hadoop 基础环境依赖及 Hadoop 的基础镜像,具体内容见[https://github.com/Dataman-Cloud/hadoop-base]。

有了基础镜像,就可以制作 Namenode 和 Datanode 的镜像了。这里主要是加入不同的配置文件和启动脚本。

1 Namenode 制作

先说 Namenode,需要配置以下配置项:

1. fs.defaultFS:设置缺省的访问地址,需在 core-site.xml 中设置。这里设置为 hdfs://0.0.0.0:8020,表示本机的8020端口。
2. dfs.permissions:权限检查开关,需要在 hdfs-site.xml 中设置。如果没有权限控制要求,则设置为 false。
3. dfs.name.dir:Namenode 的数据存储路径,需要在 hdfs-site.xml 中设置。
4. dfs.namenode.datanode.registration.ip-hostname-check:Datanode 的主机名解析检查,需要在 hdfs-site.xml 中设置。如果没有特殊的安全性考虑,设置为 false。

启动 Namenode 时,需要判断是否是首次部署,若首次部署,则需要进行格式化。 if [ ! -f ${HDFS_NAMENODE_ROOT_DIR}/current/VERSION ]; then
echo Formatting namenode root fs in ${HDFS_NN_ROOT_DIR}

bin/hdfs namenode -format
fi

最后,就可以启动 Namenode 了。

具体的 Dockerfile 和相关文件见https://github.com/Dataman-Cloud/hdfs-namenode。

2 Datanode 制作

再说 Datanode,需要配置一下配置项:

1. dfs.permissions:同 Namenode。
2. dfs.data.dir:Datanode 的数据存储路径,需要在 hdfs-site.xml 中设置。

启动 Datanode 时,需要指定 Namenode,这里通过```HDFS_NAMENODE_RPC_HOST```和```HDFS_NAMENODE_RPC_PORT```两个环境变量来设置 Namenode 地址,并写入 core-site.xml 配置文件,脚本如下: sed "s/HDFS_NAMENODE_RPC_HOST/$HDFS_NAMENODE_RPC_HOST/;s/HDFS_NAMENODE_RPC_PORT/$HDFS_NAMENODE_RPC_PORT/" ${HADOOP_INSTALL_DIR}/etc/hadoop/core-site.xml.template > ${HADOOP_INSTALL_DIR}/etc/hadoop/core-site.xml

最后,就可以启动 Datanode 了。
具体的 Dockerfile 和相关文件见https://github.com/Dataman-Cloud/hdfs-datanode。
注:以上只是描述了 HDFS 最少的必要配置,其他配置项请根据自己的实际使用需求进行添加。

第二步 部署

数人云作为云时代的操作系统,统一管理和调度集群的计算资源,并以 Docker 的形式发布和管理应用。我们先将自己的计算资源(云主机、虚拟机或是物理机)创建一个数人云集群,就可以在该集群上部署 HDFS 集群了。具体的创建集群方法见(https://github.com/Dataman-Cloud/hdfs-datanode)。

1 新建应用hdfs-namenode:

>以下镜像由数人云提供,仅用于测试。若生产环境使用,请构建自己的镜像仓库和 Docker 镜像。

* 应用名称: hdfs-namenode
* 选择集群: (选择你的集群)
* 镜像地址: index.shurenyun.com/dataman/hdfs-namenode
* 镜像版本: 2.7.1
* 网络模式: HOST
* 选择主机: 标签不选; 主机: (选择一台主机)
* 挂载点:
  * 数据路径: /home/data/hdfs-namenode, 容器路径: /var/hdfs/namenode
* 容器规格
  * CPU: 0.5
  * 内存: 1024MB
* 容器个数: 1,不勾选1容器:1主机
* 高级设置
  * 应用地址
  * 环境变量
  
注:挂载点的“容器路径”就是```dfs.name.dir```的取值。

2 新建应用hdfs-datanode:

* 应用名称: hdfs-datanode
* 选择集群: (选择你的集群)
* 镜像地址: index.shurenyun.com/dataman/hdfs-datanode
* 镜像版本: 2.7.1
* 网络模式: HOST
* 选择主机: 标签不选; 主机:(选择你要部署的主机)
* 挂载点:
  * 数据路径: /home/data/hdfs-datanode, 容器路径: /var/hdfs/datanode
* 容器规格
  * CPU: 0.5
  * 内存: 1024MB
* 容器个数: 3(需要启动的节点数),勾选1容器:1主机
* 高级设置
  * 应用地址
  * 环境变量
    * KEY: HDFS_NAMENODE_RPC_HOST, VALUE: (Namenode 所在节点的 IP)
    * KEY: HDFS_NAMENODE_RPC_PORT, VALUE: (Namenode 的访问端口,与```fs.defaultFS```取值一致,默认为8020)

>注:挂载点的“容器路径”就是```dfs.data.dir```的取值。

创建应用后,进入应用详情页的事件标签页,查看部署的操作状态,显示

```应用名称:hdfs-namenode 事件类型:应用扩展操作 事件结果:部署操作成功

应用名称:hdfs-datanode 事件类型:应用扩展操作 事件结果:部署操作成功
```

同时,应用状态显示为

```
应用状态:运行中
```

则应用部署已经成功。

访问namenode地址,http:// HDFS_NAMENODE_RPC_HOST:50070。
结束语

有以下几点说明:

1. 集群扩展:HDFS 的 Datanode 可以通过数人云的应用扩展功能轻松实现扩展。但需要注意,如果在“选择主机”处选择了固定数量的主机,则 Datanode 数量不能超过选定的主机数。
2. 资源分配:通过数人云管理界面发布应用时,目前最大容器规格限定在1CPU、4G 内存,这对于一些大数据环境是不够的,你可能需要给这些应用分配更多的资源。这一点可以通过数人云 API 实现,不受限制地分配资源给任一容器。
3. 单点问题:本文中部署的 HDFS 集群只有一个 Namenode,存在单点问题。HDFS 提供了解决单点问题的方法,需要 Journalnode 和 Zookeeper。作为一种高可用的、用于生产环境的 HDFS 集群部署方法,数人云同样可以做到快速部署,将在稍后介绍。 查看全部


HDFS 是 Hadoop Distributed File System 的简称,作为 Apache Hadoop Core 项目的一部分,提供了一个高度容错性的分布式文件系统,适合部署在廉价的机器上。HDFS 可以提供高吞吐量的数据访问,非常适合大规模数据集上的应用,很多大数据框架都已 HDFS 作为其存储方案,如 Hadoop、Spark、HBase 等。
 
作为分布式文件系统,HDFS 需要集群化部署,并会随着业务量的增加而不断扩展。但 HDFS 集群化部署并非易事,很多组织和项目都在尝试简化部署方法,网络上也存在着大量参差不齐的教程。这里介绍一种方式,通过数人云快速部署 HDFS 集群,并轻松实现集群的扩展和收缩,一起来体验一下吧!



第一步 镜像制作

数人云可以发布各种 Docker 应用,并进行统一管理和监控,因此,第一步是将 HDFS 集群的组件 Docker 化。

HDFS 集群有两种节点,以“管理者-工作者”的模式运行,一个 Namenode(管理者)和多个 Datanode(工作者)。Namenode 作为管理者,管理文件系统的命名空间,维护文件系统树及树内所有的文件和索引目录。Datanode 作为文件系统的工作者,存储并提供定位块的服务,并且定时向 Namenode 发送它们存储的块列表。用户通过 HDFS 客户端可以进行文件的读写操作,大致方式是通过 Namenode 获得Datanode 和存数块的信息,对 Datanode 进行数据写入或读取。其架构如下图所示。


1.png


如上图所示,一个 HDFS 集群至少需要两种 Docker 应用,Namenode 和 Datanode。

首先,Namenode 和 Datanode 都使用相同的 Hadoop 安装包,因此,先做一个安装了 Hadoop 基础环境依赖及 Hadoop 的基础镜像,具体内容见[https://github.com/Dataman-Cloud/hadoop-base]。

有了基础镜像,就可以制作 Namenode 和 Datanode 的镜像了。这里主要是加入不同的配置文件和启动脚本。

1 Namenode 制作

先说 Namenode,需要配置以下配置项:

1. fs.defaultFS:设置缺省的访问地址,需在 core-site.xml 中设置。这里设置为 hdfs://0.0.0.0:8020,表示本机的8020端口。
2. dfs.permissions:权限检查开关,需要在 hdfs-site.xml 中设置。如果没有权限控制要求,则设置为 false。
3. dfs.name.dir:Namenode 的数据存储路径,需要在 hdfs-site.xml 中设置。
4. dfs.namenode.datanode.registration.ip-hostname-check:Datanode 的主机名解析检查,需要在 hdfs-site.xml 中设置。如果没有特殊的安全性考虑,设置为 false。

启动 Namenode 时,需要判断是否是首次部署,若首次部署,则需要进行格式化。
    if [ ! -f ${HDFS_NAMENODE_ROOT_DIR}/current/VERSION ]; then
echo Formatting namenode root fs in ${HDFS_NN_ROOT_DIR}

bin/hdfs namenode -format
fi


最后,就可以启动 Namenode 了。

具体的 Dockerfile 和相关文件见https://github.com/Dataman-Cloud/hdfs-namenode

2 Datanode 制作

再说 Datanode,需要配置一下配置项:

1. dfs.permissions:同 Namenode。
2. dfs.data.dir:Datanode 的数据存储路径,需要在 hdfs-site.xml 中设置。

启动 Datanode 时,需要指定 Namenode,这里通过```HDFS_NAMENODE_RPC_HOST```和```HDFS_NAMENODE_RPC_PORT```两个环境变量来设置 Namenode 地址,并写入 core-site.xml 配置文件,脚本如下:
    sed "s/HDFS_NAMENODE_RPC_HOST/$HDFS_NAMENODE_RPC_HOST/;s/HDFS_NAMENODE_RPC_PORT/$HDFS_NAMENODE_RPC_PORT/" ${HADOOP_INSTALL_DIR}/etc/hadoop/core-site.xml.template > ${HADOOP_INSTALL_DIR}/etc/hadoop/core-site.xml

最后,就可以启动 Datanode 了。
具体的 Dockerfile 和相关文件见https://github.com/Dataman-Cloud/hdfs-datanode
注:以上只是描述了 HDFS 最少的必要配置,其他配置项请根据自己的实际使用需求进行添加。

第二步 部署

数人云作为云时代的操作系统,统一管理和调度集群的计算资源,并以 Docker 的形式发布和管理应用。我们先将自己的计算资源(云主机、虚拟机或是物理机)创建一个数人云集群,就可以在该集群上部署 HDFS 集群了。具体的创建集群方法见(https://github.com/Dataman-Cloud/hdfs-datanode)。

1 新建应用hdfs-namenode:

>以下镜像由数人云提供,仅用于测试。若生产环境使用,请构建自己的镜像仓库和 Docker 镜像。

* 应用名称: hdfs-namenode
* 选择集群: (选择你的集群)
* 镜像地址: index.shurenyun.com/dataman/hdfs-namenode
* 镜像版本: 2.7.1
* 网络模式: HOST
* 选择主机: 标签不选; 主机: (选择一台主机)
* 挂载点:
  * 数据路径: /home/data/hdfs-namenode, 容器路径: /var/hdfs/namenode
* 容器规格
  * CPU: 0.5
  * 内存: 1024MB
* 容器个数: 1,不勾选1容器:1主机
* 高级设置
  * 应用地址
  * 环境变量
  
注:挂载点的“容器路径”就是```dfs.name.dir```的取值。

2 新建应用hdfs-datanode:

* 应用名称: hdfs-datanode
* 选择集群: (选择你的集群)
* 镜像地址: index.shurenyun.com/dataman/hdfs-datanode
* 镜像版本: 2.7.1
* 网络模式: HOST
* 选择主机: 标签不选; 主机:(选择你要部署的主机)
* 挂载点:
  * 数据路径: /home/data/hdfs-datanode, 容器路径: /var/hdfs/datanode
* 容器规格
  * CPU: 0.5
  * 内存: 1024MB
* 容器个数: 3(需要启动的节点数),勾选1容器:1主机
* 高级设置
  * 应用地址
  * 环境变量
    * KEY: HDFS_NAMENODE_RPC_HOST, VALUE: (Namenode 所在节点的 IP)
    * KEY: HDFS_NAMENODE_RPC_PORT, VALUE: (Namenode 的访问端口,与```fs.defaultFS```取值一致,默认为8020)

>注:挂载点的“容器路径”就是```dfs.data.dir```的取值。

创建应用后,进入应用详情页的事件标签页,查看部署的操作状态,显示

```应用名称:hdfs-namenode 事件类型:应用扩展操作 事件结果:部署操作成功

应用名称:hdfs-datanode 事件类型:应用扩展操作 事件结果:部署操作成功
```

同时,应用状态显示为

```
应用状态:运行中
```

则应用部署已经成功。

访问namenode地址,http:// HDFS_NAMENODE_RPC_HOST:50070。
结束语

有以下几点说明:

1. 集群扩展:HDFS 的 Datanode 可以通过数人云的应用扩展功能轻松实现扩展。但需要注意,如果在“选择主机”处选择了固定数量的主机,则 Datanode 数量不能超过选定的主机数。
2. 资源分配:通过数人云管理界面发布应用时,目前最大容器规格限定在1CPU、4G 内存,这对于一些大数据环境是不够的,你可能需要给这些应用分配更多的资源。这一点可以通过数人云 API 实现,不受限制地分配资源给任一容器。
3. 单点问题:本文中部署的 HDFS 集群只有一个 Namenode,存在单点问题。HDFS 提供了解决单点问题的方法,需要 Journalnode 和 Zookeeper。作为一种高可用的、用于生产环境的 HDFS 集群部署方法,数人云同样可以做到快速部署,将在稍后介绍。

使用数人云轻松部署 Cassandra 集群

宁静胡同 发表了文章 • 0 个评论 • 662 次浏览 • 2016-01-29 18:43 • 来自相关话题

Cassandra 是一个高可靠的大规模分布式存储系统,是一个高度可伸缩的、一致的、分布式的结构化 key-value 存储方案,集 Google BigTable 的数据模型与 Amazon Dynamo 的完全分布式的架构于一身。数人云只需要简单几个步骤,就可以完成Cassandra集群的部署,快一起来看看吧。

Cassandra 在2007年 由 facebook 开发,并于2009年成为 Apache 的孵化项目。Cassandra 的主要特点就是它不是一个数据库,而是由一堆数据库节点共同构成的一个分布式网络服务,对 Cassandra 的一个写操作,会被复制到其他节点上去,对 Cassandra 的读操作,也会被路由到某个节点上面去读取。对于一个 Cassandra 群集来说,扩展性能是比较简单的事情,只管在群集里面添加节点就可以了。由于它良好的可扩展性,被 Digg、Twitter 等知名网站所采纳,成为了一种流行的分布式结构化数据存储方案。

接下来,让我们来体验一下用数人云来部署 Cassandra 集群吧。

部署之前,我们要在 Docker 环境下制作 Cassandra 的 Docker image,并推送至可访问的 Docker Registry。写好配置文件 docker-entrypoint.sh 和 Dockerfile,创建并上传 Docker image 之后,即可开始部署 Cassandra 集群。

第一步建立集群

请参见 “创建/删除集群” (详见文章底部链接)来创建您的集群。
创建集群的实例可以参考数人云文档第一个应用-2048,若要部署 Cassandra 集群,需至少3个 Slave 节点。

注意:本实例至少需要一个内部代理,以便进行 Cassandra 集群的服务发现。

第二步发布应用

接下来,通过数人云创建应用。
新建 Cassandra 应用:
应用名称:cassandra
选择集群:your-cluster
镜像地址:index.shurenyun.com/cassandra
镜像版本:2.2.4
网络模式:HOST 模式
选择主机:(选择3台主机)
添加目录:主机目录:/var/lib/cassandra 容器目录:/var/lib/cassandra
选择容器规格: CPU:1 内存:2048 MB
容器个数:3,选中"1容器1主机"
 
   高级设置:
    添加应用地址:
端口:9024,类型:对内 TCP,映射端口:9024
端口:9160,类型:对内 TCP,映射端口:9160
添加环境变量:
CASSANDRA_SEEDS=ip1,ip2,ip3(3台主机的 IP,以逗号分隔)
HEAP_NEWSIZE=300m
MAX_HEAP_SIZE=2g

注1:CASSANDRA_SEEDS:Cassandra 集群的种子节点地址;这个选项可以设置多个值,即 Cassandra 集群中有多个种子节点,集群中所有的服务器在启动的时候,都将于 seed 节点进行通信,从而获取集群的相关信息;这里选择3台主机作为 seed 节点;

注2:Cassandra 启动需要足够的资源,建议 CPU 数最小为1,内存最低2G;

注3:Cassandra 节点间需要通信,所以选择 HOST 模式部署,避免端口隐射导致而节点间无法通信;

注4:如果对 Cassandra 集群有大致的规划,可以在选择主机处选择所需数量的主机;应用发布后,可以在所选主机的数量范围内,自由伸缩 Cassandra 节点数量。

第三步测试

等待应用部署完成,登陆一台集群中的测试机,通过以下指令,用 cqlsh 连接 Cassandra 集群:

   sudo docker run -it --rm index.shurenyun.com/cassandra:2.2.4 cqlsh 10.3.10.39
    

其中,请将10.3.10.39换成你的集群的内部代理 IP;
若连接成功,输入以下代码: CREATE KEYSPACE test
WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 3 } AND DURABLE_WRITES = false;

SELECT * FROM system.schema_keyspaces;



若看到名为 test 的 keyspace 已经添加成功,如下图所示:







恭喜,现在你的 Cassandra 集群已经正常运作了!

更多详细内容参见:http://doc.shurenyun.com/practice/cassandra.html 查看全部

Cassandra 是一个高可靠的大规模分布式存储系统,是一个高度可伸缩的、一致的、分布式的结构化 key-value 存储方案,集 Google BigTable 的数据模型与 Amazon Dynamo 的完全分布式的架构于一身。数人云只需要简单几个步骤,就可以完成Cassandra集群的部署,快一起来看看吧。



Cassandra 在2007年 由 facebook 开发,并于2009年成为 Apache 的孵化项目。Cassandra 的主要特点就是它不是一个数据库,而是由一堆数据库节点共同构成的一个分布式网络服务,对 Cassandra 的一个写操作,会被复制到其他节点上去,对 Cassandra 的读操作,也会被路由到某个节点上面去读取。对于一个 Cassandra 群集来说,扩展性能是比较简单的事情,只管在群集里面添加节点就可以了。由于它良好的可扩展性,被 Digg、Twitter 等知名网站所采纳,成为了一种流行的分布式结构化数据存储方案。

接下来,让我们来体验一下用数人云来部署 Cassandra 集群吧。

部署之前,我们要在 Docker 环境下制作 Cassandra 的 Docker image,并推送至可访问的 Docker Registry。写好配置文件 docker-entrypoint.sh 和 Dockerfile,创建并上传 Docker image 之后,即可开始部署 Cassandra 集群。

第一步建立集群

请参见 “创建/删除集群” (详见文章底部链接)来创建您的集群。
创建集群的实例可以参考数人云文档第一个应用-2048,若要部署 Cassandra 集群,需至少3个 Slave 节点。

注意:本实例至少需要一个内部代理,以便进行 Cassandra 集群的服务发现。

第二步发布应用

接下来,通过数人云创建应用。
新建 Cassandra 应用:
   应用名称:cassandra  
选择集群:your-cluster
镜像地址:index.shurenyun.com/cassandra
镜像版本:2.2.4
网络模式:HOST 模式
选择主机:(选择3台主机)
添加目录:主机目录:/var/lib/cassandra 容器目录:/var/lib/cassandra
选择容器规格: CPU:1 内存:2048 MB
容器个数:3,选中"1容器1主机"

 
   高级设置:
   
    添加应用地址:  
端口:9024,类型:对内 TCP,映射端口:9024
端口:9160,类型:对内 TCP,映射端口:9160
添加环境变量:
CASSANDRA_SEEDS=ip1,ip2,ip3(3台主机的 IP,以逗号分隔)
HEAP_NEWSIZE=300m
MAX_HEAP_SIZE=2g


注1:CASSANDRA_SEEDS:Cassandra 集群的种子节点地址;这个选项可以设置多个值,即 Cassandra 集群中有多个种子节点,集群中所有的服务器在启动的时候,都将于 seed 节点进行通信,从而获取集群的相关信息;这里选择3台主机作为 seed 节点;

注2:Cassandra 启动需要足够的资源,建议 CPU 数最小为1,内存最低2G;

注3:Cassandra 节点间需要通信,所以选择 HOST 模式部署,避免端口隐射导致而节点间无法通信;

注4:如果对 Cassandra 集群有大致的规划,可以在选择主机处选择所需数量的主机;应用发布后,可以在所选主机的数量范围内,自由伸缩 Cassandra 节点数量。

第三步测试

等待应用部署完成,登陆一台集群中的测试机,通过以下指令,用 cqlsh 连接 Cassandra 集群:

  
  sudo docker run -it --rm index.shurenyun.com/cassandra:2.2.4 cqlsh 10.3.10.39

    

其中,请将10.3.10.39换成你的集群的内部代理 IP;
若连接成功,输入以下代码:
    CREATE KEYSPACE test 
WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 3 } AND DURABLE_WRITES = false;

SELECT * FROM system.schema_keyspaces;



若看到名为 test 的 keyspace 已经添加成功,如下图所示:

cassandra1.png



恭喜,现在你的 Cassandra 集群已经正常运作了!

更多详细内容参见:http://doc.shurenyun.com/practice/cassandra.html

活动 | Geek@100offer:Docker与Mesos实践

宁静胡同 发表了文章 • 0 个评论 • 531 次浏览 • 2016-01-26 17:06 • 来自相关话题

由Geek@100offer主办的主题为“Docker与Mesos实践”的干货分享活动即将在本周末与大家见面。数人科技云平台负责人周伟涛作为演讲嘉宾也将出席。他曾就职于国际开源解决方案供应商 Red Hat, 红帽认证工程师, Mesos contributor,高级 Python 开发工程师。 是国内较早一批接触使用Docker,Mesos等技术的开发者。 一场关于Docker与Mesos的干货盛宴正等待着大家,赶快来报名吧!


活动主题:干货分享——Docker与Mesos实践
活动时间:2016年1月30日 14:00 ~ 2016年1月30日 17:00
活动地点:(北京朝阳)广顺南大街19号(无界空间)
活动人数: 限额100人








流程安排:
13:30-14:00  签到

14:00-15:00  分享《去哪儿网基于Mesos的日志系统实践》 徐磊       去哪儿网技术专家

15:00-16:00  分享《雪球基于Docker的发布系统实践》   董明鑫       雪球技术专家

16:00-17:00  分享《Docker Swarm与 Mesos 在实践中的对比》 周伟涛       数人云技术专家


报名方式:
请填写活动行报名表单登记报名信息。
在沙龙开始前我们会发送邮件或短信提醒,请您注意查收。
有任何问题欢迎联系Maggie  18521796153

100offer介绍
100offer是一家高端招聘平台,专注于服务高端互联网用户群体,致力于“为最好的互联网人发现更好的offer”;
对于有数年工作经验的优秀互联网人,换一份工作是件成本很高的事情;100offer互联网人才拍卖专注于帮优秀互联网人一次性获得多个优质的工作机会,并且在其中找到最为满意的工作。

Geek@100offer介绍
Geek@100offer是高端招聘平台100offer的一个沙龙品牌;
从2016年1月起,每月将在北京,上海,深圳等地举办不同领域的分享沙龙;
沙龙的参与人群将锁定在工作经验2年以上,年薪15万以上的高端人群;
100offer致力于创建一个纯粹的分享平台,便于高端互联网人群之间的沟通和交流,通过平台结识更多志同道合的朋友,挖掘并传播业界最有价值的信息,为参与者提供更优质内容分享及交流空间。

本次活动微信群,欢迎提前勾搭咨询。






  查看全部


由Geek@100offer主办的主题为“Docker与Mesos实践”的干货分享活动即将在本周末与大家见面。数人科技云平台负责人周伟涛作为演讲嘉宾也将出席。他曾就职于国际开源解决方案供应商 Red Hat, 红帽认证工程师, Mesos contributor,高级 Python 开发工程师。 是国内较早一批接触使用Docker,Mesos等技术的开发者。 一场关于Docker与Mesos的干货盛宴正等待着大家,赶快来报名吧!



活动主题:干货分享——Docker与Mesos实践
活动时间:2016年1月30日 14:00 ~ 2016年1月30日 17:00
活动地点:(北京朝阳)广顺南大街19号(无界空间)
活动人数: 限额100人


地图.JPG



流程安排:
13:30-14:00  签到

14:00-15:00  分享《去哪儿网基于Mesos的日志系统实践》 徐磊       去哪儿网技术专家

15:00-16:00  分享《雪球基于Docker的发布系统实践》   董明鑫       雪球技术专家

16:00-17:00  分享《Docker Swarm与 Mesos 在实践中的对比》 周伟涛       数人云技术专家


报名方式:
请填写活动行报名表单登记报名信息。
在沙龙开始前我们会发送邮件或短信提醒,请您注意查收。
有任何问题欢迎联系Maggie  18521796153

100offer介绍
100offer是一家高端招聘平台,专注于服务高端互联网用户群体,致力于“为最好的互联网人发现更好的offer”;
对于有数年工作经验的优秀互联网人,换一份工作是件成本很高的事情;100offer互联网人才拍卖专注于帮优秀互联网人一次性获得多个优质的工作机会,并且在其中找到最为满意的工作。

Geek@100offer介绍
Geek@100offer是高端招聘平台100offer的一个沙龙品牌;
从2016年1月起,每月将在北京,上海,深圳等地举办不同领域的分享沙龙;
沙龙的参与人群将锁定在工作经验2年以上,年薪15万以上的高端人群;
100offer致力于创建一个纯粹的分享平台,便于高端互联网人群之间的沟通和交流,通过平台结识更多志同道合的朋友,挖掘并传播业界最有价值的信息,为参与者提供更优质内容分享及交流空间。

本次活动微信群,欢迎提前勾搭咨询。

30232211673691577.jpg