文章目录

  • 应用层
  • 微服务架构
  • 服务注册查询 Service Discovery
    • 客户端 Service Discovery
    • DNS-SD DNS-based Service Discovery
    • 服务端 Service Discovery
  • 服务注册与注销
    • 自注册模式
    • 第三方注册模式
  • 总结
  • 参考

应用层

在简单的 3 层结构中,Web 服务层既要处理请求,又要承载业务功能:

而更优的结构是把 Web 层与应用层(也叫平台层)分开:

这样的优势在于:

  • 能够单独扩展应用层;允许独立加机器、换专用机器
  • 复用基础设施:简化多端支持,缓存、数据库等处理都可以复用
  • 使得组织更容易扩展:一个团队负责实现/优化平台本身,其他多个团队利用平台功能进行开发

分离出应用层之后,面临的下一个问题是应用层内部如何划分职责,如何协同工作,也就是微服务架构所要解决的问题

微服务架构

Monolithic application 架构
把软件应用的不同组件都放到一个程序中,就叫 Monolithic application。例如,通过编程语言的基本特性将应用划分成类、函数和命名空间,用部署流水线来保证变更都经过测试后才部署到生产环境,并通过负载均衡机制运行多个实例,将其进行横向扩展。
在这种架构模式下,应用程序也能很好地工作,但存在 2 个问题:

  • 变更受限制:很小的一处变更也需要对整个应用进行重新构建和部署,而且难以控制变更的影响范围
  • 不利于扩展:无法仅扩展应用中需要更多资源的那些部分,只能扩展整个应用
    这些限制在云环境下尤其突出。于是,微服务架构登上了舞台。
    微服务架构提倡把应用程序设计成一系列松耦合的细粒度服务,并通过轻量级的通信协议组织起来。
    这些服务都能够独立部署、独立扩展,每个服务都具有稳固的模块边界,甚至允许使用不同的编程语言来编写不同服务,也可以由不同的团队来管理。
    微服务架构具有下面 9 大特征:
    1、通过服务进行组件化(Componentization via Services)
    组件可以理解为能够独立更换升级的软件单元,一系列组件插在一起构成软件系统。
    在微服务架构中,组件就是服务,通过 Web 服务请求或 RPC 之类的机制通信。这种服务粒度的组件化方式有 2 点优势:
  • 服务能够独立部署
  • 服务具有显式的对外接口

独立部署,意味着对一个服务的内部改动只需要重新部署该服务,涉及服务接口改动时才需要协同修改多个服务。另一方面,还可以通过服务边界和服务协议方面的演进来尽可能减少这样的关联。显式的对外接口则是一种强约束,能够保证组件的封装性,避免组件间出现过度的紧耦合。但比起进程内调用,RPC 的性能成本更高,因此 RPC 接口大多是粗粒度的,也往往更难使用。另一方面,如果想要调整组件职责的话,重构成本也更高。
2、围绕业务功能来组织团队(Organized around Business Capabilities)
微服务允许将系统根据业务功能分解成一系列服务,因此可以围绕业务功能来组织跨职能的团队。并且,这种组织结构还有利于强化服务边界。比起在 Monolithic application 中按业务线划分团队,以服务为边界更清晰、约束力也更强。因为很容易出现跨越模块边界的业务功能,而服务边界相对稳固一些。
3、做产品而不是做项目(Products not Projects)
微服务架构倾向于一个产品由所属开发团队长期维护/演进,而不是项目交付后转由另一个维护团队负责。
这种产品理念能够在开发团队与用户之间建立持续的关联,让开发团队关注到软件如何帮助用户增进业务功能。
4、智能端点和傻瓜式管道(Smart endpoints and dumb pipes)
通信机制上,一个典型的例子是企业服务总线(Enterprise Service Bus),消息都流经 ESB,由 ESB 负责消息路由、编排、转换以及业务规则的应用,随后到达端点(endpoints)进行处理。这种模式下,端点可以保持傻瓜式,因为很多逻辑都在 ESB 消息管道里处理了。因此,称之为智能管道和傻瓜式端点(smart pipes and dumb endpoints)。
而微服务倾向于相反的做法,智能端点和傻瓜式管道(smart endpoints and dumb pipes):管道只负责在组件之间分发消息,由服务本身针对消息做相应处理。
5、去中心化技术治理(Decentralized Governance)
中心化技术治理最大的问题在于其局限性,统一的技术栈并不一定适用于所有场景。
而在微服务背景下,每个服务单独构建,就有了选择不同技术栈的机会,允许用更合适的工具去做不同的事情。这种技术栈上的自由有助于服务独立演进,自然选择出更好的模式。
6、去中心化数据管理(Decentralized Data Management)
从最抽象的层面看,去中心化地管理数据,意味着各个系统对客观世界所形成的概念模型各不相同。给模型概念限定一个上下文,在该上下文中保证概念严格一致。把一个复杂领域划分成多个界限上下文,再将其间关联勾画出来,就是概念模型层面的去中心化。具体到数据存储上,微服务也进行类似的去中心化策略,让每一个服务管理自己的数据库。这些数据库可以是相同数据库的不同实例,也可以是完全不同的数据库系统,称之为混合持久化。对于去中心化数据存储带来的数据一致性问题,可以考虑通过一些补偿操作来让数据最终达到一致。
7、基础设施自动化(Infrastructure Automation)
与 Monolithic application 相比,微服务的部署要更复杂一些。因为在复杂的网络环境中,部署多个服务比部署一个独立应用更困难。
8、容错设计(Design for failure)
在微服务背景下,客户端的容错设计更为重要:

将服务作为组件使用的一个结果是,应用程序需要设计为能够容忍服务故障。
由于供应商不可用,任何服务呼叫都可能失败,客户必须尽可能优雅地响应。

比起 Monolithic application,这种容错设计带来的额外复杂性算是一种劣势。另一方面,为了快速检测到故障点,甚至尽可能自动恢复服务,实时监控在微服务架构中也格外重要。
9、演进式设计(Evolutionary Design)
组件的划分在微服务架构中很关键,关系到能否减少变化。一般原则是该组件能否独立更换和升级。
把微服务架构提供的服务分解能力当做一种工具来使用,以此实现服务粒度的变化控制:

  • 预期一些服务将来会作废,不必长期演进
  • 把那些会同时变化的东西放到同一个服务中,把很少发生变化的部分放到单独服务中,与经常发生变化的部分区分开

服务注册查询 Service Discovery

微服务架构下,应用被拆分成了多个服务,各自运行在(不同机器的)不同进程中。
如果每个微服务都只运行在单台机器上,一个微服务可以通过静态配置表找到其它依赖服务,进而通过服务间通信完成协作。然而,实际场景下,1 个微服务通常会部署在多台机器上,并按需动态伸缩(增减机器),简单的静态配置显然无法满足,因而需要一种服务注册查询机制:

这点即Service Discovery

客户端 Service Discovery


客户端查询服务注册表,得到目标服务的一系列地址,并根据负载均衡策略从中选择一个发起请求(即客户端负载均衡)。
其中,服务注册表(service registry)用来存放所有可用的服务实例,并提供管理(注册/注销)和查询 API:

服务注册表是可用服务实例的数据库。
服务注册中心提供了一个管理API和一个查询API。
使用管理API在服务注册表中注册和注销服务实例。
系统组件使用查询API来发现可用的服务实例。

具体的,在启动服务实例时,向注册表添加其网络位置,停掉服务时移除记录,并在服务实例运行期间,通过心跳机制周期性地刷新注册信息。
这种模式相对简单,而且客户端能够做出更聪明的(比如特定于应用程序的)负载均衡决策,但也存在一些缺点:

  • 客户端用到的每种语言都要实现一遍
  • 需要自行维护一个高可用的注册服务
  • 服务发现相关逻辑都在客户端实现,比如重试,造成客户端比较重

DNS-SD DNS-based Service Discovery

特殊的,可以将 DNS 用作服务注册表,称之为DNS-SD(DNS-based Service Discovery)
通过 DNS SRV 记录来完成服务到实例的一对多映射:

SRV 记录(Service locator record):通用服务定位记录,指定服务所在的服务器(域名和端口号),多用于 SIP(Session Initiation Protocol,会话发起协议)

借助 DNS 虽然简单易操作,但受限于 DNS 的更新时效(缓存问题)

服务端 Service Discovery

当然,查询的过程也可以在服务端完成:

客户端通过负载均衡器请求目标服务,负载均衡器查注册表得到一组可用实例,并根据负载均衡策略从中选择一个发起请求。
这种模式下,客户端不必再为各种语言、不同框架实现服务查询逻辑,简单地向负载均衡器发起请求即可,但如果部署平台没有提供这种能力的话,需要自行建立并维护这样一个高可用的系统组件。

服务注册与注销

Service Discovery 中,服务实例必须注册到服务注册表,并及时注销,分为自注册与第三方注册 2 种模式。

自注册模式


自注册模式下,服务实例负责把自己注册到服务注册表,以及从中注销,必要的话,还要发送心跳请求保持活跃,避免其注册过期。这种方式相对简单,不依赖其它系统组件,但服务实例和服务注册机制产生了耦合,以致于注册逻辑需要在各种语言、不同框架的客户端都实现一遍

第三方注册模式


服务实例不再负责注册/注销,交由服务登记员(service registrar)来处理,解除了服务实例与注册机制间的耦合关系。登记员通过轮询部署平台或订阅事件来跟踪服务实例的运行状态,发现新服务实例就注册上去,发现服务实例停掉了就注销掉。
例如Registrator就采用了这种模式,支持自动注册/注销用 Docker 容器部署的服务。

总结

微服务架构负责拆分服务、解耦依赖关系,而 Service Discovery 用来解决这些服务间的通信问题,让一个微服务能够找到另一个。
实现上,分为客户端 Service Discovery 与服务端 Service Discovery 两种,区别在于查询/选取逻辑实现在客户端还是服务端。而服务的注册/注销可以由服务自身完成(自注册),也可以由部署平台等第三方来完成(第三方注册)

参考

http://www.ayqy.net/blog/service-discovery/

后台系统可扩展性学习笔记(七)Service Discovery与微服务相关推荐

  1. 后台系统可扩展性学习笔记

    整理了一下笔记目录,将以前学习的一些知识串联起来了,比如cdn.负载均衡.中间件,以前只是各自了解了一点,现在大概理清了后台系统设计中他们各自的作用. 后台系统可扩展性学习笔记(一)概要 后台系统可扩 ...

  2. 后台系统可扩展性学习笔记(一)概要

    文章目录 系统大致架构 可扩展性 负载均衡器与会话保持 引入冗余增强系统可用性 缓存减轻数据库压力 异步处理 参考 系统大致架构 当一个用户请求从客户端出发,经过网络传输,达到 Web 服务层,接着进 ...

  3. 后台系统可扩展性学习笔记(十)Database Partitioning

    为了提升数据库的处理能力,我们把单库扩展成多库,并通过更新同步机制(即Replication)来保证多份数据的一致性.然而,在 各种复制方案下,每个数据库都持有一份完整数据,基于全量数据提供增删改查服 ...

  4. 后台系统可扩展性学习笔记(十四)异步机制与MQ

    对于 Web 服务而言,提升可扩展性的主要途径是将耗时的同步工作改成异步处理,从而允许将这些工作"外包"给多个 Worker 去做,或者提前完成能够预知的部分. 异步机制与可扩展性 ...

  5. 后台系统可扩展性学习笔记(十二)NoSQL

    文章目录 NoSQL定义 NoSQL种类 键值存储 文档存储 宽列存储 图形数据库 NoSQL 意味着什么 ACID vs. BASE SQL or NoSQL NoSQL定义 不同于关系型数据库,N ...

  6. 后台系统可扩展性学习笔记(五)负载均衡

    文章目录 Load balancer(负载均衡器) 请求传输拆解 DNS 负载均衡 客户端负载均衡 OSI 七层模型回顾 2 层.3 层负载均衡 3/4 层负载均衡 7 层负载均衡 在 第一节谈到了系 ...

  7. 后台系统可扩展性学习笔记(十一)Database Denormalization

    之前的两篇笔记中谈到了从单库扩展到多库以承载更多的请求量以及单库(表)拆分成多库(表),打破单库的性能瓶颈. 这都是为了应对大数据量下的措施. 然而,除却数据量外,还有一个极其影响单库性能的因素--数 ...

  8. 后台系统可扩展性学习笔记(十三)缓存

    文章目录 在哪儿加缓存 缓存什么内容 缓存原始查库结果 缓存数据对象 怎么查询缓存结果 预留缓存模式 直读模式 直写模式 回写式缓存 绕写式缓存 提前刷新模式 缓存满了如何处理 参考 读写分离.分库分 ...

  9. 后台系统可扩展性学习笔记(三)DNS机制原理

    文章目录 DNS概念梳理 域名基本概念 资源记录基本概念 路由策略 DNS 域空间结构 实现原理 复制机制 查询机制 缓存机制 参考 DNS概念梳理 DNS(Domain Name System)相当 ...

最新文章

  1. Springboot 利用AOP编程实现切面日志
  2. C++_泛型编程与标准库(八)
  3. 如何对比两个Jar包
  4. arch linux 下安装 conan permissionError :[Erno 13] Permission denied
  5. OpenCV知识和项目列表
  6. JS_dom查询节点
  7. 全能Android HOOK框架 JNI NATIVE JAVA ART DALVIK
  8. 生活随笔:态度需要端正
  9. net core 3.0 之Grpc新特性小试牛刀
  10. 一些算法题,欢迎来改进
  11. 揭秘也门仆人阶层:没食物时吃亲人尸体
  12. JAVA对接支付宝支付(超详细,一看就懂)
  13. codeforce 460B Little Dima and Equation
  14. sys.argv学习,通过运行py脚本,手动传入参数
  15. solaris java 安装_solaris中安装jdk环境
  16. 这些数据结构基本概念你晓得几个嘞?
  17. Mac 电脑 插显示器 提示:显示器不支持当前的输入时序,解决办法
  18. 安装Oozie4.1.0-CDH版本
  19. echarts嵌套饼图自动动画_使用百度echarts制作可视化大屏——制作一个双层饼图...
  20. dpkg: 处理软件包 xxxxxxxx (–configure)时出错:

热门文章

  1. c java 系统开发_java开发系统内核:使用C语言开发系统应用程序
  2. 大学生助学贷款如何还利息(本金+利息都可以)
  3. 9.1定时器 小时分秒
  4. Aspose.Words简单生成word文档
  5. KindEditor编辑器, 利用ajax动态切换编辑器内容
  6. windows.onload和body的onload属性的区别
  7. CSS3新增的伪类选择器
  8. EF 拉姆达 linq if else (整理)
  9. UI设计中颜色的前进色与后退色
  10. WPFの操作文件浏览框几种方式