微服务概述

前言

自从2015年的微服务元年开始, 微服务就已经成为了当前软件开发领域的热门话题. 越来越多的博客, 文章, 演讲都是围绕着微服务展开. 那微服务到底是什么东西, 和我们常见的架构, 以及我们现在开发的模式有什么异同点?

这系列文章, 我将尝试基于我了解到的知识, 以及阅读的文章来对微服务涉及到的知识做一个入门的介绍. 文章内容将会包含以下内容:

  • 微服务概述, 优点及缺点

  • 服务划分

  • 服务间通信方式

  • 事务处理

  • 服务间交互的挑战

  • CI\CD的挑战

  • 对外服务

希望通过阅读这系列文章, 各位能大致了解微服务架构, 并能在工作中运用相关的知识来设计服务.

monolithic服务

微服务相对应的是monolothic服务. 一般翻译为巨石服务, 或者单体服务. 在项目开始的时候, 往往都是先收集一波需求, 经过模块化的设计后, 套上一套现成的服务框架, 就开始编写服务了. 通常情况下, 服务的架构类似于下图:

image.png

这类架构被称作 modular hexogonal architecture, 其特点是:

  • 核心服务被拆成了多个模块

  • 包含了一系列的组件, 例如

    • 处理请求, 并返回相应的数据

    • 业务逻辑

    • 访问数据库组件

    • 应用集成逻辑, 用于发送消息等

  • 虽然经过了模块化设计, 但整个核心服务仍作为整体进行部署

  • 通过增加拷贝, 服务是可以平行扩容的

优点

  • 开发简单. 代码都在一个code base里, 获取到全部的代码就可以开始开发

  • 调用都在本地, 调用成本低廉

缺点

这种架构在业务初期能快速支持迭代开发, 而且得益于其整体部署的策略, 使得部署, 扩容都十分容易. 但, 随着业务的快速发展, 模块的规模不断扩大, 开发人员不断的增多, 弊病就展现出来了.

  1. 代码可读性降低. 随着功能不断迭代与开发, 代码的复杂性不断的增强, 使得新人接手代码的难度变得越来越大. 当新人加入后, 需要了解的系统模块往往会非常多且繁杂, 细节居多. 从而导致学习的难度大幅增加. 进而延缓了新人发挥战力的时间, 从而拖慢了整体开发及bug修复的时间.

  2. 资源竞争. 核心模块中, 不同模块对资源的需求是不同的. 有的可能更消耗内存, 有的则重度依赖I/O. 因为同时部署在一台机器上, 所以想要分离开是不可能的.

  3. 并行开发难度增大. 因为所有人都基于一个代码仓库进行开发. 在特性开发的过程中, 冲突的可能性会增大不少, 从而使得合并代码更为困难.

  4. 服务的可用性降低. 显而易见, 如果一个模块中出现了bug, 那整个服务都会处于不可用的状态.

  5. 技术栈切换成本高. 现在技术发展非常快, 新的框架, 工具层出不穷. 在服务迭代的过程中, 有可能某个工具或者框架非常合适某个模块. 但由于语言\框架等原因, 使得引入工作编的十分困难. 此外, 在跨团队的配合的场景下, 不同团队间使用的技术栈可能完全不同.

微服务

为了解决这类单体应用的弊病, 微服务就被提出来了. 微服务是一种架构模式, 其特点是:

  • 一组小的服务

    微服务是一组小的服务. 拆分的规则, 具体多小算作是微服务并没有特别限制. 一般来说, 一个开发者能阅读理解, 即可成为微服务.

  • 独立的进程

    每个服务都是一个独立的进程. 比如说docker容器中的一个容器, 或者一个tomcat的一个jar包等.

  • 轻量级的通信

    服务之间通过API或者消息机制来进行通信.

  • 基于业务拆分

    类似于模块化设计, 微服务也是根据业务的需求, 对单体服务进行拆分, 形成了多个小的服务. 单个微服务类似于前面提到的单体服务, 完整包含了业务逻辑, 暴露的API接口, 与外部交互的接口. 常见的类似于登录服务, 用户管理服务, 订单服务等.

  • 独立数据源

    每个微服务具有自己的数据源.

  • 独立部署

    每个服务之间是独立部署的. 单个服务可以有多个拷贝, 以提高服务的吞吐能力和性能.

  • 松耦合, 无集中化管理

    服务之间松耦合, 仅以API等方式进行交互. 不同服务可以采用完全不同的技术栈, 数据库等设施. 服务的负责团队具有很高的自主权.

  • SOA-like

    微服务的架构非常类似于传统的SOA. 都是以服务为核心进行构建. 相较于传统的SOA, 微服务更为落地及轻量, 例如使用了更为轻量级的协议(REST或者RPC), 抛弃了ESB而使用类似于ESB的实现等.

以上面的单体应用为例, 拆成相应的微服务之后, 整体架构会变成:

image.png

每个模块都相应的拆成了独立的服务. 服务与服务之间独立部署, 并提供相应的REST接口用于调用. 而原来的模块间调用就变成了服务间的调用.

每个服务代表了某块业务, 包含了该业务的所有处理逻辑. 根据每个业务的不同特性, 服务可以选择最适合自己的存储数据库.

引入的动机

那什么时候需要引入微服务呢? 这里需要考虑到的方面比较多, 一般来说, 会考虑到的推动力如下:

  • 单个服务涉及到多个团队

    单个服务如果涉及到了多个团队, 协同开发以及沟通的成本会大大增加. 此时, 使用微服务, 通过定义接口的方式, 能提高各自的开发效率. 同时, 不同团队间, 可以根据团队的特点, 各自定义自己服务的架构和技术栈.

  • 服务分享

    服务以接口方式提供给其他方进行调用, 方便数据共享等操作

  • 团队新成员必须快速上手

    单一项目代码复杂度到达一定程度, 希望通过解耦的方式, 来降低新人学习的难度

  • 应用应该易于理解和修改

  • 你想对应用进行持续集成

    通过引入CI\CD工具, 配合自动化测试, 从而提高开发效率, 增强代码的质量, 降低发布的难度. 大型的单体服务, 由于涉及到的模块很多, 操作复杂. 使得单元测试等方式不容易执行. 通过划分成微服务, 单个服务所承载的功能和逻辑较少, 使得单元测试更为简单.

  • 你必须在多台机器上部署多份应用的拷贝,以满足可伸缩性和可用性的要求

    每个微服务的可用性, 性能的需求都不同. 通过分离单体服务成为多个微服务的方式, 可以根据每个服务的具体情况, 来修改服务的数量, 从而达到性能\成本的均衡.

  • 你想使用新技术(框架、编程语言等)

    由于没有集中化的管理, 使得每个团队可以根据自己的技术栈来修改服务的实现. 同时, 因为每个服务的规模不会很大, 从而使得调整技术栈, 引入新技术成为可能

优缺点比较

微服务不是个灵丹妙药, 适用于任何场景. 微服务核心就是将原有的系统变成了分布式系统. 服务与服务之间的调用从函数调用变成了远程的服务调用. 整体上来看, 微服务带来的优点和缺点:

优点

  • 强模块边界

    传统开发, 我们会使用MVC等方式对系统进行划分, 以类等方式做抽象, 按层进行开发. 微服务在这方面更为极端. 以服务的模式, 通过API调用来提供能力.

  • 独立部署

    服务相对来说更为独立. 开发, 发布, 部署不需要涉及到多个团队来做集成和回归测试. 方便频繁部署新版本.

  • 提高故障隔离能力.

    服务之间不会相互影响. 即使某个服务引入了内存泄漏等问题, 也不会导致整个服务挂掉.

  • 单服务规模更小

    由于单服务规模较小, 从而更便于新人学习, 接手代码.

  • 按需扩容服务

    每个服务可以按照实际的需求来增加拷贝

  • 更贴合组织架构

    服务可以根据组织架构的层面进行切分, 每个团队负责其中单个或多个服务. 每个团队独立于其他团队进行开发\部署, 减少项目之间交流成本.

  • 提高技术多样性, 减少对单一技术栈的长期投入

    服务之间项目不影响. 团队可以根据自己的技术栈来构建服务. 对于某些场景, 可以使用更贴合的数据存储方式来存储. 前端团队可以使用nodejs来构建自己的服务, 后端团队可以使用java, go来支撑数据.

缺点及挑战

  • 分布式引入的复杂性

    微服务是分布式服务的一种形式. 通过将服务拆解微服务, 就引入了分布式的一些经典问题. 譬如

    • 服务间通信

    • 服务发现

    • 错误处理

  • 事务以及一致性问题

    单个微服务会有自己的数据库. 这也使得跨业务的事务成为了一个棘手的难题. 在单体模式下, 服务连接的是同一个数据库. 这使得在处理事务的过程中, 只需要使用数据库提供的2PC就可以解决了. 但是在微服务下, 跨服务间的事务, 则必须交由业务处理.

    此外, 由于CAP原则, 数据一致性也会成为一个问题. 通常情况下, 在互联网业务中都会倾向于最终一致性以来保证更高的服务吞吐量.

  • 测试

    在微服务下, 由于服务间的关系更为疏远. 服务与服务之间调用关系更为复杂, 从而导致集成测试就更为难做. 而且, 引入微服务往往意味着团队在遵循敏捷开发模式, 测试如何能支撑快速迭代与发布, 也是需要考虑的.

  • 部署

    在微服务下, 由于每个服务单独部署, 而不同服务依赖的环境可能完全不同, 需要的拷贝数量也不同, 需要的配置也不同. 这对于运维团队带来了更大的挑战.

总结

微服务其实并不神秘. 从整体上来看, 微服务就是原有的模块化设计转化成服务化设计. 将单体的应用整合成为服务间的调用, 从而更好的适应互联网的开发及服务场景. 例如

  • 服务分享

  • 快速迭代

  • 高性能高可用

  • 跨团队合作

当然, 微服务也带来了很多挑战, 需要基础设施来解决:

  • 更好的集成能力

  • 更好的快速部署方式

  • 简单的服务间发现\通信方式

  • 服务监控, 包括日志, metrics

对于各个大型的互联网厂商来说, 微服务早已经实践许久. 从netflix的微服务改造, 从而贡献出多种优秀的微服务组件, 例如consul, eureka, 到单语言, 全解决方案的spring boot框架, ali的dubbo, 腾讯开源的tars, 都很好的支撑了微服务的发展. 但整体来说, 使用微服务的成本还相对较高, 需要有专门的团队来维护这套基础设施, 才能很好的把微服务使用起来.

然而, 随着云厂商的兴起, ci/cd工具的流行, 尤其是k8s的逐渐成熟, 使得容器化部署, 服务发现, 快速扩容等问题对于小团队来说不再是个问题. 再搭配上最新的service mesh, 引入微服务的门槛不断降低, 使得微服务越来越被广大开发者接受.

引用

  • introduction to microservice

  • 微服务架构核心20讲: 一

  • 微服务架构核心20讲: 二

  • 纲举目张:带你看看微服务架构的前世今生

你可能感兴趣的:(微服务概述)