微服务基础概念认知总结

文章目录
  1. 1. 单体应用存在的问题
    1. 1.1. 复杂性高
    2. 1.2. 技术债务
    3. 1.3. 部署频率低
    4. 1.4. 可靠性差
    5. 1.5. 扩展能力受限
    6. 1.6. 阻碍技术创新
  2. 2. 微服务
    1. 2.1. 微服务架构应该具备的特性
    2. 2.2. 微服务架构的优点
    3. 2.3. 微服务架构面临的挑战
    4. 2.4. 微服务设计原则
  3. 3. 扩展
    1. 3.1. 领域驱动设计(DDD:Domain-Driver Design)
    2. 3.2. 云原生架构的方法论与最佳实践——十二要素应用宣言
    3. 3.3. 测试驱动开发(Test-Driven Development,TDD)

由于从未使用过Spring Cloud、Dubbo等微服务框架,所以只能不断地从微服务基础知识出发,不让自己局限于某一种工具框架上。以下知识摘自一些自己看过的微服务相关的书上,还有一些自己对微服务的理解。

单体应用存在的问题

复杂性高

单体应用项目包含的模块非常多、模块的边界模糊、依赖关系不清楚、代码质量层次不齐、混乱地堆砌在一起。每次修复BUG或者新增功能,涉及的部分比较多,存在着隐含的缺陷,有可能一小部分的改变会影响到其他功能。

技术债务

虽然时间的推移、需求变更和人员的更迭,会逐渐形成应用程序的技术债务,并且越积越多。

部署频率低

随着代码的增多,构建和部署的时间也会增加。而在单体应用中,每次功能的变更或缺陷的修复都会导致需要重新部署整个应用,并且上线前伴随着测试人员对整个系统功能的回归测试。全量部署的方式耗时长、影响范围大、风险高,这使得单体应用项目上线部署的频率较低。

可靠性差

一小处功能模块出问题,会导致整个应用的崩溃。

扩展能力受限

单体应用中只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩。

阻碍技术创新

单体应用往往使用统一的技术平台或方案解决所有的问题,团队中的每个成员都必须使用相同的开发语言和框架,要想引入新框架或新技术平台会非常困难。

微服务

微服务一词,最初来源于Martin Fowler,对微服务也没有一个明确的定义,但是却有一定的描述。

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automasted deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.

意思是微服务架构风格是一种将单一应用程序开发成一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过自动部署机制独立部署。这些服务共用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。

Martin Fowler

Martin Fowler是国际著名的面向对象分析设计、UML、模式等方面的专家,敏捷开发方法的创始人之一,现为ThoughtWorks公司的首席科学家。

他改变了人类开发软件的模式,他被开发者们尊为“教父”,他从不与媒体谈论技术以外的事情。

微服务架构应该具备的特性

  • 每个微服务可独立运行在自己的进程里。
  • 一系列独立运行的微服务共同构建起整个系统。
  • 每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理、用户管理等。
  • 微服务之间通过一些轻量的通信机制进行通信,例如通过RESTful API进行调用。
  • 可以使用不同的语言与数据存储技术。
  • 全自动的部署机制。

微服务架构的优点

易于开发和维护

一个微服务只会关注一个特定的业务功能,所以它业务清晰、代码量较少。开发和维护单个微服务相对简单。而整个应用是由若干个微服务构建而成的,所以整个应用也会被维持在一个可控状态。

单个微服务启动较快

单个微服务代码量较少,所以启动会比较快。

局部修改容易部署

单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。一般来说,对某个微服务进行修改,只需要重新部署这个服务即可。

技术栈不受限

在微服务架构中,可以结合项目业务及团队特点,合理地选择技术栈。例如有些服务科使用MySQL,有些则使用MongoDB;有些使用Java,有些使用Python。任何语言都不是万能的,可以根据不同的业务场景选择更适用的开发语言或框架。

按需伸缩

可根据需求,实现细粒度的扩展。例如,系统中的某个微服务遇到了瓶颈,可以结合这个微服务的业务特点,增加内存、升级CPU或者是增加节点。

微服务架构的应用虽然存在这些优点,但是在实现的过程中也存在更多单一应用所没有的挑战。

微服务架构面临的挑战

运维要求较高

更多的服务意味着更多的运维投入。在单体架构中,只需要保证一个应用的正常运行。而在微服务中,需要保证几十甚至几百个服务的正常运行与协作,这给运维带来了很大的挑战。

分布式固有的复杂性

使用微服务构建的是分布式系统。对于一个分布式系统,系统容错、网络延迟、分布式事务等都会带来巨大的挑战。

接口调整成本高

微服务之间通过接口进行通信。如果修改某一个微服务的API,可能所有使用了该接口的微服务都需要做调整。

重复劳动

很多服务可能都会使用到相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都会开发这一功能,从而导致代码重复。尽管可以使用共享库来解决这个问题,但是共享库在多语言环境下就不一定行得通了。

微服务设计原则

单一职责原则

单一职责原则是指一个单元(类、方法或者服务等)只应关注整个系统功能中单独、有界限的一部分。单一职责原则可以帮助我们更优雅的开发、更敏捷的交付。

服务自治原则

服务自治是指每个微服务应该具备独立的业务能力、依赖与运行环境。在微服务架构中,服务是独立的业务单元,应该与其他服务高度解耦。每个微服务从开发、测试、构建、部署,都应当可以独立运行,而不应该依赖其他的服务。

轻量级通信机制

微服务之间应该通过轻量级的通信机制进行交互。轻量级的通信机制应该具备两点:

  1. 体量较轻。
  2. 跨语言、跨平台。

像REST协议就是一种轻量级通讯机制,而Java的RMI通讯协议则不属于轻量级通讯协议,因为RMI绑定了Java语言。

微服务架构中,常用的协议有REST、AMQP、STOMP、MQTT等。

微服务粒度

微服务的粒度是难点,也尝尝是争论的焦点。应当使用合理的粒度划分微服务,而不是一味的把服务做小。代码量的多少不能作为微服务划分的依据,因为不同的微服务在本身的业务复杂性不同,代码量也不同。在微服务的设计阶段,就应确定其边界。微服务之间应相对独立并保持松耦合。

扩展

领域驱动设计(DDD:Domain-Driver Design)

架构是高层的设计,如果设计和理解有误,必将在实现时带来各种问题。架构又是最稳定的,不会因为各种具体技术的依赖,比如各种UI框架、ORM框架、IoC框架的更新换代而受到影响。

而在微服务的设计中,重中之重的设计就是需要确定服务边界,这个时候就可以需要提到DDD(领域驱动设计)。

DDD总体结构分为四层:Infrastructure(基础实施层),Domain(领域层),Application(应用层),Interfaces(表示层,也叫用户界面层或是接口层)。

根据DDD作者Eric Evans的说法,需要成功实施DDD主要有两个条件:

  1. 迭代开发过程
  2. 访问领域专家

迭代开发是DDD的生命力量。它可以实现实验,探索和调用问题域的主动重构,因为您可以继续与领域专家一起获得更多的洞察力。

云原生架构的方法论与最佳实践——十二要素应用宣言

  • 基准代码:一份基准代码,多份部署
  • 依赖:显式声明依赖关系
  • 配置:在环境中存储配置
  • 后端服务:把后端服务当做附加资源
  • 构建、发布、运行:严格分离构建和运行
  • 进程:以一个或多个无状态进程运行应用
  • 端口绑定:通过端口绑定提供服务
  • 并发:通过进程模型进行扩展
  • 易处理:快速启动和优雅终止可最大化健壮性
  • 开发环境与线上环境等价:尽可能的保持开发、预发布、线上环境相同
  • 日志:把日志当做事件流
  • 管理进程:后台管理任务当作一次性进程运行

测试驱动开发(Test-Driven Development,TDD)

测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码,并加速开发过程。 — 摘自百度百科

测试驱动开发的基本过程如下:

  1. 快速新增一个测试
  2. 运行所有测试(有时候只需要运行一个或一部分),发现新增的测试不能通过
  3. 做一些小小的改动,尽快让测试程序可运行,为此可以在程序中使用一些不合情理的方法
  4. 运行所有的测试,并且全部通过
  5. 重构代码,以消除重复设计,优化设计结构

关注我的微信公众号:FramePower
我会不定期发布相关技术积累,欢迎对技术有追求、志同道合的朋友加入,一起学习成长!


微信公众号

如果文章对你有帮助,欢迎点击上方按钮打赏作者