microservices/1-introduction-to-microservices.md
2017-08-20 20:14:23 +08:00

40 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1、微服务简介
目前微服务受到很多关注:文章、博客、社交媒体上的讨论和会议演讲。他们正在迅速走向[加德纳技术成熟度曲线Gartner Hype cycle](http://www.gartner.com/technology/research/methodologies/hype-cycle.jsp)的高峰。与此同时也有持怀疑态度的软件社区人员认为微服务没什么新鲜可言。反对者声称它的思想只是面向服务架构SOA的重塑。然而无论是炒作还是怀疑不可否认微服务架构模式具有非常明显的优势——特别是在实施敏捷开发和复杂的企业应用交付方面。
本章节是七章之中介绍关于的设计、构建和部署微服务方面的内容。您将了解微服务的由来和与传统[单体应用模式](http://microservices.io/patterns/monolithic.html)的比较。这本电子书描述了许多关于微服务架构方面的内容。无论是对您的项目的意义,或者是如何去应用它,您都将了解到微服务架构模式的优点和缺点。
我们先来看看为什么要考虑使用微服务。
## 1.1、构建单体应用
我们想一下,您开始制作一个新的打车应用,打算与 Uber 和 Hailo 竞争。经过初步交流与需求收集,您将手动或者使用类似 Rails、Spring Boot、Play或者Maven等平台来生成一个新项目。
这个新应用是一个模块化的六边形架构,如图 1-1 所示:
![图 1-1、一个简单的打车应用](https://github.com/oopsguy/microservices-from-design-to-deployment-chinese/blob/master/resources/1-1.png)
应用程序的核心是由模块实现的业务逻辑,它定义了服务、领域对象和事件。围绕核心的是与外部世界接口对接的适配器。适配器示例包括了数据库访问组件、生产和消费消息的消息组件和 web 组件,它们暴露了 API 或者实现了一个 UI。
尽管有一个逻辑模块化的架构,但应用程序被作为一个整体进行打包和部署。实际格式取决于应用程序的语言和框架。例如,许多 Java 应用程序被打包成 WAR 文件并部署在如 Tomcat 或者 Jetty 之类的应用服务器上。其他 Java 应用程序是打包成自包含self-contained的可执行 JAR。类似地Rails 和 Node.js 应用程序被打包为目录层次结构。
以这种风格编写的应用是很常见的。他们很容易开发,因为我们的 IDE 和其他工具专注于构建单个应用程序。这些应用程序也很容易测试。您可以通过简单地启动并使用如 Selenium 测试包来测试 UI 以轻松地实现端到端end-to-end测试。单体应用同样易于部署。你只需拷贝打包好的应用程序到服务器。您还可以通过运行多个副本和结合负载均衡器来扩展应用。在项目的早期阶段它运作良好。
## 走向单体地狱
不幸的是,这种简单的方法有很大的局限性。成功的应用有一个趋势,随着时间推移而变得越来越臃肿。在每个冲刺时期,您的开发团队实现了更多的用户需求,这意味着添加了许多行代码。几年之后,您的小而简单的应用将会逐渐成长为[庞然大物似的单体](http://microservices.io/patterns/monolithic.html)。为了给出一个极端的示例我最近和一位开发者做了交谈他正在编写一个工具用于从他们的数百万行代码lines of codeLOC应用中分析数千个 JAR 之间的依赖。我相信这是大量开发者在多年齐心协力下创造了这样的野兽。
一旦您的应用程序成为了一个庞大、复杂的单体,您的开发组织可能陷入了一个令人痛苦的世界。敏捷开发和交付的任何一次尝试都将原地徘徊。一个主要问题是应用程序实在是非常复杂。对于任何一个开发人员来说,这是在太大了,这是可以理解的。最终,正确地修复 bug 和实现新功能变得非常困难且耗时。此外,这个趋势就像是往下的螺旋。如果基本代码难以理解,那么改变将不会变得正确。您最终得到的是一个巨大且不可思议的[大泥球](http://www.laputan.org/mud/)。
应用程序的规模也将减缓发展。应用程序越大,启动的时间越长。我[调查](https://plainoldobjects.com/2015/05/13/monstrous-monoliths-how-bad-can-it-get/)过开发者们的单体应用的大小和性能,一些报告的启动时间为 12 分钟。我也听说过应用程序启动需要 40 分钟以上的怪事。如果开发人员经常要重启应用服务器,那么很大一部分时间都是在等待中度过,他们的生产力将受到限制。
另一个大问题是复杂的单体应用本身就是持续部署的障碍。如今SaaS 应用发展到了每天可将变更推送到生产中多次。这对于复杂的单体非常困难,因为您必须重新部署整个应用程序才能更新其中任何一部分。这对我之前提到的漫长的启动时间也不会有什么帮助。此外,因为变化的影响通常不是很清楚,您很可能需要做大量的手工测试。因此,持续部署是不可能做到的。
当不同模块存在资源需求冲突时,单体应用也可能难以扩展。例如,一个模块可能会执行 CPU 密集型图像处理逻辑,理想情况下是部署在 Amazon EC2 Compute Optimized 实例中。另一个模块可能是内存数据库,最适合 EC2 Memory-optimized 实例。然而,因为这些模块被部署在一起,您必须在硬件选择上做出妥协。
单体应用的另一个问题是可靠性。因为所有模块运行在同一进程。任何模块的一个 bug比如内存泄漏可能会拖垮整个进程。此外由于应用程序的所有的实例都是相同的该错误将影响到整个应用的可用性。
最后但并非是最不重要的,单体应用使得采用新的框架和语言变得非常困难。例如,我们假设您有 200 万行代码使用了 XYZ 框架编写。使用较新的 ABC 框架来重写整个应用,这将是非常昂贵的(在时间和成本方面),即使那个框架非常好。因此,这对于采用新技术是一个非常大的障碍。您在项目开始时无论选择何种新技术都将会感到困扰。
总结一下:您有一个成功的关键业务应用程序,它已经发展成为一个只有少数开发人员(如果有的话)能够理解的巨大单体。它使用了过时、非生产性技术编写的,这使得招聘优秀开发人员变得困难。应用程序难以扩展,不可靠。因此敏捷开发和应用交付是不可能的。
那么您能做些什么呢?
**待续……**