导图社区 c架构思维导图
简述了微服务的整个架构体系,构成,以及现有支持的技术
编辑于2020-03-28 14:28:14微服务
优缺点
优点
巨大的整体应用程序分解为一组服务。虽然功能总数不变,但该应用程序已分为可管理的块或服务 该体系结构使每个服务可以由专注于该服务的团队独立开发。开发人员可以自由选择任何有意义的技术,只要该服务遵守API合同即可。 微服务架构模式使每个微服务可以独立部署。 微服务架构模式使每个服务都可以独立扩展。您可以仅部署满足其容量和可用性约束的每个服务的实例数。此外,您可以使用最符合服务资源要求的硬件。例如,您可以在EC2 Compute Optimized实例上部署CPU密集型图像处理服务,并在EC2 Memory Optimized实例上部署内存数据库服务。
缺点
微服务一词过分强调服务规模。实际上,有些开发人员主张构建极细粒度的10-100 LOC服务。尽管小型服务是更可取的,但重要的是要记住,它们是达到目的的一种手段,而不是主要目标。微服务的目标是充分分解应用程序,以促进敏捷应用程序的开发和部署。 分布式系统这一事实而导致的复杂性。开发人员需要选择并实现基于消息传递或RPC的进程间通信机制。此外,由于请求的目的地可能很慢或不可用,它们还必须编写代码来处理部分失败。 分区数据库体系结构。更新多个业务实体的业务交易相当普遍。由于只有一个数据库,因此在单一应用程序中实现这类事务很简单。但是,在基于微服务的应用程序中,您需要更新不同服务拥有的多个数据库。 微服务架构模式的另一个主要挑战是实现跨多个服务的更改。例如,假设您正在实现一个需要更改服务A,B和C的案例,其中A依赖于B,B依赖于C。 在微服务架构模式中,您需要仔细计划和协调对每个服务的更改的推出。例如,您需要先更新服务C,然后再更新服务B,最后再更新服务A。 部署基于微服务的应用程序也要复杂得多。
解决问题:
解决复杂性
应用程序拆分为一组较小的,相互连接的服务。 服务通常实现一组不同的特征或功能。 每个微服务都是一个微型应用程序,具有自己的六边形体系结构,该体系结构由业务逻辑和各种适配器组成。 某些微服务会公开其他微服务或应用程序客户端使用的API。其他微服务可能实现Web UI。在运行时,每个实例通常是云VM或Docker容器。
微服务与分布式数据管理问题
关系数据库ACID事务
原子性–原子地进行更改 一致性–数据库状态始终是一致的 隔离–即使事务是同时执行的,看起来它们还是串行执行的 耐用性–交易一旦提交,便不会撤消
第一个挑战是如何实现在多个服务之间 保持一致性的业务交易。
第二个挑战是如何实现从多个服务检索数 据的查询。
事件驱动架构
微服务会在发生显着事件(例如更新业务实体)时发布事件。 其他微服务订阅了这些事件。当微服务收到事件时,它可以 更新自己的业务实体,这可能导致发布更多事件。微服务通过 消息代理交换事件。

优缺点
事件驱动的体系结构有几个优点和缺点。它使跨多个服务的事务的实现成为可能,并提供最终的一致性。另一个好处是它还使应用程序能够维护实例化视图。一个缺点是,编程模型比使用ACID事务时更复杂。通常,您必须实施补偿事务以从应用程序级故障中恢复;例如,如果信用检查失败,则必须取消订单。此外,应用程序必须处理不一致的数据。这是因为可以看到机内交易所做的更改。如果应用程序从尚未更新的实例化视图中读取数据,则还会看到不一致之处。另一个缺点是订户必须检测并忽略重复的事件。
实现原子性
还存在原子更新数据库并发布事件的问题。例如,订购服务必须在ORDER表中插入一行并发布订购创建事件。这两个操作必须原子完成。如果服务在更新数据库之后但在发布事件之前崩溃,则系统会变得不一致。确保原子性的标准方法是使用涉及数据库和Message Broker的分布式事务。但是,由于上述原因(例如CAP定理),这正是我们不希望做的。
使用本地事务发布事件
实现原子性的一种方法是,应用程序使用仅涉及本地事务的多步骤过程来发布事件。 诀窍是在存储业务实体状态的数据库中具有一个EVENT表,该表充当消息队列。 1.应用程序开始(本地)数据库事务,更新业务实体的状态,将事件插入EVENT表,然后提交事务。 2.单独的应用程序线程或进程查询EVENT表,将事件发布到Message Broker,然后使用本地事务将事件标记为已发布。
EVENT表(充当消息队列)
1.应用程序开始(本地)数据库事务,更新业务实体的状态,将事件插入EVENT表,然后提交事务。 2.单独的应用程序线程或进程查询EVENT表,将事件发布到Message Broker,然后使用本地事务将事件标记为已发布。

优缺点
一个好处是,它可以确保每次更新都发布一个事件,而无需依赖2PC。此外,该应用程序还发布业务级别的事件,从而无需推断它们。 一个缺点是,由于开发人员必须记住要发布事件,因此它很容易出错。这种方法的局限性在于,由于它们的事务和查询功能有限,因此在使用某些NoSQL数据库时难以实施
一种通过使应用程序简单地 更新状态来实现原子性的方法。
挖掘数据库事务日志
在没有2PC的情况下实现原子性的另一种方法是 事件由挖掘数据库事务或提交日志的线程或进程发布。该应用程序更新数据库,这导致更改被记录在数据库的事务日志中。事务日志挖掘器线程或进程读取事务日志并将事件发布到Message Broker。

例子
这种方法的一个示例是开源LinkedIn Databus项目。Databus挖掘Oracle事务日志并发布与更改相对应的事件。LinkedIn使用Databus来保持各种派生数据存储与记录系统一致。 另一个示例是AWS DynamoDB中的流机制,这是一个托管的NoSQL数据库。DynamoDB流包含过去24小时内对DynamoDB表中的项目进行的按时间顺序排列的更改(创建,更新和删除操作)序列。应用程序可以从流中读取这些更改,例如,将其作为事件发布。
优缺点
一个好处是,它保证了每次更新都可以发布事件,而无需使用2PC。事务日志挖掘还可以通过将事件发布与应用程序的业务逻辑分开来简化应用程序。 一个主要的缺点是事务日志的格式是每个数据库专有的,甚至可以在数据库版本之间进行更改。同样,可能很难从事务日志中记录的低级更新中对高级业务事件进行反向工程。 事务日志挖掘通过让应用程序执行一件事来消除对2PC的需求:更新数据库
使用事件源
通过使用根本不同的,以事件为中心的方法来持久化业务实体,事件采购无需2PC就可以实现原子性。 该应用程序不是存储实体的当前状态,而是存储一系列状态更改事件。 该应用程序通过重播事件来重建实体的当前状态。 只要业务实体的状态发生变化,就会在事件列表中附加一个新事件。 由于保存事件是单个操作,因此它本质上是原子的。
每个订单都映射到ORDER表中的一行以及例如ORDER_LINE_ITEM表中的行。但是,在使用事件源时,订单服务以其状态更改事件的形式存储订单:已创建,已批准,已发货,已取消。每个事件都包含足够的数据来重构订单状态。 
优缺点
事件存储的行为也类似于消息代理。它提供了使服务能够订阅事件的API。事件存储将所有事件传递给所有感兴趣的订户。事件存储是事件驱动的微服务体系结构的骨干。 事件源有几个好处。它解决了实现事件驱动的体系结构中的关键问题之一,并使得在状态改变时可靠地发布事件成为可能。结果,它解决了微服务体系结构中的数据一致性问题。另外,由于它保留事件而不是域对象,因此它可以避免对象关系阻抗不匹配的问题。事件源还提供了对业务实体所做的更改的100%可靠的审核日志,并使得可以实施临时查询来确定实体在任何时间点的状态。事件源的另一个主要优点是您的业务逻辑由交换事件的松散耦合的业务实体组成。这使得从单片应用程序迁移到微服务架构变得容易得多。 事件源也有一些缺点。这是一种不同且陌生的编程风格,因此存在学习曲线。事件存储区仅直接支持通过主键查找业务实体。您必须使用命令查询职责隔离(CQRS)来实现查询。结果,应用程序必须处理最终一致的数据。 第一个挑战是如何实现在多个服务之间保持一致性的业务交易。第二个挑战是如何实现从多个服务检索数据的查询。 对于许多应用程序,解决方案是使用事件驱动的体系结构。实现事件驱动的体系结构的一个挑战是如何原子更新状态以及如何发布事件。有几种方法可以做到这一点,包括将数据库用作消息队列,事务日志挖掘和事件源。
重构到微服务
停止挖掘
您应该停止将整体增大。这意味着在实现新功能时,不应将更多代码添加到整体中。相反,此策略的主要思想是将新代码放入独立的微服务中。
分割前端和后端
缩小整体应用程序的一种策略是将表示层与业务逻辑和数据访问层分开。典型的企业应用程序至少包含三种不同类型的组件: 表示层–处理HTTP请求并实现(REST)API或基于HTML的Web UI的组件。在具有复杂用户界面的应用程序中,表示层通常是大量的代码。 业务逻辑层–作为应用程序核心并实现业务规则的组件。 数据访问层–访问基础结构组件的组件,例如数据库和消息代理。 通常,一侧的表示逻辑与另一侧的业务和数据访问逻辑之间完全分开。业务层具有由一个或多个外观组成的粗粒度API,这些外观封装了业务逻辑组件。该API是一个自然的接缝,您可以沿着该接缝将整料分割成两个较小的应用程序。一个应用程序包含表示层。另一个应用程序包含业务和数据访问逻辑。拆分之后,表示逻辑应用程序对业务逻辑应用程序进行远程调用
提取服务
如何提取模块 提取模块的第一步是定义模块和整体之间的粗粒度界面。它最有可能是双向API,因为整体将需要服务拥有的数据,反之亦然。由于模块和应用程序其余部分之间存在复杂的依赖关系和细粒度的交互模式,因此实现这样的API通常具有挑战性。由于域模型类之间存在大量关联,因此使用域模型模式实现的业务逻辑尤其难以重构。您通常需要进行重大的代码更改才能打破这些依赖性。下图显示了重构。 一旦实现了粗粒度接口,就可以将模块变成独立的服务。为此,您必须编写代码以使整体组件和服务能够通过使用进程间通信(IPC)机制的API进行通信。
Service Instance 2(eg:Docker容器)
数据库
通信
REST API
部署
Service Instance 2(eg:Docker容器)
数据库
通信
REST API
部署
客户端⇔服务交互方式
同步
同步–客户端期望服务及时响应,甚至在等待时可能会阻塞
异步
异步–客户端在等待响应时不会阻塞,并且响应(如果有的话)不一定会立即发送。
一对一
一对一–每个客户端请求仅由一个服务实例处理。 请求/响应–客户端向服务发出请求并等待响应。客户希望响应能够及时到达。在基于线程的应用程序中,发出请求的线程甚至可能在等待时阻塞。 通知(也称为单向请求)–客户端向服务发送请求,但不希望或未发送答复。 请求/异步响应–客户端将请求发送到服务,该服务以异步方式答复。客户端在等待时不会阻塞,并假设响应可能不会在一段时间内到达。
子主题
一对多
一对多–每个请求由多个服务实例处理 发布/订阅–客户端发布通知消息,该消息由零个或更多感兴趣的服务使用。 发布/异步响应–客户端发布请求消息,然后等待一定时间以等待感兴趣的服务的响应。
负载均衡器
API 网关
负载平衡
缓存
访问控制
API计量
监视
请求路由,组合和协议转换
优点&缺点
优点 好处是它封装了应用程序的内部结构。客户端不必调用特定的服务,而只是与网关进行对话。API网关为每种客户端提供特定的API。这减少了客户端与应用程序之间的往返次数。它还简化了客户端代码。 缺点 它是另一个必须开发,部署和管理的高可用性组件。API网关也有成为开发瓶颈的风险。开发人员必须更新API网关才能公开每个微服务的端点。
技术实现
在JVM上,您可以使用基于NIO的框架之一,例如Netty,Vertx,Spring Reactor或JBoss Undertow。 一种流行的非JVM选项是Node.js,它是基于Chrome的JavaScript引擎构建的平台。 NGINX Plus提供了易于部署,配置和编程的成熟,可扩展的高性能Web服务器和反向代理。NGINX Plus可以管理身份验证,访问控制,负载平衡请求,缓存响应,并提供可感知应用程序的运行状况检查和监视。
实施API 网关
服务实例
基于微服务的应用程序是在多台计算机上运行的分布式系统。每个服务实例通常是一个进程。服务必须使用进程间通信(IPC)机制进行交互。
服务调用
基于微服务的应用程序是一个分布式系统,必须使用进程间通信机制。
进程间通信机制
消息的异步实现
JMS
标准协议
AMQP
STOMP
优点&缺点
使用消息传递有很多优点: 使客户端与服务脱钩–客户端仅通过向适当的通道发送消息即可发出请求。客户端完全不知道服务实例。它不需要使用发现机制来确定服务实例的位置。 消息缓冲–使用同步请求/响应协议(例如HTTP),客户端和服务在交换期间必须都可用。相反,消息代理将写入通道的消息排队,直到消费者可以处理它们为止。例如,这意味着即使订单履行系统很慢或不可用,在线商店也可以接受来自客户的订单。订单消息只是排队。 灵活的客户端-服务交互–消息支持前面描述的所有交互样式。 显式进程间通信–基于RPC的机制试图使调用远程服务看起来与调用本地服务相同。但是,由于物理定律和部分失效的可能性,它们实际上是完全不同的。消息传递使这些差异非常明显,因此开发人员不会陷入错误的安全感中。 但是,使用消息传递有一些缺点: 额外的操作复杂性–邮件系统是又一个必须安装,配置和操作的系统组件。消息代理必须高度可用,否则系统可靠性会受到影响。 实现基于请求/响应的交互的复杂性–请求/响应式的交互需要一些工作来实现。每个请求消息必须包含一个回复通道标识符和一个相关标识符。服务将包含相关ID的响应消息写入回复通道。客户端使用相关性ID将响应与请求进行匹配。使用直接支持请求/响应的IPC机制通常会更容易。
渠道
一条消息由标头(例如发送方之类的元数据)和一条消息主体组成。消息通过通道交换。任何数量的生产者都可以将消息发送到一个频道。同样,任何数量的使用者都可以从频道接收消息。有两种渠道,点对点渠道和发布订阅渠道。点对点通道将消息传递给正从该通道读取的消费者中的一个。服务使用点对点渠道进行前面所述的一对一交互样式。发布订阅通道将每个消息传递给所有附加的使用者。服务将发布-订阅通道用于上述一对多交互样式。
点对点渠道
发布订阅渠道

消息系统
RabbitMQ,Apache Kafka,Apache ActiveMQ和NSQ。
同步机制
请求/响应IPC 当使用基于请求/响应的同步IPC机制时,客户端会将请求发送到服务。该服务处理请求并发送回响应。在许多客户端中,发出请求的线程在等待响应时会阻塞。其他客户端可能使用异步的,事件驱动的客户端代码,这些代码可能由Futures或Rx Observables封装。但是,与使用消息传递时不同,客户端假定响应将及时到达。有许多协议可供选择。两种流行的协议是REST和Thrift。
HTTP&REST API
https://www.nginx.com/blog/building-microservices-inter-process-communication/
Thrift
服务发现
API网关需要知道与之通信的每个微服务的位置(IP地址和端口) https://www.jianshu.com/p/b0a073207bb0 服务实例具有动态分配的网络位置。而且,服务实例集会由于自动缩放,故障和升级而动态更改。因此,您的客户端代码需要使用更复杂的服务发现机制。 有两种主要的服务发现模式:客户端发现和服务器端发现。 HTTP反向代理和负载平衡器(例如NGINX)也可以用作服务器端发现负载平衡器。服务注册中心可以将路由信息推送到NGINX并调用正常的配置更新。例如,您可以使用Consul Template。NGINX Plus支持其他动态重新配置机制 –它可以使用DNS从注册表中获取有关服务实例的信息,并且提供用于远程重新配置的API。
客户端发现
客户端负责确定可用服务实例的网络位置,并在它们之间进行负载平衡请求。客户端查询服务注册表,该服务注册表是可用服务实例的数据库。然后,客户端使用负载平衡算法来选择可用的服务实例之一并发出请求。  服务实例的网络位置在启动时会在服务注册表中注册。实例终止时,将从服务注册表中将其删除。通常使用心跳机制定期刷新服务实例的注册。
服务器端发现
客户端通过负载平衡器向服务发出请求。负载平衡器查询服务注册表,并将每个请求路由到可用的服务实例。 
例子
AWS弹性负载均衡(ELB)是一个服务器端发现路由器的一个例子 HTTP服务器和负载平衡器(例如NGINX Plus和NGINX)也可以用作服务器端发现负载平衡器 某些部署环境(例如Kubernetes和Marathon)在群集中的每个主机上运行代理
使用原因
正在运行的服务实例集会动态更改。实例具有动态分配的网络位置。因此,为了使客户端对服务进行请求,它必须使用服务发现机制。
服务注册表 Eureka
该服务注册表是服务发现的一个关键部分。它是一个数据库,其中包含服务实例的网络位置。 服务发现的关键部分是服务注册表。服务注册表是可用服务实例的数据库。服务注册表提供管理API和查询API。服务实例使用管理API在服务注册表中注册或注销。系统组件使用查询API查找可用的服务实例。
例子
Netflix Eureka是服务注册表的一个很好的例子。 etcd –高可用性,分布式,一致的键值存储,用于共享配置和服务发现。使用etcd的两个著名项目是Kubernetes和Cloud Foundry。 consul –用于发现和配置服务的工具。它提供了一个API,允许客户端注册和发现服务。领事可以执行运行状况检查以确定服务可用性。 Apache Zookeeper –广泛用于分布式应用程序的高性能协调服务。Apache Zookeeper最初是Hadoop的子项目,但现在是顶级项目。
服务注册模式
自我注册模式
服务实例负责在服务注册表中进行自身注册和注销。同样,如果需要,服务实例会发送心跳请求以防止其注册过期。 通过实施包括服务发现在内的各种模式的Spring Cloud项目,可以轻松地在Eureka中自动注册服务实例。您只需使用注释对Java Configuration类进行@EnableEurekaClient注释。

第三方注册模式
在某些部署环境中,您需要使用服务注册中心(例如Netflix Eureka,etcd或Apache Zookeeper)来建立自己的服务发现基础结构。在其他部署环境中,内置了服务发现。例如,Kubernetes和Marathon处理服务实例的注册和注销。他们还在充当服务器端发现路由器角色的每个群集主机上运行代理。
服务实例不负责在服务注册表中自行注册。取而代之的是另一个称为服务注册器的系统组件来处理注册。服务注册商通过轮询部署环境或订阅事件来跟踪对正在运行的实例集的更改。当发现新的可用服务实例时,它将在服务注册表中注册该实例。服务注册商的另一个示例是NetflixOSS Prana

实现时要解决的问题
处理部分故障 实现API网关时必须解决的另一个问题是部分失败的问题。每当一个服务调用另一个响应缓慢或不可用的服务时,在所有分布式系统中都会出现此问题。API网关绝不应无限期地阻塞等待下游服务。
返回缓存的数据
通过返回默认数据或缓存的数据,API网关可确保系统故障不会影响用户体验。
本身缓存
外部缓存
例如Redis或Memcached。
断路器模式
Netflix Hystrix是一个非常有用的库,用于编写调用远程服务的代码。Hystrix使超出指定阈值的呼叫超时。它实现了断路器模式,可阻止客户端不必要地等待无响应的服务。如果服务的错误率超过指定的阈值,则Hystrix将使断路器跳闸,并且所有请求将在指定的时间内立即失败。Hystrix允许您定义请求失败时的回退操作,例如从缓存中读取或返回默认值。如果您使用的是JVM,则绝对应该考虑使用Hystrix。并且,如果您在非JVM环境中运行,则应使用等效的库。
网络超时
网络超时–永远不会无限阻塞,并且在等待响应时始终使用超时。使用超时可确保资源不会无限期地被占用。
提供回退
提供回退–当请求失败时执行回退逻辑。例如,返回缓存的数据或默认值,例如空的建议集
概念
API网关是服务器,是系统的单个入口点。它与面向对象设计中的“ 外观”模式相似。API网关封装了内部系统架构,并提供了针对每个客户端量身定制的API。它可能还具有其他职责,例如身份验证,监视,负载平衡,缓存,请求整形和管理以及静态响应处理。 
背景
一个问题是客户端需求与每个微服务公开的细粒度API之间的不匹配。 客户端直接调用微服务的另一个问题是,有些服务可能使用不支持Web的协议。一个服务可能使用Thrift二进制RPC,而另一服务可能使用AMQP消息传递协议。两种协议都不是特别适合浏览器或防火墙的协议,并且最好在内部使用。应用程序应在防火墙外部使用HTTP和WebSocket之类的协议
Service Instance 1(eg:Docker容器)
数据库
通信
REST API
部署
每个主机模式有多个服务实例

优缺点
优点: 一个主要的好处是它的资源使用相对高效。多个服务实例共享服务器及其操作系统。如果一个进程或进程组运行多个服务实例,例如共享同一个Apache Tomcat服务器和JVM的多个Web应用程序,则效率更高。 另一个好处是,部署服务实例相对较快。您只需将服务复制到主机并启动即可。如果服务是用Java编写的,则可以复制JAR或WAR文件。对于其他语言,例如Node.js或Ruby,则复制源代码。无论哪种情况,通过网络复制的字节数都相对较小。 缺点: “每个主机的多个服务实例”模式仍存在一些重大缺陷。一个主要缺点是,除非每个服务实例是一个单独的进程,否则服务实例几乎没有隔离。尽管可以准确地监视每个服务实例的资源利用率,但是不能限制每个实例使用的资源。行为异常的服务实例可能会消耗主机的所有内存或CPU。 如果多个服务实例在同一进程中运行,则根本没有隔离。例如,所有实例可能共享相同的JVM堆。行为异常的服务实例很容易破坏在同一进程中运行的其他服务。此外,您无法监视每个服务实例使用的资源。
每个主机模式的服务实例
部署微服务的另一种方法是“ 每主机服务实例”模式。使用此模式时,每个服务实例都在其自己的主机上独立运行。此模式有两种不同的专业化:每个虚拟机的服务实例和每个容器的服务实例
每个虚拟机模式的服务实例
 在每个虚拟机模式下使用服务实例时,会将每个服务打包为虚拟机(VM)映像,例如Amazon EC2 AMI。每个服务实例都是使用该VM映像启动的VM(例如,EC2实例)。下图显示了此模式的结构: 您可以使用多种工具来构建自己的VM。您可以配置持续集成(CI)服务器(例如Jenkins)以调用Aminator将服务打包为EC2 AMI。Packer.io是用于自动创建VM映像的另一个选项。与Aminator不同,它支持多种虚拟化技术,包括EC2,DigitalOcean,VirtualBox和VMware。 Boxfuse公司有一种引人注目的方式来构建VM映像,它克服了我在下面描述的VM的缺点。Boxfuse将Java应用程序打包为最小的VM映像。由于这些映像暴露出有限的攻击面,因此它们可以快速构建,快速启动并且更安全。 每个虚拟机模式的服务实例有很多好处。 VM的主要优点是,每个服务实例都可以完全隔离地运行。它具有固定数量的CPU和内存,无法从其他服务中窃取资源。 将微服务部署为VM的另一个好处是,您可以利用成熟的云基础架构。AWS之类的云提供了有用的功能,例如负载平衡和自动扩展。 将服务部署为VM的另一个巨大好处是,它封装了服务的实现技术。将服务打包为VM后,它将变成一个黑匣子。VM的管理API成为用于部署服务的API。部署变得更加简单和可靠。 缺点 一个缺点是资源利用效率较低。每个服务实例都有整个VM(包括操作系统)的开销。此外,在典型的公共IaaS中,VM具有固定的大小,并且VM使用率可能不足。 迁移时,公共IaaS通常对VM收费,而不管它们是忙还是闲。诸如AWS之类的IaaS提供自动缩放功能,但是很难对需求变化做出快速反应。因此,您通常必须过量配置VM,这会增加部署成本。 这种方法的另一个缺点是,部署新版本的服务通常很慢。由于VM映像的大小,其生成速度通常很慢。同样,再次由于其大小,VM实例化速度通常很慢。另外,操作系统通常需要一些时间才能启动。但是请注意,这并不是普遍适用的,因为存在轻量级VM,例如Boxfuse构建的那些。
每个容器模式的服务实例

当您使用“ 每个容器的服务实例”模式时,每个服务实例都在其自己的容器中运行。容器是操作系统级别的虚拟化机制。容器由在沙箱中运行的一个或多个进程组成。从进程的角度来看,它们具有自己的端口名称空间和根文件系统。您可以限制容器的内存和CPU资源。一些容器实现也具有I / O速率限制。容器技术的示例包括Docker和Solaris Zones。
请将服务打包为容器映像。容器映像是由运行服务所需的应用程序和库组成的文件系统映像。一些容器映像由完整的Linux根文件系统组成。其他则更轻巧。例如,要部署Java服务,您需要构建一个容器映像,其中包含Java运行时(可能是Apache Tomcat服务器)和已编译的Java应用程序。 将服务打包为容器映像后,便可以启动一个或多个容器。通常,您在每个物理或虚拟主机上运行多个容器。您可以使用集群管理器(例如Kubernetes或Marathon)来管理容器。集群管理器将主机视为资源池。它根据容器所需的资源和每个主机上可用的资源来决定将每个容器放置在何处。
优缺点
优点: 容器的好处类似于VM的好处。它们将您的服务实例彼此隔离。您可以轻松地监视每个容器消耗的资源。另外,容器与VM一样,封装了用于实现服务的技术。容器管理API也可用作管理服务的API。 容器是一种轻量级技术。容器映像通常构建起来非常快。例如,在我的笔记本电脑上,将Spring Boot应用程序打包为Docker容器仅需5秒钟。由于没有冗长的OS启动机制,因此容器也可以非常快速地启动。当容器启动时,运行的是服务。 缺点: 是,您要对管理容器图像进行无差别的繁重工作负责。另外,除非您使用托管容器解决方案(例如Google Container Engine或Amazon EC2容器服务(ECS)),否则您必须管理容器基础架构以及可能在其上运行的VM基础架构。 此外,容器通常部署在按虚拟机定价的基础架构上。因此,如前所述,您可能会产生过度配置VM的额外费用,以处理负载高峰。