亚马逊、阿里、Netflix等很多公司都采用所谓的微服务架构模式解决了单体地狱问题。与其构建一个单一的应用程序,不如将您的应用程序拆分为一组更小的互连服务。服务通常实现一组不同的特性或功能,例如订单管理、客户管理等。每个微服务都是一个微型应用程序,具有自己的六边形架构,由业务逻辑和各种适配器组成。一些微服务公开了一个API,供其他微服务或应用程序客户端使用。其他微服务可能会实现WebUI。在运行时,每个实例通常是云虚拟机或Docker容器。例如,一个网约车软件系统的可能分解如下图所示:示例网约车应用程序的微服务架构,每个微服务提供一个RESTfulAPI微服务架构模式现在表示应用程序的每个功能区域由自己的微服务服务实现。此外,Web应用程序被拆分为一组更简单的Web应用程序(例如,在我们的出租车示例中,一个用于乘客,一个用于司机)。这使得为??特定用户、设备或特殊用例部署不同的体验变得更加容易。每个后端服务公开一个RESTAPI,大多数服务使用其他服务提供的API。例如,DriverManagement使用通知服务器来通知可用的驱动程序有关潜在行程的信息。UI服务调用其他服务来呈现网页。服务也可以使用异步的、基于消息的通信。本系列稍后将更详细地介绍服务间通信。一些RESTAPI也暴露给司机和乘客使用的移动应用程序。但是,这些应用程序无法直接访问后端服务。相反,通信由称为API网关的中介进行调解。APIGateway负责负载均衡、缓存、访问控制、API计量和监控等任务,APIGateway可以使用NGINX有效地实现。“ScaleCube”微服务架构模式将功能分解为Y轴上的微服务,对应于ScaleCube的Y轴缩放,这是优秀书籍TheArtofScalability中可扩展性的3D模型。另外两个缩放轴是X轴缩放,它涉及在负载均衡器后面运行多个相同的应用程序副本,以及Z轴缩放(或数据分区),其中请求的属性(例如,主键行或客户身份)用于将请求路由到特定的服务器。应用程序通常同时使用这三种类型的缩放。Y轴缩放将应用程序分解为微服务,如本节的第一个图表所示。在运行时,X轴缩放在负载均衡器后面运行每个服务的多个实例,以提高吞吐量和可用性。一些应用程序也可能使用Z轴缩放来划分服务。下图显示了如何使用运行在AmazonEC2上的Docker部署差旅管理服务。用于乘车服务的示例微服务应用程序,部署在Docker容器中并由负载均衡器作为前端在运行时,乘车管理服务由多个服务实例组成。每个服务实例都是一个Docker容器。为了实现高可用性,容器在多个云虚拟机上运行。在服务实例前面是一个负载均衡器,例如NGINX,它在实例之间分配请求。负载均衡器还可以处理其他问题,例如缓存、访问控制、API计量和监控。微服务架构模式显着影响应用程序和数据库之间的关系。每个服务都有自己的数据库模式,而不是与其他服务共享一个数据库模式。一方面,这种做法与企业级数据模型的思路不一致。此外,它通常会导致某些数据重复。但是,如果您想从微服务中获益,每个服务都有一个数据库模式是必不可少的,因为它可以确保松散耦合。下图显示了示例应用程序的数据库架构。乘车服务示例微服务应用程序中的数据库架构每个服务都有自己的数据库。此外,服务可以使用最适合其需求的数据库类型,即所谓的多语言持久性架构。例如,在潜在乘客附近寻找司机的司机管理必须使用支持高效地理查询的数据库。从表面上看,微服务架构的模式类似于SOA。对于这两种方法,体系结构都由一组服务组成。然而,考虑微服务架构模式的一种方式是,它是一种SOA,没有Web服务规范和企业服务总线(ESB)的商品化和感知包袱。基于微服务的应用程序更喜欢更简单、轻量级的协议,例如REST而不是WS-*。他们也非常避免使用ESB,而是在微服务本身中实现类似ESB的功能。微服务架构模式也拒绝SOA的其他部分,例如规范模式的概念。微服务的好处微服务架构模式有很多重要的好处。首先,它解决了业务复杂性问题。它将原本单一的应用程序分解为一组服务。虽然功能总量保持不变,但应用程序已分解为可管理的业务或服务。每个服务都有一个以RPC或消息驱动API形式定义的边界。微服务架构模式强制执行一定程度的模块化,这在实践中很难通过单体代码库实现。因此,单个服务的开发速度要快得多,并且更容易理解和维护。其次,这种架构使每项服务都可以由专门负责该服务的团队独立开发。开发人员可以自由选择任何有意义的技术,前提是服务遵守API合同。当然,大多数组织希望避免完全无政府状态并限制技术选择。然而,这种自由意味着开发人员不再有义务使用在新项目开始时可能已经过时的技术。在编写新服务时,他们可以选择使用当前技术。此外,由于服务相对较小,使用当前技术重写旧服务变得可行。第三,微服务架构模式使得每个微服务都可以独立部署。开发人员永远不需要协调对其服务的本地更改的部署。这些类型的更改可以在测试后立即部署。例如,UI团队可以执行A/B测试并快速迭代UI更改。微服务架构模式支持持续部署。最后,微服务架构模式使每个服务都可以独立扩展。您只能部署满足其容量和可用性限制的每个服务的尽可能多的实例。此外,您可以使用最符合您的服务资源要求的硬件。例如,您可以在EC2计算优化实例上部署CPU密集型图像处理服务,并在EC2内存优化实例上部署内存数据库服务。正如FredBrooks将近30年前所写,微服务的缺点是没有灵丹妙药。与所有其他技术一样,微服务架构也有缺点。一个缺点是名称本身。微服务一词过于强调服务规模。事实上,一些开发人员提倡构建极其细粒度的10-100LOC服务。虽然小型服务更可取,但重要的是要记住它们是达到目的的手段,而不是主要目标。微服务的目标是将应用程序充分分解,以促进应用程序的敏捷开发和部署。微服务的另一个主要缺点是微服务应用程序是分布式系统这一事实带来的复杂性。开发者需要选择并实现一种基于消息传递或RPC的进程间通信机制。此外,他们必须编写代码来处理部分故障,因为请求的目的地可能很慢或不可用。虽然这些都不是火箭科学,但它比模块通过语言级方法/过程调用相互调用的单体应用程序要复杂得多。微服务的另一个挑战是分区数据库架构。更新多个业务实体的业务事务相当普遍。这些类型的事务很容易在单体应用程序中实现,因为只有一个数据库。但是,在基于微服务的应用程序中,您需要更新不同服务拥有的多个数据库。使用分布式事务通常不是一种选择,这不仅仅是因为CAP定理。许多当今高度可扩展的NoSQL数据库和消息代理根本不支持它们。您最终不得不使用基于最终一致性的方法,这对开发人员来说更具挑战性。测试微服务应用程序也复杂得多。例如,使用像SpringBoot这样的现代框架,编写一个启动单体Web应用程序并测试其RESTAPI的测试类是微不足道的。相反,服务的类似测试类需要启动该服务及其依赖的任何服务(或至少为这些服务配置存根)。同样,这不是火箭科学,但重要的是不要低估这样做的复杂性。微服务架构模式的另一个主要挑战是跨多个服务实施变更。例如,假设您正在实现一个需要更改服务A、B和C的故事,其中A依赖B,B依赖C。在单体应用程序中,您可以简单地更改相应的模块,集成更改,并一次部署它们。相比之下,在微服务架构模式中,您需要仔细规划和协调对每个服务的更改的推出。例如,您需要更新服务C,然后是服务B,最后是服务A。幸运的是,大多数更改通常只影响一个服务,需要协调的多服务更改相对较少。部署基于微服务的应用程序也更加复杂。单个应用程序只需部署在传统负载均衡器后面的一组相同服务器上。每个应用程序实例都配置了基础设施服务的位置(主机和端口),例如数据库和消息代理。相比之下,微服务应用程序通常由大量服务组成。例如,根据AdrianCockcroft的说法,Hailo有160种不同的服务,而Netflix有超过600种[编辑-Hailo已被MyTaxi收购。].每个服务将有多个运行时实例。这些是需要配置、部署、扩展和监控的更多活动部件。此外,您还需要实现一种服务发现机制(在后面的文章中讨论),使服务能够发现它需要与之通信的任何其他服务的位置(主机和端口)。传统的基于票证的手动操作方法无法扩展到这种复杂程度。因此,成功部署微服务应用程序需要开发人员更好地控制部署方法,以及高度自动化。实现自动化的一种方法是使用现成的PaaS,例如CloudFoundry。PaaS为开发人员提供了一种部署和管理微服务的简便方法。它使他们无需担心采购和配置IT资源等问题。同时,配置PaaS的系统和网络专业人员可以确保符合最佳实践和公司政策。另一种自动化微服务部署的方法是开发本质上属于您自己的PaaS。一个典型的起点是使用Kubernetes等集群解决方案和Docker等技术。在本系列的后面,我们将看到基于软件的应用程序交付方法(例如NGINXPlus)可以轻松处理缓存、访问控制、API计量和监控,可以帮助实现这一点。总之,构建复杂的应用程序本身就很困难。单体架构只对简单、轻量级的应用程序有意义。如果你将它用于复杂的应用程序,你将陷入痛苦的世界。尽管存在缺陷和实施挑战,但微服务架构模式是复杂、不断发展的应用程序的更好选择。
