我咨询了十几个微服务项目。有些人表示,微服务真棒(这是未来!),而有些人很沮丧(谁发明了这个废物?)
所以,不要一味接受别人喜好与否的言论,最重要的是亲自尝试,而不是只研究方法。不论你成功,还是失败。
以下是我的一些个人经验,看看 传统整体式架构 和 微服务 如何取得他们的一席之地。
为正确的工作选择正确的工具
我的团队建立了 “新闻阅读器应用” 它的功能为:处理文本,提取内容,分类,提供API,显示管理面板和管理用户。
- Scrapy(Python 2)是网络搜索领域的领导者。所以我们创建了一个抓取网址的微服务。(如果你有兴趣,这里有更多信息-15MB Docker镜像,包括Tor,Privoxy和一个进程管理器。)
- Newspaper(python 3)是最好的开源文章提取库之一。所以我们创建了一个微服务,在给定输入URL的情况下,返回提取的内容。
- R 有一些很好的分类库。一位熟悉R的同事使用 R 的 REST API 创建了整合分类文章的服务。
- ActiveAdmin 是最好和最简单的管理面板界面之一。很长一段时间以来,我们一直在利用它来管理视图,我们在这里折腾了好几天。
- 最后,对于API网关,我们将Node.js与 PassportJS(用于多个身份验证)和 ElasticSearch 结合使用。
在重写之前,我们的旧应用程序是一个使用 Rails 开发的传统整体式架构。它试图重塑之前提到的一切。您可以想象代码中关于质量,进度和时效的权衡是多么困难。
糟糕的传统整体式架构试图重塑世界。他们认为代码和设计模式是一切的解决方案。努力构建可重用的组件,库,并成为一个平台。但事实上这些目标很难取得成功。
重点#1:微服务是一种商业解决方案,而不仅仅是一种技术解决方案。它们使开发人员不必浪费时间重新解决已经解决的技术问题。
我不关心你是否称他们为“服务”,“面向服务的架构”或“微服务”。一旦我们遇到流行语,“单服务与微服务”就归结为“1服务与N服务”。
对于我们的应用程序,“N服务”原来是我们想要的技术栈。
CRUD应用程序
一些企业项目可以简单地归类为 CRUD(创建 - 读取 - 更新 - 删除)应用程序。这是一个永无止境的形式,包含着数据关系,转换流程,以及非常复杂的“业务逻辑”。范围很大,但受众很少。
对这些程序而言,没有人关心用户体验,而且通常使用快速和简陋的视图来完成工作。
我们就有一个这样的企业转型项目,这个古老的庞然大物是基于数据库视图的整合。事实上,它的设计非常优秀,只需要几个人来维护,包括丑陋的用户界面。
新的后端服务主要是用Java编写的,所以很难开发,集成,共享和维护其兼容性。而新的前端服务已经进入了不断变化的,单页应用程序世界。
在早年间,开发人员工具生态系统成熟之前,部署需要巨大的,基础设施自动化设置。那时,每一份合约变更都需要手动协调和更新。这与之前的情况正好相反 —— 微服务的成果/产出/开销比旧的传统整体式架构更大。
重点#2:注意! 将微服务的分割代码层错误的处理为 docker 化的容器,这可能会导致“重大破坏”。
驯服巨大的依赖关系树
我们进行了另一个遗留的企业应用程序转换,它包含了很多功能,如产品抓取和并行聚合。这是一个复杂的,难以解决的庞然大物。
当我们在单个应用程序内部执行多个正交业务功能时,会导致一个巨大的编译时间依赖关系树,其中包含大量的库和框架。因此,运行时间占用空间,生命周期和构建时间也很长。这导致了真正的问题:开发人员无法快速迭代,导致功能的发布时间受到了影响。
编写简单功能所需的时间:几天。
升级库(guice)版本的时间:1周。
升级框架(Spring)版本所需的时间:永远。
一些琐碎的事情很可能会破坏掉整个时间安排。即使是一个很小的重构也会花费极长时间。事实证明,传统整体式框架的确会影响进度。
我们尝试为该项目划分为一些功能边界,积极确保不共享库,从而避免依赖树的瓶颈。
例如,我们使用一个现代客户端库来发布消息,通过PubSub发布微服务。但传统整体式框架的大依赖树不允许我们使用相同的库。所以我们使用了一个不同的基于HTTP的PubSub客户端。
微服务转型者经常犯共享太多库这一经典错误,并为此重新创建相同的编译时依赖树(“分布式整体”)。
但是通过避免共享功能,我们可以使用不同的库来完成相同的任务,而无需操作所有的服务。
其中一项服务需要很多并发性(每个请求约需要1k次查询)。它最初利用RxJava。但它可以在任何一天用Golang的相同的API合约重写,而没有人会关心依赖关系树。
重点#3:使用微服务,您不会再听到“大改”或“遗留系统”这个词,因为没有任何的大系统。
可扩展性的神话
我的团队开发了一个代码评估应用。它包含90%的CRUD,用户界面和报告,以及10%
的对十几种语言的复杂的代码评估。
在我们着手之前,它是一系列微服务 - 针对每种语言的一种,监听不同的消息队列。它有一个单独的服务前端,管理面板即服务等等。这样做的初始目的?可扩展性。
我们处理掉了所有东西,并建立了一个更好的整体式框架。它完全是作为单个Rails应用程序完成的 - 用户界面,管理员,后端和候选界面。
代码评估部分作为后台作业(ActiveJob)运行。我们通过简单的,无状态的一次性Docker容器来解决这个问题。评估代码的核心合同从REST / JSON更改为file / stdin / stdout。它比旧系统精简得多,因为我们只需要增加后台工作人员来处理更多的代码评估。
外部看起来像一个复杂的应用程序 - 支持8种主要的编程语言和智能评估 —— 在内部却非常简单。
重点#4:有时并不需要微服务来运行服务或工作者的多个实例。良好的整体式架构同样可以针对某些类别的问题进行扩展。
创建可缩放的整体和不可缩放的微服务。这一切都取决于你如何运用他们的特性。
产品化的微服务
我工作过的最满意的微服务项目之一就是将微服务作为产品。我们的客户非常聪明,拥有自己的技术人员,并利用微服务来作为其商业工具。
他们将每项服务建模为一种产品,然后向不同的客户发布多种产品。他们以各自可以利用其他API的方式排列产品发布。反过来,他们创造了一个伟大的生态系统,这帮助他们成为垂直市场的领导者。
现如今,平均每个企业至少使用十多种软件产品和集成,平均每个云服务使用者都使用多个云产品。我现在也看到,即使是非技术人员也使用微型产品和微型应用程序。例如,一些面试工具,用于度假跟踪的小工具,工资单小程序等等。人们正在拥抱更小,更专业化的工具来正确的完成工作。
重点#5:我们正在进入微型应用程序和微服务的时代。因此,最好学会做得更好。
有一种对机器学习即将替代程序员的工作的恐惧持续不断。现如今大多数编程工作正在逐步被开发的API接口直接替代。
分布式事务
反对使用微服务的最常见论点之一是与分布式事务相关的风险。
您是否遇到过调用外部支付网关系统时,回调失败?您是否有多种登录机制(如电子邮件或OAuth)?您是否调用没有回滚选项的第三方SaaS产品?您是否利用了不尊重您的交易边界的Cloud API和存储桶?您是否有在同一个服务中跨多个请求生命周期的工作流?
然后,无论您是否喜欢,事实上您都已经以某种方式分发了事务。
通过一个系统和一个请求,可以代表或控制业务问题的整个交易状态的整个想法,这的确是一种幻想。如果您可以在没有分布式锁定和交易的情况下对外部集成进行建模,那么您也可以对内部模型进行建模。
重点#6:对于整体式框架而言,分布式锁和合约,同样不够自由。
工具与人
是的,更多的服务意味着更多的工具。这包括持续集成和持续部署(CI / CD),基础架构自动化,开发人员工具,设计良好API,合约共享,文档,客户端智能和库,流程,测试以及其他许多工具。
你一定要使用上微服务。
如果一个团队不具备工程稳健性和成熟度从而轻松运行少数服务(设计模式,CI,CD,集成,测试等),那么切换到其中的许多服务将是一场灾难。
很多来自传统整体式架构的人士都会采用Big Design Up Front。微服务是最好的,当他们无可避免。只要扔掉所有的样板,以毫无意义的方式实施API,而不是投入时间进行高质量的单元/合约测试。与工具VS人一样 —— 微服务需要思维方式的改变,以及大量的放弃。
好在这些工具的很多问题都有很好的工程解决方案。Docker,Kubernetes,REST,Swagger,Falcor,gRPC,CI / CD管道工具,PaaS,Cloud等。围绕微服务的生态系统已经十分成熟,且一直在完善。
但是是微服务不能像框架或工具一样轻松掌握。他们需要有经验的整体方法。需要优秀的人员,他们不仅是优秀的编程人员,而且还是全面的工程师,他们在从开发到测试到部署的整个软件开发生命周期中都要拥有坚实的基础。
有大型企业每个集成需要几个月的时间。然后有像Google,Facebook和Netflix这样的现代化公司以更高的质量和速度运行数千种集成服务。不同之处不仅仅在于工具 —— 同样涉及人员和他们的工程思路。
重点#7:微服务是多种工程实践的结晶。他们有一个陡峭的学习曲线。
结论
微服务方法只是解决方案工具包中的另一个工具。而一个工具仅仅只是一个工具。它可能最终成为一个强大的商业产物,或者是一个非生产性的开发者瓶颈。对我们而言是好还是坏,这只取决于我们如何使用这一工具。
系统架构微服务系统架构微服务