微服务现在引起和很大的关注:文章,博客,讨论或者在社交媒体和会议报告上。他们正快速走向Gartner炒作周期的高估预期阶段。与此同时,在软件社区中有怀疑者角儿微服务没有任何新意。Naysayers声称这个想法只是SOA的重塑。不过,尽管有炒作和怀疑,微服务架构模式在敏捷开发和复杂交付应用中有明显的优势。

这篇博客是关于设计,建立,部署微服务七部曲中的第一篇。这个系列将讲解很多微服务元素。你将了解到微服务架构的优点和缺点。

译者:去掉了很多废话,跟上了一些注释和见解

编者 – 此七部曲已经完成:

  1. Introduction to Microservices (this article)
  2. Building Microservices: Using an API Gateway
  3. Building Microservices: Inter-Process Communication in a Microservices Architecture
  4. Service Discovery in a Microservices Architecture
  5. Event-Driven Data Management for Microservices
  6. Choosing a Microservices Deployment Strategy
  7. Refactoring a Monolith into Microservices

建立单体应用

让我们想象你将开始建立一个新的出租车招标程序,准备和Uber和Hailo竞争。在一些启动会议和需求采集之后。这个新的应用将具有模块化六边形架构,如图:

应用的核心是模块化实现的定义服务、对象和事件的业务逻辑,在核心周围是外部世界的接口。比如数据库组件,消息组件和产生和消费消息的组件,暴露API的web组件。

这样的应用非常常见,易于在IDE开发,测试,打包到服务器,在负载均衡后面挂几个有同样代码的服务器就行。在早期阶段这样没什么问题。

迈向单体应用的地狱

不幸的是,这样简单的方法有很大的限制。成功的应用有一个成长习惯最后变得巨大。在每一个急着开发的时候,你的开发团队实现了更多的功能,同时意味着很多行代码。几年后,你的小程序将成长为一个怪异的整体。给个极端的例子,我最近谈到一个开发人员,他正在写一个工具去在百万行代码的应用中分析数以千计的Jars之间的依赖关系。我确信很多开发人员在很多年后都会这样。

一旦你的应用变成了一个大的,复杂的怪兽,你的开发组织可能会处于一个痛苦的世界。任何的敏捷开发和部署都将完蛋。有这么多问题:

  1. 代码难以理解,新功能难以实现(译者觉得这些可能是你没重构的锅,退一步说,你的代码越少,重构的难度也会越少)
  2. 阻碍持续发布。测试、发布速度太慢。现在,SAAS应用每天都会推多次新的提交到产品环境中。(译者深有体会,要是测试需要30分钟,发布CI/UAT/PROD各自要10分钟的话一天差不多没了)
  3. 硬件软件选择困难。很难去针对业务来选择硬件或者数据库优化需求,AWS EC2的按需实例就是干这个的。
  4. 可靠性低。任何一个模块的BUG都可能导致整个应用崩溃。
  5. 更新框架难。换框架或者语言的时候你可能是崩溃的。以后有个很好的框架或者技术出来之后,你肯定会纠结到底换不换。

微服务-解决复杂性

Amazon, eBay用微服务来解决这个问题。不是构建一个但一个的怪物应用而是将你的应用分成一组较小的互相连接的服务。

一个应用通常要实现一组不同的功能,比如订单管理,客户管理。每个微服务都是个小的应用程序,有自己的六边形结构、业务逻辑和不同的适配器。一些微服务可能暴露API给别的微服务用或者给客户用。其他的微服务实现UI。运行时,每个实例都是个虚拟机或者Docker容器。

应用的每个功能都实现在自己的微服务。此外,应用被分成一组更简单的应用(比如一个给乘客一个给司机)。这使得为特定用户、设备或者不同的情况部署不同的体验。

每个后台服务暴露了一个REST API,大部分服务使用其他服务的API。比如司机管理服务使用通知服务去推送潜在的客户给司机。UI服务调用其他服务为了去渲染web网页。服务可能用异步、基于消息的通信。这些会在后面的文章讲到。

一些REST API可以直接暴露给司机和乘客用的移动APP。但是,应用不能直接访问后台服务。API Gateway作为中介可以去帮助交流。它负责负载均衡、缓存、访问控制、API计量和监控。

微服务对应3D立方体的Y轴,是《可扩展性的艺术》中的3D模型。X轴包括在一个负载均衡器后面的多个相同的应用副本,Z轴是缩放(或数据分区),其中的对于属性的请求(一行主键或者客户的标示)将路由到特定服务器。

这是Trip服务的AWS部署方式。由多个不同的服务实例组成。每个服务实例都是一个Docker容器。

微服务也显著影响了应用和服务器之间的关系。而不是和其他服务共享一个服务器,每个服务都有自己的数据库。换个角度说,这个方法与企业级数据模型不一样,可能会有数据的重复。但是如果你想用到微服务的优势,那么每个服务有自己的服务器是必要的。优势就是如果对于附近潜在乘客的司机就需要使用高效查询的数据库。

表面上,微服务很像SOA。通过这两种方法,架构包含一组服务。然而,SOA是已经被商业化提供服务的并且有ESB(Enterprise Service Bus)。基于微服务的应用支持更简单,轻量的协议比如REST而不是Web Service。并且非常避免使用ESB,而是在微服务中实现ESB类似的功能。微服务架构也拒绝SOA其他部分,比如规范模式的概念。

微服务的优势

  1. 解决复杂性问题。分解了一个怪物成为一组服务,功能不会受影响,但应用已经被分解成可管理的服务。每个服务都以RPC或者消息驱动的API来定义明确的边界。微服务也强制使用模块化,通常在单体应用代码中比较难以实现。因此,单个服务开发要快的多,易于理解和维护。
  2. 使每个服务由专注于该服务的团队独立开发。开发则可以随意选择技术和框架,只要符合API。创建新服务就可以使用新的技术框架了。
  3. 每个微服务都能独立部署。由于每个服务相对独立并且比较小,修改测试部署都是非常方便的,同时便于持续集成,使持续部署成为可能。
  4. 微服务架构使每个服务都可以独立调整。你可以为每个服务部署满足它的需求的实例。此外,你可以使用最匹配服务需求的硬件。比如,你可以在EC2上选择CPU密集型处理图像,内存优化型上部署内存数据库服务。

微服务的缺点

就像Fred Brooks在30年前写到,没有银弹。像其他技术一样,微服务架构也有缺点。

  1. 一个就是它的名字,Microservice过于强调服务规模。实际上,一些开发者主张构建极细粒度的10-100LOC服务。虽然小服务是最好的,但是这只是手段而不是微服务的目标。目标是充分分解应用,以便敏捷应用程序的开发和部署
  2. 分布式的复杂性。开发人员需要选择和实现基于消息或者RPC的内部交流机制。更有甚者,需要些代码去处理请求目标慢或者不可用的错误。虽然这些都不难,但是它比通过语言级别的方法/过程调用要复杂的多。
  3. 分区数据库架构。更新多个业务实体的业务交易是相当普遍的。因为有单体数据库,所以在单体应用程序中微不足道。但是,在基于微服务的应用中,你需要更新不同服务的多个数据库。用分布式事务通常不是一个选择,不仅是因为CAP定理。这根本不被现在很多NOSQL数据库和邮件代理支持。你最后不得不用基于一致性(注:放弃一致性,保证可用性和分区容错性。由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。可用性是数据库的容灾,NOSQL有支持,如MongoDB的Replica Sets,需要自行配置)的方法,这对开发者来说更具有挑战性。
  4. 测试微服务应用更加复杂。例如使用一个现代框架就像Spring Boot,写一个启动代替应用的REST API测试是简单的。相反,一个类似的测试类需要启动这个服务依赖的其他服务(或者配置一个虚拟的)。
  5. 跨多个服务的修改更复杂。例如,让我们想象你在实现一个需要改变服务A、B、C的故事卡片,A依赖B,B依赖C。在单体应用你可以简单修改对应模块,并与其他集成。相反,在微服务架构,你需要很小心计划和协调每个服务的更改。比如你可能需要更改C,C被B使用,最后服务与A。幸运的是,很多修改通常只影响一个服务,需要协调多个服务的比较少。
  6. 部署更复杂。单体应用在相同的服务和负载均衡器上部署是很简单的。每个应用实例都配置有基础架构(数据库和消息代理)的访问入口(主机和端口)。相反,微服务通常包括很多服务。比如,Hailo有160个不同的服务,Adrian Cockcroft说Netflix有超过600个。每个服务端都有很多运行时实例。很多可移动组件需要被配置,部署,扩展和监控。另外,你需要实现一个服务发现机制(稍后讨论)使服务可以发现任何其需要通信的其他服务的位置(主机和端口)。传统的基于故障单子和手动操作的方式无法扩展到这种复杂程度。所以,成功部署一个微服务应用程序需要更高水平人员实现的的部署方法和自动化。

自动化的一种方式是用PAAS比如Cloud Foundry。PAAS给开发者提供一个轻松部署和管理其微服务的方法。它使他们免于采购和配置IT资源。与此同时,配置PAAS的系统和网络人员可以确保他们用的是最佳实践和公司政策。另一个方法是开发自己的PAAS。一个典型的起点是使用集群方案,例如Kubernetes,与Docker结合。在稍后的系列中我们将介绍基于软件的应用交付方式,比如在微服务层面轻松处理缓存、权限控制、API计量和监控的的nginx。

总结

构建复杂应用本质上是困难的。一个单体应用仅仅适用于简单、轻量的程序。你将沦陷到痛苦的世界如果你将它用于复杂的应用。微服务架构是复杂,进化应用的更好的选择,尽管有缺点和实现难度。

Comments