单一构建系统发布与部署的业界现状研究
【引言】
微服务是一种软件开发技术,是面向服务架构(SOA)风格的变体,将应用程序安排成松散耦合的服务集合,在微服务架构中,每个服务都应该是精细的的,轻量级的。
【简介】
对于微服务,没有一个单一的定义。随着时间的推移,业界已经形成了一个共识的观点。经常被引用的一些定义特征包括:
l 微服务架构(MSA)中的服务通常是通过网络进行通信的,通常使用HTTP等协议来进行。
l 微服务体系结构中的服务是可以独立部署的。
l 服务是以具体业务需求来创建的。
l 服务可以利用不同的程序设计语言、数据库、硬件和软件环境,根据不同的需求,使用不同的编程语言、数据库、硬件和软件环境来实现。
l 服务的规模很小,支持消息传递,受语境约束,自主开发,可独立部署,去中心化,并通过自动化流程构建和发布。
微服务并不是单体应用中的一个层(例如,web控制器,后端,前端),相反,它是一个自成一体的业务功能,具有明确的接口,可以通过自己的内部组件实现分层架构。从策略的角度来看,微服务架构本质上遵循了Unix的 "做一件事,做好一件事 "的理念,Martin Fowler将基于微服务的架构描述为:
l 适用于持续交付的软件开发过程。改变应用程序的一小部分只需要重建和重新部署一个或少量的服务即可。
l 坚持使用可直达独立部署服务的精细化接口、业务驱动开发(如领域驱动设计)等原则。
微服务架构普遍被采用于云原生应用、无服务器计算、以及使用轻量级容器部署的应用等。根据Fowler的观点,由于服务数量众多(与单体应用实现相比),为了有效地开发、维护和运营这类应用,去中心化的持续交付和带有整体服务监控的DevOps是必要的。 遵循这种方法的一个合理性结果是,单独的微服务可以单独扩展。在单体应用架构方法中,一个支持三个功能的应用,即使只有其中一个功能需要添加资源约束,也需要对其进行整体的扩展。微服务则不同,只需要对有资源约束需求的微服务进行扩展, 这样就带来了资源和成本的优化。
如下为一个微服务系统设计图:
(图1)
【历史与前景】
早在2005年,Peter Rodgers在Web服务边界会议的一次演讲中就提出了 "Micro-Web-Service "这个词。他反对传统思维,在SOAP SOA架构炒作的高峰期,他主张 "REST-服务",并在会议演讲的第4页幻灯片上讨论了 "软件组件就是微服务",他接着说:"微服务是使用类似Unix的管道技术(Web+Unix=真正的松耦合)。服务可以调用服务(支持多语言运行)。复杂的服务组件被抽象到简单的URI接口后面。任何服务,在任何粒度上都可以暴露出来。" 他描述了一个精心设计的微服务平台是如何 "将Web和REST服务的底层架构原则与类似Unix的调度和管道一起应用于面向服务的架构中,以提供彻底的灵活性和改进的简单性。"
罗杰斯的工作起源于1999年惠普实验室的Dexter研究项目,其目的是让代码不那么脆弱,并使大规模复杂的软件系统能够稳健地应对变化。 最终,这条研究之路导致了面向资源的计算(ROC)的发展,这是一种广义的计算抽象,其中REST是一个特殊的子集。
2007年,Juval Löwy在他的著作和演讲中呼吁构建每个类都是服务的系统。Löwy意识到这就需要使用一种能够支持这种细粒度使用服务的技术,他扩展了Windows Communication Foundation (WCF)来做到这一点,在保留传统的类编程模型的同时,把每一个类都当作服务来对待。
2011年5月,在威尼斯附近举办的一个软件架构师研讨会上,与会者用 "微服务 "这个词来描述这种常见的架构风格,他们中的许多人当时都在探索这种风格。2012年5月,同一个小组决定用 "微服务 "作为最合适的名称。2012年3月,James Lewis在克拉科夫的第33届学位大会上,以 "微服务--Java,Unix之道"为例,介绍了其中的一些想法,Fred George也是在同一时间做了介绍。Adrian Cockcroft,前Netflix公司云系统总监,将这种方法描述为 "细粒度的SOA",在Web规模上开创了这种风格,当然其他许多人如Joe Walnes、Dan North、Evan Bottcher和Graham Tackley也是此种风格的推动者。
微服务是面向服务架构(SOA)的一种专门化的实现方式,用于构建灵活的、可独立部署的软件系统,微服务方式是SOA的第一个实现方式,它是随着DevOps的引入而出现的,在构建连续部署的系统中越来越流行。
2020年2月,《云微服务市场研究报告》预测,2019年至2026年,全球微服务架构市场规模将以21.37%的年复合增长率增长,到2026年将达到31亿美元 。
【服务粒度】
定义微服务架构的一个关键步骤是弄清楚单个微服务需要有多大。对此,没有共识或可借鉴的经验,因为正确的答案取决于业务背景和需求,例如,亚马逊使用的是面向服务的架构,一个服务通常是一个由3到10个工程师组成的团队实现的。
将服务做得太小被认为是不好的做法,因为那样的话,运行时的开销和操作复杂性会抵消这种方法的好处。当事情变得过于细化时,必须考虑其他的方法:比如把函数打包成库,再移到其他微服务中。
如果在为系统构建的领域建模时采用了领域驱动设计,那么微服务可以小到作为一个聚合体,大到成为一个绑定的上下文环境平台。
【好处】
将一个应用程序分解成不同的小服务的好处是很多的。
l 模块化。这使得应用程序更容易理解、开发、测试,并变得更容易抵御架构的侵蚀。与单体应用架构的复杂度相比,这经常被认为是一种优势。
l 可扩展性。由于微服务是独立实现和部署的,即在独立的进程内运行,因此可以独立监控和扩展。
l 异构系统和遗留系统的集成:微服务被认为是对现有的单体软件应用进行现代化改造的可行手段。有一些公司已经成功地用微服务取代了全部或者部分的现有软件,或者正在进行中。遗留系统的软件现代化改造过程中,一般采用增量的方法。
l 分布式开发:它使小型的自主团队能够独立地开发、部署和扩展各自的服务,从而实现了开发的并行化,它还可以通过不断的重构,使单个服务的架构更加优良。基于微服务的架构有利于连续集成、连续交付和部署。
【批评】
微服务的设计理念因为下面的一些问题而受到批评:
l 各自独立的服务形成信息壁垒。
l 在网络上进行的业务间呼叫在网络延迟和报文处理时间方面的成本要高于单体服务流程内的进程内呼叫。
l 测试和部署比较复杂。
l 在服务之间功能迁移是比较困难的,这主要是因为可能涉及到不同团队之间的沟通,用另一种语言重写功能,或者是将其适配到不同的基础架构中。微服务可以独立于应用程序的其他部分进行部署,而在单体应用上的各团队工作需要同步部署到一起。
l 将服务的大小视为主要的结构化机制,可能会导致过多的服务,而内部模块化的替代方案可能会导致更简单的设计,这就需要更好的理解应用的整体架构和组件之间的相互依赖关系。
l 在基于微服务的架构中,分阶段提交被认为是一种反模式,因为这导致了事务中所有参与者之间的紧密耦合。然而,由于缺乏某种技术,导致了尴尬的情况,为了保持数据的一致性,所有的事务参与者都必须等待或者实现这项技术。
l 如果使用不同的工具和技术来构建许多服务,那么开发和支持这些服务就更具有挑战性。尤其是如果工程师在项目之间频繁地移动时,问题就尤为突出。
l 微服务通常使用的协议(HTTP)是为面向公共服务设计的,因此不适合用在内部调用的微服务之间。
l 分解方法通常采用的是功能分解的方法,在处理需求变化的同时,增加了服务的复杂度。
l 微服务这个概念本身就有误导性,对于服务何时开始或停止称为微服务,并没有一个合理的定义。
【复杂度的提高】
该架构引入了额外的复杂度和需要处理的新问题,如网络延迟、消息格式设计、备份/可用性/一致性、负载平衡和容错等,所有这些问题都必须能够适应规模的变化。根据《微服务2020状态报告》的研究结果,维护和调试仍然是构建微服务的开发团队面临的最大问题之一。
如果一个单一的应用程序被重新实现为一组微服务应用程序,那么它的复杂度会增加。这些新的复杂度有些来自于操作复杂度,还有些复杂度表现在网络流量的增加以及由此带来的性能变慢。
而且,一个由任意数量的微服务组成的应用程序有更多的接口点来访问其各自的生态系统,这也增加了架构的复杂度。
各种组织原则(如HATEOAS、通过Swagger捕获的接口和数据模型文档等)已经被应用到实践中以减少这些额外的复杂度的影响。
【服务网格】
在服务网格中,每个服务实例都与一个反向代理服务器的实例配对,称为服务代理。服务实例和服务代理共享一个容器,容器由容器协调工具(如 Kubernetes、Nomad、Docker Swarm 或 DC/OS)管理。服务代理负责与其他服务实例进行通信,可以支持服务(实例)发现、负载均衡、认证和授权、安全通信等功能。
在服务网格中,服务实例和它们的代理构成了所谓的数据平面,它不仅包括数据管理,还包括请求处理和响应。服务网格还包括一个控制平面,用于通过服务代理管理服务之间的交互。服务网状结构有几种选择:Istio(Google、IBM和Lyft的联合项目)、Linkerd(Buoyant领导的CNCF项目)、Consul(HashiCorp的产品))等。
【平台的比较】
实施微服务架构是非常困难的。任何微服务架构都需要解决很多问题。
Netflix开发了一个微服务框架来支持他们的内部应用,然后开源了该框架的许多部分。这些工具中的很多都是通过Spring框架普及的--它们在Spring Cloud项目的佑护下被重新实现为基于Spring的工具。
下表显示了Kubernetes生态系统中的一个实现功能与Spring Cloud世界中的等价物的比较,Spring Cloud生态系统的一个值得注意的方面是,它们都是基于Java的技术,而Kubernetes是一个多技术运行的平台。
微服务相关考量 |
Spring Cloud & Netflix OSS |
Kubernetes |
配置管理:微服务应用的配置需要从代码中接口化,并通过一个简单的服务调用来进行使用。 |
Spring Config Server、Netflix Archaius都支持基于Git-repository的配置。Archaius支持数据类型配置。 |
Kubernetes ConfigMaps通过服务公开了存储在etcd中的配置。Kubernetes Secrets支持基于服务的安全部署和使用敏感配置信息(如密码、证书等)。 |
服务发现:维护一个微服务域内可工作的服务实例列表。 |
Spring Cloud Eureka允许客户注册,并与注册的客户保持关联,将服务名映射到主机名上,通过服务名查询服务。 |
Kubernetes服务提供部署时注册服务实例,这些服务实例在集群内部可用。Ingress是一种机制,通过这种机制,服务可以向集群外的客户端暴露接口调用。 |
负载平衡:扩展分布式系统的关键在于能够运行一个组件的多个实例,随后通过负载平衡器将负载分配到这些实例中。 |
Spring Cloud Ribbon为服务客户端提供了跨服务实例的负载平衡能力。 |
Kubernetes服务提供了跨服务实例的负载平衡能力。 |
API网关:微服务提供的API的粒度往往与服务客户端的需求不同。API网关实现门面,并提供额外的服务,如代理、协议翻译等管理功能。 |
Spring Cloud Zuul提供了基于配置的API门面。 |
Kubernetes服务和Ingress资源、Istio、Ambassador等解决方案,既提供了南北向(流量进出数据中心),也提供了东西向(流量跨数据中心或云或区域)的API网关功能。 |
安全方面的考量:许多安全问题被推送到API网关实现中。对于分布式微服务应用,不重复造安全轮子,允许在所有服务共享的组件中进行策略定义和安全实现。 |
Spring Cloud通过Spring Cloud Zuul解决了许多安全问题。 |
Kubernetes生态系统提供了像Istio这样的服务网格,能够通过其API网关机制提供安全保障。 |
集中化的日志记录:有一个集中的日志收集和分析基础设施来管理大量的服务----其中许多服务是以分布式的方式运行的,因此,拥有一个集中的日志收集和分析基础设施非常重要。 |
ELK Stack (Elasticsearch, LogStash, Kibana) |
EFK Stack (Elasticsearch, Fluentd, Kibana) |
集中的指标:一个集中的区域,可以监测各项服务和整个系统的健康状况和性能,这对于正常运作至关重要。 |
Spring Spectator & Atlas |
Heapster, Prometheus, & Grafana |
分布式追踪:每个进程日志和指标监控都有自己的作用,但两者都无法重构事务在分布式系统中传播的复杂路径。分布式追踪是微服务平台的重要工具。 |
Spring Cloud Sleuth |
Hawkular, Jaeger |
复原力和容错能力:分布式系统必须能够围绕故障自动路由,并能够将请求路由到能够提供最佳响应的服务实例。 |
Spring Hystrix, Turbine, & Ribbon |
健康检查,服务网格(例如:Istio) |
自动扩展和自愈:分布式系统通过水平扩展来应对更高的负载:平台必须检测并自动响应。此外,系统需要检测故障并尝试自动重启,而无需操作员介入。 |
- |
健康检查、自我修复和自动扩展功能 |
包装、部署和调度:大型系统需要强大的封装管理,用部署系统来管理滚动部署或蓝绿部署,必要时还可以回滚。调度器根据当前条件决定新的服务集可以部署到哪个特定的执行节点。 |
Spring Boot、Apache Maven。Spring Cloud没有真正的调度器。 |
Docker, Rkt, Kubernetes调度和部署, Helm |
作业管理:预定的计算与任何单个用户的请求断开连接。 |
Spring Batch |
Kubernetes Jobs 和 Scheduled Jobs |
Singleton应用程序:指定特定服务作为整个系统中唯一的服务实例运行。 |
Spring Cloud Cluster |
Kubernetes Pods |
【小结】
构建复杂的应用的确是很有挑战性的工作。单体应用架构更适合简单、轻量级的应用,它是微服务架构的基础,每个微服务本身就是按照单体架构来实现的。对于复杂的、不断发展的应用,微服务架构模式当然是更好的选择,在具体的开发实践中,应该实事求是的紧贴业务需求,循序渐进的增加新的服务。
总之,我们的目标是:既要能够利用微服务架构设计带来的横向扩展便利,又要尽可能的规避由这种方法所带来的一系列复杂度的提升和挑战。
- 点赞
- 收藏
- 关注作者
评论(0)