前言

最近几年微服务很火,大家都在建设微服务,仿佛不谈点微服务相关的技术,都显得不是那么主流了。

近几年见识到身边朋友的很多公司和团队都在尝试进行微服务的改变,但很多团队并没有实际微服务踩坑经验,很多团队甚至强行为了微服务而去微服务,最终写成一个大型的分布式单体应用,就是改造后的系统既没有微服务的快速扩容,灵活发布的特性,也让原本的单体应用失去了方便开发,部署容易的特性(项目拆为多份,开发部署复杂度都提高了),不得不说是得不偿失。

作者亲身经历和参与几个大型项目微服务的改造和建设。所以想作为实践者跟大家分享关于微服务的实际经验,帮助大家了解微服务的优缺点和一些开发原则,从而可以结合自身业务做出更加合适的选择。

(PS:因为市面上存在太多对如何使用微服务框架工具的教程,所以本篇只是一篇关于微服务的总体概述性文章,不涉及各种微服务框架的安装和使用教程,我们只谈论微服务本身的设计模式的优缺点和适合应用的场景)

什么是微服务?为什么要使用微服务?

什么是微服务?(熟悉的同学可以直接跳过)

通常而言,微服务架构是一种架构模式或者说是一种架构风格

它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值

服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。

简单举例:看军事新闻的同学应该都知道,一艘航空母舰作战能力虽然很强,但是弱点太明显,就是防御能力太差,单艘的航空母舰很少单独行动,通常航空母舰战斗群才是主要军事力量,你可以把单艘航母理解为的单体应用(防御差,机动性不好),把航母战斗群(调度复杂,维护费用高)理解为微服务。

微服务架构和单体架构的区别

A. 单体架构

通俗地讲,“单体应用(monolith application)”就是将应用程序的所有功能都打包成一个独立的单元,可以是JAR、EXE、BIN或其它归档格式。


单体应用有如下优点:

1、开发简单直接,集中式管理, 基本不会重复开发

2、功能都在本地,没有分布式的管理开销和调用开销

它的缺点也非常明显,特别对于互联网公司来说:

1、开发效率低:所有的开发在一个项目改代码,递交代码相互等待,代码冲突不断

2、代码维护难:代码功能耦合在一起,新人不知道何从下手

3、部署不灵活:构建时间长,任何小修改必须重新构建整个项目,这个过程往往很长

4、稳定性不高:一个微不足道的小问题,可以导致整个应用挂掉

5、扩展性不够:无法满足高并发情况下的业务需求

B、微服务架构

随着业务需求的快速发展变化,敏捷性、灵活性和可扩展性需求不断增长,迫切需要一种更加快速高效的软件交付方式。微服务就是一种可以满足这种需求的软件架构风格。单体应用被分解成多个更小的服务,每个服务有自己的归档文件,单独部署,然后共同组成一个应用程序。这里的“微”不是针对代码行数而言,而是说服务的范围限定到单个功能。


微服务有如下优点:

1、微服务是松藕合的,无论是在开发阶段或部署阶段都是独立的。

2、能够快速响应, 局部修改容易, 一个服务出现问题不会影响整个应用。

3、易于和第三方应用系统集成, 支持使用不同的语言开发, 允许你利用融合最新技术。

4、每个微服务都很小,足够内聚,足够小,代码容易理解。团队能够更关注自己的工作成果, 聚焦指定的业务功能或业务需求。

5、开发简单、开发效率提高,一个服务可能就是专一的只干一件事, 能够被小团队单独开发,这个小团队可以是 2 到 5 人的开发人员组成。

同样的, 也存在如下缺点:

6、微服务架构带来过多的运维操作, 可能需要团队具备一定的 DevOps 技巧.

7、分布式系统可能复杂难以管理。因为分布部署跟踪问题难。当服务数量增加,管理复杂性增加。

微服务架构的主要特点

微服务架构是一种松耦合的、有一定的有界上下文的面向服务架构。也就是说,如果遇到一个功能变更, 但其要求每个服务都要同时修改,那么它们就不能称之为微服务,因为它们紧耦合在一起;如果你需要掌握一个服务的上下文场景使用条件,那么它就是一个有上下文边界的服务,这个定义一般来自DDD(领域驱动设计)。

它的主要特点是组件化、松耦合、自治、去中心化,体现在以下几个方面:

A. 细粒度的服务分解

服务粒度要小,而每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情。

B. 独立部署运行和扩展

每个服务能够独立被部署并运行在一个进程内。这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。

C. 独立开发和演化

技术选型灵活,不受遗留系统技术约束。合适的业务问题选择合适的技术可以独立演化。服务与服务之间采取与语言无关的API进行集成。相对单体架构,微服务架构是更面向业务创新的一种架构模式。

D. 独立团队和自治

团队对服务的整个生命周期负责,工作在独立的上下文中,自己决策自己治理,而不需要统一的指挥中心。团队和团队之间通过松散的社区部落进行衔接。

通过解耦我们所做的事情,分而治之以减少不必要的损耗,使得整个复杂的系统和组织能够快速的应对变化。

使用微服务应该遵循哪些原则?

古人云:兵马未动,粮草先行。建设微服务是需要建立长远规划,不是像写CMS那样建好数据库表,然后就开始干活,这样十有八九是会失败的。我们要进行微服务改造前,架构师要提前做好规划,我们把这里分为三步,前期阶段,设计阶段,技术阶段。

前期阶段,大致要做好如下事情:

  • 和多方充分沟通,确保能符合客户和组织的需求,并且得到认同
  • 和团队沟通,让队友(开发/测试/运维)理解,并且积极投入
  • 和业务部门沟通,指定版本计划和上线时间

设计阶段,参考 Sam Newman 的著作《微服务设计》,单微服务必须要满足以下的条件,才符合微服务的基本要求:

  • 标准的 REST 风格接口(基于 HTTP 和 JSON 格式)
  • 独立部署,避免共享数据库(避免因为数据库而影响整个分布式系统)
  • 业务上的高内聚,减少依赖(从设计上要避免服务过大或者太小)

庞大的分布式系统,需要强大基础设施来支撑,微服务涉及哪些基础设施?

  • CI/CD和自动化(分布式系统几乎不可能通过人工手动发布)
  • 虚拟化技术(要保证微服务运行环境隔离,目前行业主流的是使用 Docker 容器)
  • 日志聚合,全链路监控(高度可观察和分析诊断问题)

需要考虑的问题

1、单个微服务代码量小,易修改和维护。但是,系统复杂度的总量是不变的,每个服务代码少了,但服务的个数肯定就多了。就跟拼图游戏一样,切的越碎,越难拼出整幅图。一个系统被拆分成零碎的微服务,最后要集成为一个完整的系统,其复杂度肯定比大块的功能集成要高很多。

2、单个微服务数据独立,可独立部署和运行。虽然微服务本身是可以独立部署和运行的,但仍然避免不了业务上的你来我往,这就涉及到要对外通信,当微服务的数量达到一定量级的时候,如何提供一个高效的集群通信机制成为一个问题

3、单个微服务拥有自己的进程,进程本身就可以动态的启停,为无缝升级打好了基础,但谁来启动和停止进程,什么时机,选择在哪台设备上做这件事情才是无缝升级的关键。这个能力并不是微服务本身提供的,而是需要背后强大的版本管理和部署能力。

4、多个相同的微服务可以做负载均衡,提高性能和可靠性。正是因为相同微服务可以有多个不同实例,让服务按需动态伸缩成为可能,在高峰期可以启动更多的相同的微服务实例为更多用户服务,以此提高响应速度。同时这种机制也提供了高可靠性,在某个微服务故障后,其他相同的微服务可以接替其工作,对外表现为某个设备故障后业务不中断。同样的道理,微服务本身是不会去关心系统负载的,那么什么时候应该启动更多的微服务,多个微服务的流量应该如何调度和分发,这背后也有一套复杂的负载监控和均衡的系统在起作用。

5、微服务可以独立部署和对外提供服务,微服务的业务上线和下线是动态的,当一个新的微服务上线时,用户是如何访问到这种新的服务?这就需要有一个统一的入口,新的服务可以动态的注册到这个入口上,用户每次访问时可以从这个入口拿到系统所有服务的访问地址。这个统一的系统入口并不是微服务本身的一部分,所以这种能力需要系统单独提供。

6、还有一些企业级关注的系统问题,比如,安全策略如何集中管理?系统故障如何快速审计和跟踪到具体服务?整个系统状态如何监控?服务之间的依赖关系如何管理?等等这些问题都不是单个微服务考虑的范畴,而需要有一个系统性的考虑和设计,让每个微服务都能够按照系统性的要求和约束提供对应的安全性,可靠性,可维护性的能力。

选择微服务框架的关注点

1、服务注册、发现、负载均衡和健康检查:假定采用进程内LB方案,那么服务自注册一般统一做在服务器端框架中,健康检查逻辑由具体业务服务定制,框架层提供调用健康检查逻辑的机制,服务发现和负载均衡则集成在服务客户端框架中。

2、监控日志:框架一方面要记录重要的框架层日志、metrics和调用链数据,还要将日志、metrics等接口暴露出来,让业务层能根据需要记录业务日志数据。在运行环境中,所有日志数据一般集中落地到企业后台日志系统,做进一步分析和处理。

3、REST/RPC和序列化:框架层要支持将业务逻辑以HTTP/REST或者RPC方式暴露出来,HTTP/REST是当前主流API暴露方式,在性能要求高的场合则可采用Binary/RPC方式。针对当前多样化的设备类型(浏览器、普通PC、无线设备等),框架层要支持可定制的序列化机制,例如,对浏览器,框架支持输出Ajax友好的JSON消息格式,而对内部服务及应用程序,框架支持输出性能高的Binary消息格式。

4、配置:除了支持普通配置文件方式的配置,框架层还可集成动态运行时配置,能够在运行时针对不同环境动态调整服务的参数和配置。

5、限流和容错:框架集成限流容错组件,能够在运行时自动限流和容错,保护服务,如果进一步和动态配置相结合,还可以实现动态限流和熔断。

6、管理接口:框架集成管理接口,一方面可以在线查看框架和服务内部状态,同时还可以动态调整内部状态,对调试、监控和管理能提供快速反馈。Spring Boot微框架的Actuator模块就是一个强大的管理接口。

7、统一错误处理:对于框架层和服务的内部异常,如果框架层能够统一处理并记录日志,对服务监控和快速问题定位有很大帮助。

8、安全:安全和访问控制逻辑可以在框架层统一进行封装,可做成插件形式,具体业务服务根据需要加载相关安全插件。

9、文档自动生成:文档的书写和同步一直是一个痛点,框架层如果能支持文档的自动生成和同步,会给使用API的开发和测试人员带来极大便利。Swagger是一种流行Restful API的文档方案。

因此,一个完整的微服务系统,它最少要包含以下功能:

1、日志和审计,主要是日志的汇总,分类和查询

2、监控和告警,主要是监控每个服务的状态,必要时产生告警

3、消息总线,轻量级的MQ或HTTP

4、注册发现

5、负载均衡

6、部署和升级

7、事件调度机制

以下功能不是最小集的一部分,但也应该在选择时进行考虑:

1、认证和鉴权

2、多语言支持, 是否支持多种编程语言

3、统一服务构建和打包

4、统一服务测试

5、统一配置文件管理

6、服务依赖关系管理

7、问题跟踪调试框架

8、灰度发布

9、蓝绿部署

10、资源管理,如:底层的容器, 虚拟机, 物理机和网络管理

开发方式影响

随着持续交付概念推广以及容器概念的普及,微服务将这两种理念和技术结合起来,形成新的微服务+API + 容器平台的开发模式,提出了容器化微服务的持续交付概念。

下图为传统单体应用的DevOps开发队伍方式:

        这种整体型架构要求产品队伍横跨产品管理 Dev开发 QA DBA 以及系统运营管理,而微服务架构引入以后,如下图:


        微服务促进了DevOps方式的重组,将一个大臃肿的整体产品开发队伍切分为根据不同微服务的划分的产品队伍,以及一个大的整体的平台队伍负责运营管理,两者之间通过API交互,做到了松耦合隔绝。

小结

微服务的实施是有一定的先决条件:基础的运维能力(如监控、快速配置、快速部署)需提前构建,否则就会陷入较被动的局面。

推荐采用CI/CD改进基础设施及运维的实践,通过自动化运维使得可以快速安全的响应和处理微服务对服务部署的要求,通过容器技术保证服务环境之间拥有更高的一致性,降低“在我的环境工作,而你的环境不工作”的可能,也是为后续的发布策略和运维提供更好的支撑。

想要更好的实施微服务, 首先需要考虑构建团队DevOps能力,这是保证微服务架构在持续交付和应对复杂运维问题的动力之源;

其次保持服务持续演进,使之能够快速、低成本地被拆分和合并,以快速响应业务的变化;同时要保持团队和架构对齐。微服务看似是技术层面的变革,但它对团队结构和组织文化有很强的要求和影响。识别和构建匹配架构的团队是解决问题的另一大支柱。

最后,打造持续改进的组织文化是实施微服务的关键基石。只有持续改进,持续学习和反馈,持续打造这样一个文化氛围和团队,微服务架构才能持续发展下去,保持新鲜的生命力,从而实现我们的初衷。

本篇参考文献:
[1]:微服务概念及优缺点 https://blog.csdn.net/kunyus/article/details/90670710
[2]: 什么是微服务 https://www.cnblogs.com/xiao2shiqi/p/11298663.html
[3]: 什么是微服务架构 https://www.zhihu.com/question/65502802

受益的朋友记得三连支持小菌!

文章持续更新,可以微信搜一搜「 猿人菌 」第一时间阅读,思维导图,大数据书籍,大数据高频面试题,海量一线大厂面经…期待您的关注!

这可能是你见过最硬核的微服务入门指南!相关推荐

  1. 如何度过人生艰难:魔都28岁硬核知识型美少女自救指南

    Hello大家好,我是柱柱哥,以及一个正在接受Rchop方案化疗的滤泡型淋巴瘤4期病人. 其实很不想提笔写自己的事情,好像强迫别人了解接受自己一样.可是这两天一直刷到朋友圈的鸡汤文,"扛过人 ...

  2. 程序员需要了解的硬核知识之操作系统入门

    对于程序员来说,最莫大的荣耀莫过于自己的软件被大多数人使用了吧. 历史文章请戳 程序员需要了解的硬核知识之内存 程序员需要了解的硬核知识之CPU 程序员需要了解的硬核知识之二进制 程序员需要了解的硬核 ...

  3. 你从未见过的,最全微服务架构实战详解,干货满满

    前言 随着各行各业的快速发展,业务规模的不断扩大,不可避免地造成原有架构不能够适应快速的增长和变化.这时,微服务就进入大家的视野. 但微服务并不是一个全新的架构,更不是一个包治百病的架构.它同样也会给 ...

  4. 你从未见过的,最全微服务架构实战详解,干货满满!

    前言 随着各行各业的快速发展,业务规模的不断扩大,不可避免地造成原有架构不能够适应快速的增长和变化.这时,微服务就进入大家的视野. 但微服务并不是一个全新的架构,更不是一个包治百病的架构.它同样也会给 ...

  5. 航空母舰与钢铁侠助阵,这么硬核的智能锁你见过么

    当威风凛凛的航空母舰映入眼帘:当帅气逼人的钢铁侠亮相现场,你肯定也会和我一样发出由衷的惊叹声. 不过大家不要误会,这可不是漫威又一部电影大片的拍摄现场,而是鹿客智能锁举办的一场新品发布会. 5月21日 ...

  6. 【独立游戏】黎明之刃——3D硬核ARPG游戏

    - 项目概念:<黎明之刃>深受主机上<鬼泣>.<黑暗之魂>等硬核动作游戏的启发,是Sunset Game 团队成员合力创作出的拥有全新想法的一款动作游戏 - 我们生 ...

  7. 1个人,耗时2年半,这款大型仙侠3D硬核ARPG是怎么做出来的?

    导语 如何用游戏特有的交互以及规则制定,表现武侠.江湖的内核?对于<剑魄>制作人离忧先生在第7期GWB腾讯游戏品鉴会上提出的这个问题,腾讯游戏学院专家给出了自己的看法. <剑魄> ...

  8. Linux Kernel TCP/IP Stack|Linux网络硬核系列

    大家好,我是Alex,今天给大家介绍Linux网络技术中最核心的部分--TCP/IP协议栈 . 我们先看一下抽象的网络协议栈模型 TCP/IP四层(参考)模型 再按分层思想看Linux内核协议栈实现框 ...

  9. Redis 多线程网络模型全面揭秘|网络硬核系列

    目录 导言 Redis 有多快? Redis 为什么快? Redis 为何选择单线程? 避免过多的上下文切换开销 避免同步机制的开销 简单可维护 Redis 真的是单线程? 单线程事件循环 多线程异步 ...

最新文章

  1. 13.组合查询--SQL
  2. 跳至下一个断点_基金经理:DeFi将推动以太坊在下一个上涨周期中涨至9000美元...
  3. Spring IDE 1.2.4发布
  4. 转:11个实用但你可能不知道的Python程序库
  5. 汇编语言-003(LAHF_SAHF 、XCHG、FLAGS、 OFFSET、ALIGN、PTR、LENGTHOF、SIZEOF)
  6. ubuntu使用git时,终端不显示git分支。
  7. Express框架中如何引用ejs模板引擎
  8. 12.go 源码文件
  9. python3 微博API code获取解决方案 长期保存access_token
  10. PDFCreator pdf制作软件+教程
  11. Excel基础(08)IF函数
  12. 计算机桌面图标乱了,如何解决电脑桌面图标乱跑的问题
  13. 【数仓】大数据领域建模综述-《大数据之路》读书笔记
  14. CF1143F/1142C U2
  15. linux卸载集群oracle,Oracle RAC集群卸载步骤
  16. Python编程基础 第七章 编程练习 用户从键盘上输入一个字符串,如果该字符串的内容不是有效的数值,则输出invalid;如果是有效的数值,再判断其是否是整数,如果是整数则输出yes,否则输出no。
  17. 一起来了解木马的七种分类
  18. Steam账号被盗后,账号找回,PUBG解封经验分享
  19. 安化云台山:中秋月圆夜,赏月正当时
  20. cydia java_Cydia for Android

热门文章

  1. 找圆算法((HoughCircles)总结与优化
  2. 剑指offer-二叉树(python)
  3. AAA云免费云主机推荐码
  4. datastage(IBM InfoSphere Information Server )日志的获取和分析
  5. C语言学习经典书籍推荐
  6. dataView及其用法
  7. 【python】简单使用selenium编写无界面谷歌浏览器的网页登录和签到功能
  8. linux查看计算机信息,Linux下查看计算机信息
  9. opera mini android apk,Download Opera Mini APK Android
  10. c 与java通信_javaSocket与C通信