前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用容器构建微服务体系结构

使用容器构建微服务体系结构

作者头像
Techeek
发布2018-07-09 17:37:12
1.5K0
发布2018-07-09 17:37:12
举报
文章被收录于专栏:云计算云计算

先前的文章中,我谈到了如何使用 Linux 容器技术(如 Docker)简化开发和测试体验。由于容器可跨不同类型的基础架构移植,它们可以像在裸机服务器上一样容易地在AWS中运行,容器使代码的部署非常方便。对于开发和测试工作负载,这可以消除在开发和测试环境之间的细微差异导致部署失败时倾向于发生的大量猜测和指责。

在本文中,我们将探讨使容器成为开发/测试工作负载的理想选择的一些特性,这也使得它们成为在 AWS 中构建基于微服务的体系结构的绝佳选择。微服务体系结构是一种使基于 Web 的开发更灵活而易于维护的代码库。我们将讨论这种架构如何使开发人员高效工作,并快速迭代和发设计代码库。对于快速成长的创业公司来说,微服务架构可以真正帮助开发团队在实现灵活敏捷地开发。

Web 开发简史

但首先,让我们快速浏览过去大概 20 年的基于 Web 开发的历史,因为这将为解释微服务架构变得如此流行的原因以及这种架构所解决的问题提供了一些重要的背景。

在 Web 应用程序开发的早期,应用程序是使用通用网关接口(Common Gateway Interface, CGI)构建的。这个接口为 Web 服务器在处理来自浏览器的 HTTP 请求时执行脚本(通常用 Perl 编写)提供了一种方式。CGI 体系结构不能很好地扩展,因为 Perl 进程将针对脚本资源的每个传入请求启动。为了解决这个问题,当时流行的 Web 服务器增加了对模块的支持。Apache 是目前最流行的 Web 服务器之一,它添加了一个名为 “ mod_perl ” 的东西, mod_perl 是在服务器自身内部运行 Perl 代码的一种方式。这将允许 CGI 脚本执行速度更快。

尽管 mod_perl 等技术相比传统的 CGI 有了很大的改进,但仍然存在问题。也就是说,负责构建视图(views)的代码(即在页面上发布的 HTML 动态部分)与应用程序的业务逻辑混杂在一起。这意味着完成一个简单的任务,比如添加一列到 HTML 表格或将新元素添加到表单中,通常需要修改低级应用程序代码。因此,Web 编程技术的下一轮发展促成了 “服务器页面(server pages)” 的诞生,这是一种模板化框架,允许可执行代码与 HTML 一起嵌入。这样便允许应用程序逻辑与视图逻辑更清晰地分离。在 Java 编程世界中,一种名为 “Model 2” 的设计模式迅速出现,其中涉及将应用程序代码放入 Java servlet 中,数据则放在类名为 Java Bean 的类中, 如图一所示:

“Model 2” 设计迅速发展成今天广泛使用的 模型 - 视图 - 控制器(Model - View - Controller,MVC)设计。许多早期的 MVC 框架都是基于 Java 编写的(比如Apache Struts),但是其他语言编写的也在迅速普及,比如 Ruby on Rails。通过 MVC 设计模式,“ Controller ” 类定义了使用类名为 “router(路由)”映射到 URL 模式的方法。控制器方法利用 “Model” 类来封装业务逻辑和核心应用程序实体的数据。最后,每个控制器方法呈现一个 “View” ,用于显示和编辑相应模型类中的数据。这种模式强化了业务,应用程序和视图逻辑之间的关注点的清晰分离,如图2所示:

REST 协议的兴起

与 MVC 的迅速采用相结合来作为 Web 开发的实际选择,这是进程间通信( Interprocess communication,IPC)的演变,以利用基于文本的序列化格式,如 XML 和 JSON。像 SOAP 这样的协议允许跨 HTTP 的 IPC,很快Web开发人员不仅仅构建向浏览器提供内容的 Web 应用程序,还有能执行操作并将数据传递给其他程序的 Web 服务。这种基于服务的架构被证明是非常强大的,因为它消除了对共享代码库的依赖,并且允许应用程序开发人员进一步分离他们的应用程序组件。SOAP 协议和相关的 WS- *标准很快就变得越来越复杂,并且严重依赖于应用程序服务器中的特定实现,因此开发人员迁移到更轻量级的 REST 协议。随着移动设备使用数量爆炸增长以及 web UX 开发转向 AJAX 和 JavaScript 框架, 应用开发者开始扩展 REST 用于在客户端与网络服务器间传输数据。

事实证明,MVC 框架也非常适合开发 REST 端点。REST的资源导向性很好地映射到控制器和模型的概念,如图3所示。

单片架构

因此,曾经由模型、视图和控制器组成的 MVC 应用程序主要提供 HTML 内容,而这些应用程序不仅能够提供传统的 HTML,还能够通过 REST 端点提供 JSON。许多这些应用程序都使用单片架构。该应用程序被部署为单个文件(即 Java)或以同一目录(即 Rails)为根的文件集合。所有的应用程序代码都在同一个进程中运行。扩展需要将完全相同的应用程序代码的多个副本部署到多个服务器。图4描绘了一个单片架构:

单片架构存在许多问题。首先,随着功能和服务被添加到应用程序中,代码库将变得更加复杂。这可能令新开发人员望而生畏。现代 IDE 甚至可能在加载整个应用程序代码时遇到问题,并且编译和构建的时间很长。由于所有应用程序代码都在服务器上的相同进程中运行,因此很难(如果不是不可能)缩放应用程序的各个部分。如果一项服务占用大量内存,另一项占用大量 CPU,则必须为服务器配备足够的内存和 CPU 以处理每项服务的基准负载。如果每个服务器都需要大量的 CPU 和内存,成本将会很高,如果使用负载均衡来横向扩展应用程序,会加剧此问题。最后,更微妙的是,工程团队的结构往往会随着时间的推移而开始反映应用程序架构。UX 工程师将负责构建 UI 组件,中间层开发人员将构建服务端点,而数据库工程师和 DBA(数据库管理员) 将负责处理数据访问组件和数据库。如果 UX 工程师想要将一些数据添加到屏幕上,这将涉及与中间层和数据库工程师的协调。就像水一样,人们往往采取阻力最小的路径,这意味着每个工程组都会尝试在他们控制的应用程序的部分中嵌入尽可能多的逻辑。这是一个保证随时间推移的不可维护代码的公式。

微服务架构

微服务架构旨在解决这些问题。整体应用程序体系结构中定义的服务被分解为单独的服务,并在不同的主机上彼此分开部署。

每个微服务都与特定的业务功能保持一致,并且只定义该业务功能所需的操作。这听起来可能与面向服务的体系结构(service-oriented architecture,SOA)完全相同,而微服务体系结构和 SOA 确实具有一些共同的特征。两种体系结构都将代码组织到服务中,并且都定义了明确的边界,这些边界代表了服务应与其他服务分离的点。然而,SOA 源于集成彼此暴露API(通常基于SOAP)的单片应用程序的需求。在 SOA 中,集成严重依赖于中间件,特别是企业服务总线(enterprise service bus,ESB)。通常微服务体系结构可能使用消息总线,但消息层中没有任何逻辑 —— 它纯粹用作从一个服务到另一个服务的消息传输。这与 ESB 有很大的不同,ESB 包含消息路由、模式验证、消息转换和业务规则的大量逻辑。因此,微服务体系结构比传统 SOA 简单得多,并且不需要相同级别的治理和规范化数据建模来定义服务之间的接口。借助微服务,开发非常迅速,服务也随着业务需求而发展。

微服务架构的另一个关键优势是服务可以根据其资源需求单独进行扩展。微服务不必运行配置大量 CPU 和 内存 的大型服务器,而是可以部署在仅包含该服务所需资源的较小主机上。另外,每个服务都可以用最适合服务执行操作的语言实现。图像处理服务可以使用像 C ++ 这样的高性能的语言来实现。执行数学或统计操作的服务可以用 Python 实现。执行资源基本的 CRUD 操作的服务可能最好用 Ruby 实现。微服务架构不需要单片架构的 “一刀切” 模型,

但是微服务也有一些缺点。由于服务分布在多个主机上,因此难以跟踪哪些主机运行某些服务。而且,尽管每台主机可能不如运行单片应用程序的主机那么强大,但随着微服务架构的扩展,主机数量的增长速度将高于使用单片架构的速度。在 AWS 环境中,甚至可能会有不需要所有资源的微服务,即使是最小的 EC2 实例类型。这会导致过度配置并增加成本。如果服务以不同的编程语言实现,这意味着每个服务的部署需要一套完全不同的库和框架,以便部署到服务器组合中。

救援容器

Linux容器可以帮助缓解微服务架构中的许多挑战。Linux 容器使用内核接口(如 cname和命名空间),它们允许多个容器在完全隔离的情况下共享相同的内核。Docker 执行环境使用一个名为 libcontainer 的模块,它将这些接口标准化。Docker 还为容器镜像提供了一个类似 GitHub 的 DockerHub 存储库,可以轻松共享和分发容器。正是在同一主机上运行的容器之间的这种隔离,使得使用不同语言和框架开发微服务代码变得非常容易。使用 Docker,我们可以创建一个 DockerFile 来描述该服务的所有语言、框架和库依赖关系。例如,下方的 DockerFile 可以定义一个使用 Ruby 和 Sinatra 框架的微服务 Docker 镜像:

代码语言:txt
复制
FROM ubuntu:14.04
MAINTAINER John Doe <jdoe@example.com>
RUN apt-get update && apt-get install -y curl wget default-jre git
RUN adduser ——home /home/sinatra ——disabled-password ——gecos '' sinatra
RUN adduser sinatra sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER sinatra
RUN curl -sSL https://get.rvm.io | bash -s stable
RUN /bin/bash -l -c "source /home/sinatra/.rvm/scripts/rvm"
RUN /bin/bash -l -c "rvm install 2.1.2"
RUN /bin/bash -l -c "gem install sinatra"
RUN /bin/bash -l -c "gem install thin"

使用 Java 和 DropWizard 框架,从此镜像创建的容器可以轻松放置在运行另一个从 Docker 镜像创建的容器主机上。容器执行环境将主机上运行的每个容器彼此隔离,因此不存在由一个容器使用的语言、库或框架的依赖关系会与另一个容器有相互冲突的风险。

容器的便携性也使微服务的部署变得轻而易举。要推出运行在给定主机上的服务的新版本,可以简单地停止正在运行的容器,并使用最新版本的服务代码启动基于 Docker 镜像的新容器。在主机上运行的所有其他容器都不会受到此更改的影响。

容器还有助于高效利用主机上的资源。如果给定服务未使用 Amazon EC2 实例上的所有资源,则可以在该实例的容器中启动其他服务,这些服务将使用空闲资源。当然,如果手动完成,那么在容器中部署服务、管理在哪些主机上运行哪些服务以及跟踪所有运行容器的主机的容量利用率将很快变得无法管理。

最近宣布的 Amazon EC2容器服务 (Amazon ECS)能为你解决所有这些问题。使用Amazon ECS,你可以将计算资源池定义为一个"集群( Cluster )"。集群由一个或多个Amazon EC2实例组成。 Amazon ECS 管理集群中运行的所有基于容器的应用程序的状态,提供遥测和日志记录,并管理集群的容量利用情况,从而实现高效的工作安排。 Amazon ECS 提供称为“任务定义( task definition )”的结构体,该结构体用于定义组成应用程序的容器分组。任务定义中的每个容器都指定该容器所需的资源,Amazon ECS 将根据集群中的可用资源安排该任务的执行。

微服务很容易被定义为一个任务,一个微服务可能包含两个容器 —— 一个运行服务端点代码,另一个运行数据库。 Amazon ECS 管理这些容器之间的依赖关系,以及整个集群中资源的所有平衡。 Amazon ECS 还提供对 Elastic Load Balancing(弹性负载均衡),Amazon EBS,Elastic Network Interface (弹性网络接口 )和Auto Scaling (自动伸缩)等重要 AWS 服务的无缝访问。借助 Amazon ECS,使用 Amazon EC2 部署应用程序的所有这些基本功能都可用于基于容器的应用程序。

像 Amazon ECS 这样的容器管理解决方案也简化了 “service discovery (服务发现)” 的实现。由于微服务通常部署在多个主机上,并且经常根据负载进行扩展伸缩,因此需要服务发现才能使一个服务知道如何找到其他服务。在最简单的情况下,可以使用负载均衡器。但在许多情况下,必须使用真正的分布式配置服务,例如 Apache Zookeeper。 Amazon ECS API 可以与 Zookeeper 等第三方工具集成。也可以使用 Amazon ECS 来管理 Zookeeper 集群。可以使用任务定义将包含 Zookeeper 集群的容器分组在一起,并通过 Amazon ECS 服务安排在集群中的 Amazon EC2 主机上执行。

从很多方面来说,使用容器来实现微服务架构是一种演变,与过去20年在 Web 开发中观察到的没有什么不同。大多数这种演变都是由于需要更好地利用计算资源以及维护日益复杂的基于 Web 的应用程序的需求。正如我们所看到的,使用带有 Linux 容器的微服务架构可满足这些需求。我们简要介绍了如何将微服务定义为 Amazon ECS 中的任务,但在分布式系统中使用容器远远超出了微服务。容器越来越多地成为所有分布式系统中的 “一等公民”,在接下来的文章中,我们将讨论对于管理基于容器的计算上,像 Amazon ECS 这样的工具重要程度几何。

查看本系列的下一篇文章:使用 Docker 和 Amazon EC2 容器服务的基于集群的体系结构

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Web 开发简史
  • REST 协议的兴起
  • 单片架构
  • 微服务架构
  • 救援容器
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档