内核堆栈 用户堆栈
重要要点
- 大多数在Kubernetes上构建应用程序的开发人员仍然主要依靠无状态协议和设计。 问题在于,仅专注于无状态设计会忽略分布式系统中最困难的部分:管理状态-您的数据。
- 挑战不是设计和实现服务本身,而是管理服务之间的空间:数据一致性保证,可靠的通信,数据复制和故障转移,组件故障检测和恢复,分片,路由,共识算法等。
- Kubernetes和Akka可以很好地合作,因为它们各自负责应用程序堆栈中的不同层和功能。 Kubernetes允许对弹性和可伸缩性进行容器级别的粗粒度管理。 Akka允许对弹性和可伸缩性进行细粒度的实体级管理。
- 在过去两年中,Akka一直在快速增长。 如今,它每月的下载量约为500万,而两年前的每月下载量为50万。
在今年夏天的纽约QCon上,JonasBonér着重介绍了会议中最受欢迎的演讲之一,他的演讲重点是“ 设计事件优先的微服务” 。 在本InfoQ问答中,我们请Bonér解释“如何从整体设计中养成不良习惯”是通往服务设计无路可走的道路,以及他在哪里看到自己的Akka框架适合云原生堆栈。
InfoQ:在QCon上,您说过:“当您开始微服务之旅时,您应该注意不要以' 微石 '结尾,因为您可能会从单片设计到微服务带来不良习惯,从而在服务之间建立了强大的联系。” 说明。
JonasBonér :在应用程序开发的云原生世界中,我仍然看到对无状态协议(通常是同步协议)的强烈依赖。
大多数在Kubernetes上构建应用程序的开发人员仍然主要依靠无状态协议和设计。 它们包含容器,并且经常保留旧的体系结构,设计,习惯,模式,实践和工具,这些都是为在全能的RDBMS之上运行的单片单节点系统而设计的。
问题在于,仅专注于无状态设计会忽略分布式系统中最困难的部分:管理状态-您的数据。
忽略最困难的部分并将其职责推到应用程序层有时可能是个好主意。 但是,随着当今应用程序变得越来越以数据为中心和以数据为驱动力,通过具有一种高效,高性能和可靠的方式来管理,处理,转换和丰富应用程序本身附近的数据来获取数据所有权变得越来越重要。比以往任何时候都好。
许多应用程序无法为每个数据访问或存储提供往返数据库的往返服务,并且需要连续不断地接近实时地处理数据,并从永无止境的数据流中挖掘知识。 在准备好存储之前,通常还需要以分布式方式处理此数据(以实现可伸缩性,低延迟和吞吐量)。
InfoQ:长期以来,人们一直将有状态服务视为采用主流容器的最大障碍。 告诉我们更多有关为什么这是一个棘手的领域?
Bonér :将容器视为逻辑上相同的单元的策略,可以无条件地替换,旋转和移动,这对于无状态服务确实非常有效,但是与您要管理分布式有状态服务和数据库的方式相反。 首先,有状态的实例不是很容易被替换的,因为每个实例都有其自己的状态,需要将其考虑在内。 其次,有状态副本的部署通常需要副本之间的协调-诸如引导程序依赖顺序,版本升级,架构更改等。 第三,复制需要时间,并且从中进行复制的计算机将比平时承受更大的负载,因此,如果在负载下启动新副本,则实际上可能会关闭整个数据库或服务。
解决该问题的一种方法(它有其自身的问题)是将状态管理委派给Kubernetes集群外部的云服务或数据库。 也就是说,如果我们想使用Kubernetes以统一的方式管理您的所有基础架构,那我们该怎么办?
这时,Kubernetes对运行非云原生的有状态服务的问题的回答是StatefulSet的概念,该概念可确保为每个Pod提供稳定的身份和专用磁盘,该磁盘在重启后仍可维护(即使在重启后也是如此)重新安排到另一台物理计算机)。 结果,尽管有很大挑战,但现在仍可以在Kubernetes上部署分布式数据库,流数据管道和其他有状态服务。
现在需要的是新一代工具,允许开发人员构建真正的云原生状态服务,这些服务仅具有Kubernetes提供给无状态服务的基础架构要求。 这并不是反对使用诸如Kubernetes和Istio这样的低级基础设施工具(它们显然带来了巨大的价值),而是在基础设施和应用程序层之间保持更紧密协作以维护整体正确性和安全性保证的呼吁。
InfoQ:告诉我们Akka在Kubernetes堆栈的这套有状态服务需求中的适合位置。
Bonér :确实,最困难的部分不是设计和实现服务本身,而是管理服务之间的空间。 在这里,所有困难的事情都出现了:数据一致性保证,可靠的通信,数据复制和故障转移,组件故障检测和恢复,分片,路由,共识算法等等。 将所有这些缝合在一起,并随着时间的推移进行维护,这是非常非常困难的。
端到端的正确性,一致性和安全性对于不同的服务意味着不同的事情,完全取决于用例,并且不能完全外包给基础架构。 我们需要的是一种用于云的编程模型,再加上可以完成繁重工作的运行时,该运行时可以使我们专注于建立业务价值,而不是搞砸网络编程和故障模式的复杂性—我相信Akka与Kubernetes可能就是这种解决方案。
Akka是一个于2009年创建的开源项目,旨在作为云的分布式系统的结构和编程模型。 从最真实的意义上来说,Akka是云原生的,它是在术语“云原生”诞生之前在云中本地运行的。
Akka基于Actor模型,并基于Reactive Manifesto中概述的原则,该原则将Reactive Systems定义为一组体系结构设计原则,旨在满足当今和未来系统所面临的需求。在Akka中,工作和状态的单位称为参与者,可以看作是有状态的,容错的,孤立的,自治的组件或实体。 这些参与者/实体在资源方面非常轻巧-您可以轻松地在一台计算机上同时运行数百万个参与者-并使用异步消息传递进行通信。 它们具有内置的自动自我修复机制,并且默认情况下可分发且位置透明。 这意味着它们可以按需对集群/实体的用户透明的方式按需扩展,复制和在集群中移动(与应用程序的使用方式有关)。
InfoQ:当Kubernetes和Akka一起使用时,关注点在哪里分开呢?
Bonér :一种看待它的方式是,Kubernetes在管理和编排软件(容器)的“盒子”方面非常出色,但是管理这些盒子只能使您半途而废。 同样重要的是,您要放在盒子里的东西,这是Akka可以帮助的。
Kubernetes和Akka的组合非常好,它们分别负责应用程序堆栈中的不同层和功能。 Akka是用于编写应用程序及其支持的运行时的编程模型,它有助于管理业务逻辑。 数据一致性和完整性; 操作语义; 分布式和本地工作流与沟通; Kubernetes是一种用于以统一方式管理大量容器实例的操作工具,它有助于管理容器生命周期; 容器的版本控制和分组; 路由容器之间的通信; 管理容器之间的安全性,身份验证和授权等。
本质上,Kubernetes的工作是为您的应用程序提供足够的计算资源,将外部流量发送到应用程序中的节点,并管理访问控制之类的事情,而Akka的工作是确定如何在所有计算资源之间分配工作。给它。
声明:Akka奉行“让它崩溃”的方法-失去一位演员没关系,因为另一位演员会接手工作。 您能解释一下它在容器环境中如何工作吗? 管理员需要干预吗?
Bonér :传统的基于线程的编程模型仅提供单个控制线程,因此,如果该线程因异常而崩溃,您将遇到麻烦。 这意味着您需要在此单个线程中明确所有错误处理。 异常不会在线程之间或整个网络中传播,因此甚至无法发现某些故障。 但是丢失线程,或者在最坏的情况下,整个容器非常昂贵。 更糟的是,使用同步协议可能会导致这些故障在整个应用程序中级联。 我们可以做得更好。
在Akka中,您可以在所谓的“主管层次”中设计应用程序,在这些层次中,参与者要注意彼此的健康状况并管理彼此的故障。 如果参与者失败,则会隔离并包含其错误,并将其错误化为消息,并在需要时通过网络异步发送给其监督参与者,该监督参与者可以在安全健康的上下文中处理故障并根据以下信息自动重新启动失败的参与者:声明式定义的规则。 这自然会产生一种非防御性的编程方式以及一种快速的失败(和恢复)方法,也称为“让它崩溃”。
听起来这似乎与Kubernetes的角色重叠,并且的确是Kubernetes和Akka都可以帮助管理弹性和可伸缩性,但是应用程序堆栈中的粒度级别不同。 您还可以从细粒度与粗粒度的弹性和可伸缩性方面看这两种技术。
Kubernetes允许对容器级别的弹性和可扩展性进行粗粒度管理,在该容器中复制,重新启动或横向扩展/整体扩展容器。 Akka允许对弹性和可伸缩性进行细粒度的实体级管理(与应用程序紧密协作),其中每个服务本身都是实体副本的集群,可以根据需要对其进行复制,重新启动和放大和缩小,并由应用程序自动管理Akka运行时,无需操作员或Kubernetes干预。
InfoQ:您能给我们介绍一下Akka的采用吗? 您目前看到每月多少次下载?
Bonér :Akka在过去两年中发展Swift。 如今,它每月的下载量约为500万,而两年前的每月下载量为50万。 如果您对项目的某些最早的历史和里程碑感兴趣,则此信息图包含一些很酷的数据点。
关于被访者
内核堆栈 用户堆栈