什么情况下使用微服务?

news2024/9/29 15:34:56

单体架构图参考网络: 

1. 什么是单体应用


单体应用就是将应用程序的所有功能都打包成一个独立的单元,最终以一个WAR包或JAR包存在,没有外部的任何依赖,里面包含DAO、Service、UI等所有的逻辑。
优点:

1.便于开发:只需要借助IDE的开发,调试功能即可。
2.易于测试:只需要通过单元测试或浏览器即可完成测试。
3.易于部署:打包成单一可执行jar包,执行jar包即可完成部署。


可是,这种简单的单元有很大的局限性。应用随着业务需求迭代,功能的追加扩展,最终成为一个庞然大物,变得更加复杂,逻辑耦合很严重,难以理解。团队开发人员职责不清,部署困难,回归测试成本巨大,交付率大大降低,总结下来单体应用有以下5大缺点:
 1.复杂性高

代码难以理解 部署困难  应用越来越大 测试越来越难


  在业务规模和团队规模发展到一定阶段,这些不足表现的更加明显。单体架构的不足表现在复杂性上,maven模块增多,多个模块耦合在一起,代码结构混乱,很难理解整个代码逻辑,容易导致代码质量低,复杂性进一步增加,同时代码复用度降低,不清楚某段代码的修改后的影响范围。
 代码难以被修改和重构
  不理解代码当然也写不出高内聚低耦合的代码,代码质量持续下降;复杂性进一步增加,然后耦合度越来越高,代码牵一而动全身,代码就很难修改和重构了。

团队职责不清楚


  高度耦合的单体工程使得逻辑边界模糊不清,新的业务需求开发任务无法有效分配到人,团队人员职责不清楚,沟通成本增加。

2.交付效率低
  构建和部署耗时长,难以定位问题,开发效率低。代码比较庞大,编译时间就会很长,开发调试将大部分时间花在重新编译上,代码量的增加又很难定位bug,导致开发效率进一步降低,在代码合并过程中很容易造成代码冲突,又花不少时间解决代码冲突,这些都可以导致开发效率降低。还有就是当我们开发一个新的功能或者修复一个bug,代码的变更影响是很难预估的,每次发布之前都要进行全部功能的回归测试;部署耗时长,影响范围广,风险大,发布频次低也会造成产品不能及时呈现给用户,甚至被对手赶超。


 3.伸缩性(scalable)差


  单体应用只能按整体横向扩展,无法分模块垂直扩展。IO密集型模块和CPU密集模块无法独立升级和扩容。业务模块对资源的需求是不一样的,比如图片压缩,加解密这些 都是cpu资源密集的应该升级CPU,而IO密集型的模块比如日志收集服务IO操作比较多需要更大的内存,使用比如SSD性能更好的磁盘。


  4.可靠性差


  一个bug有可能引起整个应用的崩溃。比如一个不重要的部分的内存泄露就会导致所有应用实例一个个宕机掉


  5.阻碍技术创新
  受技术栈限制,团队成员使用同一框架和语言。升级和变革技术框架困难。

2. 什么是微服务


2.1 微服务的定义

微服务架构图参考网络: 


   微服务架构是将单体应用拆分为多个高内聚低耦合的小型服务,每个服务运行在独立的进程,可由不同的团队开发和维护,服务间采用轻量通信机制,独立自动部署,可以采用不同的语言及存储。
   单体架构整个团队为何开发一个大工程和一个单库,在微服务架构中,用户请求经过API Gateway被路由到下游服务,服务之间以轻量级通信协议进行通信,服务通过注册中心发现彼此,每个服务都有专门的开发维护团队,每个服务都可以有自己独立的数据库,服务独立开发,部署,上线。

微服务的优点

1.易于开发与维护:微服务相对较小,易于理解,启动时间短,开发效率高。
2.独立部署:一个服务的修改不需要协调其他服务
3.伸缩性强:可以横向和纵向扩展
4.与组织结构匹配:更好的将架构和组织匹配,每个团队独立负责某些服务。
5.技术异构性:使用最适合该服务的技术,降低尝试新技术的成本。
 

说完优点,那么微服务有什么挑战呢?


2.2 微服务的挑战


1.服务拆分

拆分原则:领域模型,限定上下文,单一职责,组织结构,康威定律。


    现实中没有一个具体明确的方法可以将拆分一步到位,而是遵守一定的规则。服务拆分的同时还要考虑到数据库也要独立(如果需要),当每个服务服务直接读写数据库中同一张表时,对这些表做任何改动都需要协调这些相关服务的部署。共享的数据存储很容易不经意间造成耦合。每个服务需要有自己的私有数据。这一点违背了服务相互独立这一原则。比如订单表被订单服务和商品服务所共享,商品服务单独做统计并不知道自己一天多少商品被卖出,不知道哪些数据由本服务产生的,就无法进行技术产品规划,对表结构的修改也要通知多个服务,这是所不能容忍的。每个服务需要自己的数据库,但这些数据库可共置在一台共享的数据服务器上,数据库私有的重点在于不应让服务知道其他服务底层数据库的存在。可用一台共享数据服务器先开始开发,以后如果数据量和并发量变大,服务器可以进行隔离。服务器隔离后,只要更改配置即可将不同服务的数据库隔离起来。确定服务边界也是一个难题,需要对自己的产品和业务有足够的了解才能确定最自然的服务边界确定服务边界坚持的原则是要高内聚弱耦合,弱耦合就是一个服务与其他服务的任何通信都应通过公开暴露的接口(API、事件等)实现,这些接口需要妥善设计以隐藏内部细节。这样我们的服务之间保持独立,在未来我们可以轻松重构,高内聚力就是密切相关的多个功能应尽量包含在同一个服务中,这样可将服务之间的干扰降至最低。
 2.数据一致性
  在单体架构中,我们通过数据库事务完成的操作放在分布式微服务架构下无法完成了,因为实例被部署不同服务器上,比如订单服务进行下单操作,下单操作和扣减库存应该放在同一个事务中。在微服务架构下,下单操作和扣库存操作被分布在不同服务器上,就需要进行分布式事务操作,而分布式事务具有延迟较高、nosql数据库不支持等缺点。
这些缺点导致分布式事务无法应用到微服务中在微服务场景下,我们通常使用最终一致性来代替强

    一致性:

  • 可靠性事件模式 
  • 补偿模式-sagas模式


3.服务通信

通信技术方案: RPC vs REST vs 异步消息


  RPC、REST API、异步消息,异步消息我们可以借助一些消息队列框架来实现比如kafka、rrabbitMQ,那现在我们说下rpc和使用http协议的类似REST API之间 如何选择,TTP的好处是方便调试、跨语言、门槛低、广泛接受,同样缺点是协议文档不好维护,协议较为繁琐,性能较TCP要差是http协议的不足。
Rpc通信通常基于Tcp,常用的技术选型是thrift、grpc、dubbo,像thrift、grpc需要定义idl文件,通过idl文件来生成java代码,通过rpc的好处是IDE友好,有代码提示,协议维护在代码中,传参和响应结果都通过代码可以知道。但同时也有缺点比如很多rpc方案不知道跨语言,所支持的语言有限,需要定义和维护idl文件,且有一定的学习成本,另外rpc不容易方便的调试和测试。

服务注册和发现


  在服务实例变化不定的环境中,用硬编码指定IP地址的方式是行不通的,需要通过某种发现机制让服务能相互查找。这就需要我们将我们的服务信息注册到一个分布式存储中,这些服务信息就叫做服务注册表服务注册表可以作为信息的权威来源。其中包含有关可用服务的信息,以及服务网络位置比如ip、端口号这些信息。那借助什么组件进行实现呢,一般有Eureka,zookeeper,Nocas,除此之外我们还可以借助etcd,consul,redis这些。

负载均衡


  有了注册发现功能,客户端通过服务注册表发现实例清单并决定要连接哪个实例,在客户端做负载均衡,基于客户端做负载均衡相比服务端负载均衡有诸多好处:首先节省了硬件均衡设备,减少了运维成本,其次可以实现多种负载均衡策略比如响应感知的负载均衡策略。
  
4.服务网关

API Gateway


   我们的微服务如果和终端用户通信,势必要考虑到身份认证,安全防御等方面,如果每个微服务都与终端用户打交道,那么这些方面代码需要拷贝多份植入到每个微服务业务代码中。造成了业务代码和身份认证代码的耦合,降低了代码的复用性。这就需要在网络边界实现一个服务网关(这里的网络边界可以认为是内网和外网之间的边界),将身份认证,安全防御,流量控制这些功能放到服务网关中,向业务服务屏蔽网络边界服务的细节,使得业务服务专注于业务逻辑的开发维护和测试。
 
  为前端服务的后端(Backends For Forntends)
 
  服务网关可以根据终端产品形态来划分,比如公共API,桌面客户端,移动客户端分别对应一个服务网关,而服务网关可以是API Gateway只输出api,或者是为前端服务的后端,这里的为前端服务的后端,比如将来自多个服务的数据聚合到一起返回给前端。

身份认证、路由服务、限流防刷、日志统计

5.高可观察

健康检测、集中监控

     每个服务和使用的组件都有提供健康检测机制,使得我们可以及时发现异常的节点,然后做出判断和调整,将所有的监控指标进行聚合输出可视化图表和界面帮助我们快速直观发现问题。

日志聚合及检索

    比如在电商app我们发现无法进行下单操作,在分布式架构下,日志散落在多个服务多个服务器中,我们不知道错误日志打在哪台服务器上,如果每台服务器去登陆去看是极其低效的。这要求我们做到日志格式标准化,并通过一些手段聚合到一起进行检索查询。同时可跨越所有服务、特定的某个服务,或服务的某个实例搜索日志;将日志发送至集中化日志系统所用的代码可包含在共享库中或通过代码脚手架提供。

分布式追踪

     在微服务架构场景中,一个客户端发起的请求要经过多个服务的调用最终聚合数据结构返回给客户端,但我们不知道这个请求不知道经过哪些服务,调用哪个服务出现了问题,每个服务的输入输出是什么,这给我们定位问题带来了困扰,除此以外,如果一个请求耗时较长,我们不知道到底哪个服务耗时最长,好有针对性的性能优化。随着架构的演进,我们在架构设计规划时需要知道 服务之间的依赖关系,这有需要什么技术来实现呢,这就是我们要介绍的分布式追踪,分布式追踪借助关联id,在请求源头创建这个关联id,并且在服务间进行透传,最终将关联id等信息聚合到一起进行查询分析。

6.可靠性


      在讲单体的过程中,我们讲到,一个业务模块的内存泄露会导致整个进程退出。在微服务场景下,如果一个服务出现内存泄露是不会影响 没有依赖关系的服务的。但是却可以因为该异常服务的僵死或不可用造成上游服务线程hang住,进而产生级联效应,故障进一步向上游传播。

流量控制,超时控制

     可靠性技术通过流量的控制和超时控制,保证服务消费者不被下游服务拖慢,及时对业务线程循环复用。

舱壁隔离,熔断机制

     熔断是指服务调用出错次数在一定时间达到一定数量,自动关闭对该服务的调用开关,改为返回错误或者将请求转交给降级方法,降低资源耗尽的风险,当服务不可用时,作为服务消费者应该对接口方法编写一个降级方法。

服务降级, 幂等重试

      由于服务间通信是通过网络传输的,网络异常和网络分区故障 就会经常出现,我们遇到这种情况可以进行调用重试,重试时要注意两点,一个是接口必须是幂等的,无论运行一次或多次,最终结果必须相同。幂等性保证了重试不会产生负面影响。在重试过程时休眠时间应该是指数增长的,否则会产生惊群效应,比如:故障后的服务恢复上线后,如果有大量其他服务正在同一个重试窗口内重试,此时很容易给系统造成巨大压力。

提炼代码脚手架

      除了开发业务逻辑,我们还需要搭建一套微服务工程可用框架,这样是是为了加快团队工作效率,微服务解决方案保持统一,增强代码复用性,统一进行优化,微服务要解决的问题非常多,所以抽取服务代码模板是有必要的,它包括服务注册发现、服务通信、监控、日志、异常处理等等。

从单体迁移到微服务

1、何时迁移微服务?

 讲了这么多微服务的好处,我们是不是可以从此抛弃单体架构,一切项目直接投向微服务的怀抱了呢?

Martin Fowler在《MicroservicePremium》一文说:
“don’t even consider microservices unless you have a system that’s too complex to manage as a monolith”,翻译过来就是:如果你的系统不到足够复杂的程度不要考虑使用微服务。

     当业务不复杂,团队规模不大的时候,单块架构比微服务架构具有更高的生产率(productivity)。因为建立微服务架构需要额外的开销来支持和管理微服务,从而降低生产率;但是随着业务复杂性的增加和团队规模的扩大,单块架构比微服务架构的生产率下降更趋明显。
当复杂性达到一个临界点,微服务架构的生产率会优于单块架构,因为微服务的松散耦合自治特性减缓了生产率的下降趋势。
所以我们在做项目时,一定要根据自己的团队和业务复杂性来判断,何时应用微服务。

    以我的经验给大家的建议时,一个全新项目在1-3团队时,可以先拆分成一个API 网关和一个集合所有业务的后端服务,API网关关注鉴权和路由、处理部分失败;后端服务要划分好业务模块;项目初期,由于流量不多,可以不必添加流量控制和断路器等组件。

同时即使向微服务架构迁移之后,拆分的粒度也要由粗到细演进式发展,一定要根据自己的业务规模复杂性和团队规模来定。

2.如何迁移到微服务上来?

      一个策略是:不要大规模(big bang)重写代码(只有当你承担重建一套全新基于微服务的应用时候可以采用重写这种方法)。重写代码听起来很不错,但实际上充满了风险最终可能会失败,就如Martin Fowler所说:“the only thing a Big Bang rewrite guarantees is a Big Bang!”相反,应该采取逐步迁移单体式应用的策略,通过逐步生成微服务新应用,与旧的单体式应用集成,随着时间推移,单体式应用在整个架构中比例逐渐下降直到消失或者成为微服务架构一部分。这个策略有点像在高速路上限速到70迈对车做维护,尽管有挑战,但是比起重写的风险小很多。
Martin Fowler将这种现代化策略成为绞杀应用,名字来源于雨林中的绞杀藤(strangler vine),也叫绞杀榕(strangler fig)。绞杀藤为了爬到森林顶端都要缠绕着大叔生长,一段时间后,树死了,留下树形藤。这种应用也使用同一种模式,围绕着传统应用开发了新型微服务应用,传统应用会渐渐退出舞台。

SOA VS 微服务

SOA和微服务的对比是一个老生常谈的话题,我认为两者最大的不同是提出时所处的技术背景和环境。

      SOA的出现其实是为了解决历史问题:企业在信息化的过程中会有各种各样互相隔离的系统,需要有一种机制将他们整合起来,所以才会有ESB的出现。同样的,也成了SOA初期的服务是很大的概念,通常指定的一个可以独立运作的系统。

      微服务没有历史包袱,服务的尺寸通常不会太大。从服务粒度来讲,SOA更像是单体的简单组合,而微服务是粒度更细小的服务,其次数据拆分SOA倾向于共享数据库,微服务一个服务对应一个数据库。

3. 为什么采用Spring Cloud Alibaba

Spring Cloud Alibaba架构图参考网络:

3.1 Spring Cloud Alibaba 真实应用场景

  • 大型复杂的系统,例如大型电商系统(原因:业务复杂)
  • 高并发系统,例如大型门户,秒杀系统(原因:去中心化,能够承载更高的负载压力,并且提供个一款很好用的容错组件`Sentinel`可以进一步提升应用可用性、容错性)
  • 需求不明确,且变更很快的系统,例如创业公司业务系统(原因:修改模块方便)

3.2 Spring Cloud Alibaba 和 Spring Cloud 有什么区别和联系呢?

  • Spring Cloud Alibaba 是 Spring Cloud的子项目
  • Spring Cloud Alibaba 是 Spring Cloud的子项目
Spring Cloud 第一代状态Spring Cloud Alibaba状态
Eureka2.0孵化失败Nacos Discovery性能强劲,感知更快
Ribbon进去维护状态,预计2020年1月停止维护,新的标准已形成:spring-clound-loadbalancer,但暂无参考实现。Spring Clound Hoxton 才会孵化出替代品
Hystrix/Hystrix Dashboard/Turbine进入维护状态,预计2020年1月停止维护Sentinel可视化配置,上手更简单
Zuul进入维护状态,预计2020年1月停止维护Spring Cloud Gateway性能是Zuul的1.6倍
Spring Clound Config搭建复杂,约定多,设计繁重,没有洁面,难维护,难以上手Nacos Config搭建简单,有可视化界面,配置管理更高效,学习曲线低

总体来将 Spring Cloud Alibaba 组件性能更强,良好的可视化界面,搭建简单,学习曲线低,文档丰富并且是中文

3.3 Spring Clound Alibaba 的重要组件

服务发现 Nacos实现负载均衡 Ribbon声明式HTTP客户端-Feign
服务发现原理负载均衡的常见模式剖析如何使用Feign
Nacos Server/ClientRestTemplate整合RibbonFeign配置自定义
高可用Nacos搭建Ribbon配置自定义如何扩展Feign
0如何扩展 Ribbon0
服务容错 Sentinel消息驱动 RocketMQAPI网关 Gateway
服务容错原理Spring Clound Stream整合Gateway
Sentinel实现异步消息推送与消费三大核心
Sentinel Dashboard聚合微服务请求
Sentinel 核心原理分
用户认证与授权配置管理 Nacos调用链监控Sleuth
认证授权的常见方案配置如何管理调用链监控原理剖析
改造Gateway配置动态刷新Sleuth使用
扩展Feigh Dashboard配置管理的最佳实践Ziplin使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Multisim14.0仿真(十九)两片74LS138接成4线16线译码器

一、仿真原理图: 二、仿真效果图:

win系统环境搭建(五)——Windows安装redis

windows环境搭建专栏🔗点击跳转 win系统环境搭建(五)——Windows安装redis 本系列windows环境搭建开始讲解如何给win系统搭建环境,本人所用系统是腾讯云服务器的Windows Server 2022,你可以理解成就是你用的windows10…

一台主机外接两台显示器

一台主机外接两台显示器 写在最前面双屏配置软件双屏跳转 写在最前面 在使用电脑时需要运行多个程序,时不时就要频繁的切换,很麻烦 但就能用双屏显示来解决这个问题,用一台主机控制,同时外接两台显示器并显示不同画面。 参考&a…

【运维篇】三、SLF4J与Logback

文章目录 0、Java的门面设计模式1、SLF4J2、作用3、调试4、SpringBoot采用SLF4JLogback5、切换SpringBoot的日志框架6、logback的配置加载7、logback的配置组成8、logback之logger9、logback之appender10、logback之pattern11、appender的Filter12、logback.xml全解释13、logba…

带你读懂任正非先生的最新讲话——与ICPC代表讲话纪要(一)

2023年9月19日,在ICPC中国赛区北京总部的官网(设立在北京大学)上发布了一条新闻:《今天我们汇聚一堂,明天我们将奔向四面八方——任正非与ICPC基金会及教练和金牌获得者的学生的谈话纪要》。 2023年8月21日和8月26日&a…

Java笔记:Java虚拟机的指令

1. 字节码指令集 1.1 概述 Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode) 以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。 比如&#x…

对话ChatGPT:AIGC时代下,分布式存储的应用与前景

随着科技的飞速发展,我们正步入一个被称为AIGC时代的全新阶段,人工智能、物联网、大数据、云计算成为这个信息爆炸时代的主要特征。自2022年11月以来,ChatGPT的知名度迅速攀升,引发了全球科技爱好者的极大关注,其高超的…

【23种设计模式】装饰模式(九)

前言 装饰模式,英文名称:Decorator Pattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理解吧,大家一定要看清楚,是“装修”,不是“装饰”。在房子装修的过程中,各种功能可…

Jenkins学习笔记3

gitgithubjenkins: 架构图: 说明:jenkins知道github有更新了,就pull进行构建build,编译、自动化测试。然后部署到应用服务器。 maven java的项目构建工具。 在开发者电脑上创建空密码密钥对。 [rootgit-developer ~…

系统架构设计师-数据库系统(3)

目录 一、数据控制 1、安全性 2、完整性 3、并发控制 4、故障恢复 二、数据库设计概述 1、数据库设计关注的问题 2、数据库性能优化 3、规范化与反规范化 一、数据控制 1、安全性 2、完整性 (1)实体完整性约束:规定基本关系的主属性不能取空…

论文写作格式经验

论文写作经验: 交叉引用 在公式后输入#(1),回车选中(1),选择插入->添加书签,自定义书签名交叉引用->引用类型:书签一个公式对应一个书签 这样就可以只显示公式编号了 word转p…

数据的力量,环保的未来!气象信息采集系统解决方案助您实现环境优化

小伙伴们,今天给大家讲一个真实的案例,看看如何用气象信息采集系统提高环保监测能力。 随着环境污染问题越来越严重,许多城市都开始建设空气质量监测站,对各类污染数据进行采集。但是传统的监测站设备复杂,采集范围有限,这就需要用到工业物联网的解决方案。 我们公司参与建设了…

R语言-关于颜色

目录 颜色 示例 R 颜色板 参考: 颜色 什么场景会用到颜色?比如在绘图过程中,为了让图更好看,有的时候,需要选择使用不同的颜色进行绘制或者填充。本文提供了R颜色的相关参数。 在R中,可以通过颜色下标…

面向面试知识-Redis

面向面试知识-Redis 什么是Redis 运行于内存的基于key-value的非关系型数据库。 一款开源的内存数据结构存储,用作数据库、缓存、消息代理等。(可以基于Redis实现分布式锁、以及消息队列) 发布订阅?? 对数据类型的操…

数据库数据恢复-SQL SERVER数据库文件损坏的故障表现数据恢复方案

SQL SERVER数据库故障类型: SQL SERVER数据库MDF(NDF)或LDF损坏。 SQL SERVER数据库故障原因: 1、数据库正在操作过程中,机器突然断电。 2、人为误操作。 SQL SERVER数据库MDF(NDF)或LDF损坏的…

Qt/C++音视频开发55-加密保存到文件并解密播放

一、前言 为了保证视频文件的安全性,有时候需要对保存的视频文件加密,然后播放的时候解密出来再播放,只有加密解密的秘钥一致时才能正常播放,用ffmpeg做视频文件的加密保存和解密播放比较简单,基于ffmpeg强大的字典参…

2023最全软件测试面试八股文(答案+文档+视频讲解)

Part1 1、你的测试职业发展是什么? 测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师奔去。而且我也有初步的职业规划,前3年积累测试经验,按如何做好测试工程师的要点去要求自…

【C语言】指针的进阶(三)—— 模拟实现qsort函数以及指针和数组的笔试题解析

目录 1、模拟实现qsort函数 1.1、qsort函数的回顾 1.2、模拟实现qsort函数 2、指针和数组笔试题解析 2.1、一维数组 2.2、字符数组 1、模拟实现qsort函数 1.1、qsort函数的回顾 要模拟实现qsort函数,就要了解清楚qsort函数的参数以及使用方式。 我们先回顾一…

PyTorch实战:实现Cifar10彩色图片分类

目录 前言 一、Cifar10数据集 class torch.utils.data.Dataset torch.utils.data.DataLoader 二、定义神经网络 普通神经网络: 定义损失函数和优化器 训练网络-Net CPU训练 模型准确率 ​编辑 GPU训练 训练网络-LeNet 模型准确率 点关注,防走丢&#x…

9月15日、9月18日上课内容 Zookeeper集群 + Kafka集群

Zookeeper 本章结构 Zookeeper 概述 Zookeeper 定义 *(了解) Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。 Zookeeper 工作机制 *****(非常重要,需要掌握) Zookeeper从设计模式…