微服务概述与SpringCloud概述

1.什么是微服务?

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相协作(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

从技术角度来说:

微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事,从技术角度看就是一种小而独立的处理过程,类似进程概念,能够自行单独启动或销毁,拥有自己独立的数据库。

2.微服务技术栈有哪些

微服务条目落地技术:

服务开发

Springboot、Spring、SpringMVC

服务配置与管理

Netflix公司的Archaius、阿里的Diamond等

服务注册与发现

Eureka、Consul、Zookeeper等

服务调用

Rest、RPC、gRPC

服务熔断器

Hystrix、Envoy等

负载均衡

Ribbon、Nginx等

服务接口调用

(客户端调用服务的简化工具)Feign等

消息队列

Kafka、RabbitMQ、ActiveMQ等

服务配置中心管理

SpringCloudConfig、Chef等

服务路由

(API网关)Zuul等服务监控Zabbix、Nagios、Metrics、Spectator等

全链路追踪

Zipkin,Brave、Dapper等

服务部署

Docker、OpenStack、Kubernetes等

数据流操作开发包

SpringCloud Stream(封装与Redis,Rabbit、Kafka等发送接收消息)

事件消息总线

Spring Cloud Bus…

3.微服务之间的通讯方式

1.远程调用

直接通过远程调用来访问服务。

例如:RESTful,RPC

优点:

简单,常见。因为没有中间件代理,系统更简单

缺点:

只支持请求/响应的模式,不支持别的,比如通知、请求/异步响应、发布/订阅、发布/异步响应
降低了可用性,因为客户端和服务端在请求过程中必须都是可用的

2. 消息

使用异步消息来做服务间通信。服务间通过消息管道来交换消息,从而通信。

例如:Apache Kafka、RabbitMQ

优点:

把客户端和服务端解耦,更松耦合 提高可用性,因为消息中间件缓存了消息,直到消费者可以消费
支持很多通信机制比如通知、请求/异步响应、发布/订阅、发布/异步响应

缺点:

消息中间件有额外的复杂性 会增加额外负担

4.微服务的优缺点

优点

  • 每个服务足够内聚,足够小,代码容易理解这样能聚焦一个指定的业务功能或业务需求 开发简单、开发效率提高,一个服务可能就是专一的只干一件事。
  • 微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。
  • 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。 微服务能使用不同的语言开发。
  • 易于和第三方集成,微服务允许容易且灵活的方式集成自动部署,通过持续集成工具,如Jenkins, Hudson, bamboo
  • 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。 微服务允许你利用融合最新技术。
  • 微服务只是业务逻辑的代码,不会和HTML,CSS 或其他界面组件混合。
  • 每个微服务都有自己的存储能力,可以有自己的数据库。也可以有统一数据库。

缺点

  • 开发人员要处理分布式系统的复杂性
  • 多服务运维难度,随着服务的增加,运维的压力也在增大
  • 系统部署依赖
  • 服务间通信成本
  • 数据一致性
  • 系统集成测试
  • 性能监控……

5.服务雪崩、降级与熔断,隔离

分布式系统面临许多问题,其中服务雪崩、降级与熔断,隔离都是常问到的问题。


分布式体系结构中的应用程序有很多依赖关系,每个依赖关系在某些时候将不可避免地失败。

服务雪崩

服务调用链图
服务A的流量突然增加,服务A扛得住请求,服务B服务C未必能扛得住这突发的请求。

如果服务C因为抗不住请求,变得不可用。那么服务B的请求也会阻塞,慢慢耗尽服务B的线程资源,服务B就会变得不可用。紧接着,服务 A也会不可用

在这里插入图片描述
一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒钟内饱和,为了对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。

为了对服务依赖的保护主要有以下三种解决方案

熔断:类似于家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用,如果目标服务情况好转则恢复调用。

隔离:这种模式就像对系统请求按类型划分成一个个小岛的一样,当某个小岛被火少光了,不会影响到其他的小岛。例如可以对不同类型的请求使用线程池来资源隔离,每种类型的请求互不影响,如果一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,不再调用后续资源。这种模式使用场景非常多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者多中心。

限流:上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则可以称为预防模式。限流模式主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统整体资源分配问题,因为没有被限流的请求依然有可能造成雪崩效应。


服务熔断

服务熔断,解决服务雪崩的手段之一。

服务熔断:当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。

熔断其实是一个框架级的处理,那么这套熔断机制的设计,基本上业内用的是断路器模式

在这里插入图片描述

  • 最开始处于closed状态,一旦检测到错误到达一定阈值,便转为open状态;
  • 这时候会有个 reset timeout,到了这个时间了,会转移到half open状态;
  • 尝试放行一部分请求到后端,一旦检测成功便回归到closed状态,即恢复服务;

在Hystrix中,对应配置如下

//滑动窗口的大小,默认为20
circuitBreaker.requestVolumeThreshold 
//过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.sleepWindowInMilliseconds 
//错误率,默认50%
circuitBreaker.errorThresholdPercentage

每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。


服务降级

这里有两种场景:

  • 当下游的服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!
  • 当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

上面的场景就是熔断,下面的场景是降级。

应该要这么理解:

  • 服务降级有很多种降级方式!如开关降级、限流降级、熔断降级!
  • 服务熔断属于降级方式的一种!

熔断和降级必定是一起出现,不可能只出现熔断,不出现降级。当下游服务不可用,为了对用户负责,就要进入上游的降级逻辑

try{
    //调用下游的helloWorld服务
    xxRpc.helloWorld();
}catch(Exception e){
    //因为熔断,所以调不通
    doSomething();
}

下游的helloWorld服务因为熔断而调不通。此时上游服务就会进入catch里头的代码块,那么catch里头执行的逻辑,你就可以理解为本地降级逻辑


服务降级大多是属于一种业务级别的处理。另一种降级方式,也就是开关降级,在生产中也很常见。

做个开关,然后将开关放配置中心!在配置中心更改开关。配置变动后,应用监控到配置发生了变动,决定哪些服务进行降级。

在应用程序中部下开关的这个过程,叫埋点

哪些业务需要埋点?一般有以下方法

(1)简化执行流程
自己梳理出核心业务流程和非核心业务流程。然后在非核心业务流程上加上开关,一旦发现系统扛不住,关掉开关,结束这些次要流程。

(2)关闭次要功能
一个微服务下肯定有很多功能,那自己区分出主要功能和次要功能。然后次要功能加上开关,需要降级的时候,把次要功能关了吧!

(3)降低一致性
假设,你在业务上发现执行流程没法简化了,愁啊!也没啥次要功能可以关了,桑心啊!那只能降低一致性了,即将核心业务流程的同步改异步,将强一致性改最终一致性!


服务隔离

做服务隔离的目的就是避免服务之间相互影响。毕竟无法保证任何一个微服务百分百可用,如果不做隔离,一旦一个服务出现了问题,整个系统的稳定性都会受到影响!

根据隔离方式分为:

  • 种类隔离
  • 用户隔离

按种类隔离

按种类隔离,是将服务划分成两个种类,两种角色。即服务提供方服务调用方

在这里插入图片描述
如图,图中存在三个服务提供方角色和一个服务调用方角色

服务提供方 :

支付服务(给用户提供服务)
库存服务(给支付服务提供服务)
订单服务(给支付服务提供服务)

服务调用方:
支付服务(调用订单服务和库存服务)
服务提供方隔离方式

针对于服务提供方,可以做物理层面的隔离。即每一个服务乃至其数据库,单独给一个服务器部署。这样某个服务出现故障,也不会相互影响。这里就突出了docker的好处,隔离强,可移植,轻量高效,每个docker容器都相当于一台服务器。

服务调用方隔离方式(也可以叫资源隔离)

针对于服务调用方,如果不做隔离会出现以下情况。
在这里插入图片描述
一个请求过来,占用支付服务中的Tomcat的一个线程。然后,该线程去顺序调用订单服务和库存服务!如果库存服务出现问题,Tomcat的线程就一直卡在那,无法返回!与此同时,页面上源源不断的有请求过来,会把Tomcat里头的线程池资源全部消耗完毕!对于后面的请求,Tomcat就无法响应!

因此,如果不针对被调服务做服务隔离,一个被调服务出问题,就将导致调用方服务不可用!

避免说对某一个依赖服务的调用,因为依赖服务的接口调用的延迟或者失败,导致服务所有的线程资源全部耗费在这个服务的接口调用上,导致调用方服务不可用,崩溃,蔓延。

而针对于这种调用方隔离的方式有两种,多个依赖服务的调用分别隔离到各自自己的资源池内。一种是线程池隔离,一种是信号量隔离。

线程池隔离(ThreadPool)

给每个微服务都初始化出一个线程池。
如下图所示,给订单服务和库存服务都初始化出一个线程池,不使用Tomcat线程池中的线程直接调用,而是用相应线程池中的线程去调用!如果库存服务不可用了,库存服务线程池会被迅速塞满,此时后面进来的新请求发现库存服务线程池满啦,就不去调库存服务,直接返回!

在这里插入图片描述

信号量隔离(semaphore)

每次调用线程,当前请求通过计数信号量进行限制,当信号大于了最大请求数(maxConcurrentRequests)时,进行限制,调用fallback接口快速返回。信号量的调用是同步的,所有的请求都将经过信号队列的计数器。
在这里插入图片描述

每次调用都得阻塞调用方的线程,直到结果返回。这样就导致了无法对访问做超时(只能依靠调用协议超时,无法主动释放)

Hystrix中的实现

总结对比:

隔离方式 是否支持超时 是否支持熔断 隔离原理 是否是异步调用 资源消耗
线程池隔离 支持,可直接返回 支持,当线程池到达maxSize后,再请求会触发fallback接口进行熔断 每个服务单独用线程池 可以是异步,也可以是同步。看调用的方法 大,大量线程的上下文切换,容易造成机器负载高
信号量隔离 不支持,如果阻塞,只能通过调用协议(如:socket超时才能返回) 支持,当信号量达到maxConcurrentRequests后。再请求会触发fallback 通过信号量的计数器 同步调用,不支持异步 小,只是个计数器

已经实现的技术有Hytrix,Sentinel,Resilience4j,zuul等等。具体如何使用,根据业务需求来决定。Resilience4j只提供信号量隔离。

两种分别的应用场景

线程池:适合绝大多数的场景,线程池资源隔离一般用于对依赖服务的网络请求的调用和访问,timeout这种问题。每个command运行在一个线程中,限流是通过线程池的大小进行控制的。

信号量适合对内部的一些比较复杂的业务逻辑的访问,但是像这种访问,系统内部的代码其实不涉及任何的网络请求。那么只要做信号量的普通限流就可以了,因为不需要去捕获timeout类似的问题,算法+数据结构的效率不是太高,并发量突然太高,因为这里稍微耗时一些,导致很多线程卡在这里的话,不太好,所以进行一个基本的资源隔离和访问,避免内部复杂的低效率的代码,导致大量的线程被hang住。command是运行在调用线程中,但是通过信号量的容量来进行限流。

6.什么是SpringCloud

SpringCloud 是给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包

基于SpringBoot提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型中立的开源组件。

SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等,它们都可以用SpringBoot的开发风格做到一键启动和部署。

所以

SpringCloud=分布式微服务架构下的一站式解决方案,
是各个微服务架构落地技术的集合体,俗称微服务全家桶

7.SpringBoot 和 SpringCloud的关系

  • SpringBoot专注于快速方便的开发单个个体微服务。

  • SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,
    为各个微服务之间提供,配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等集成服务

  • SpringBoot专注于快速、方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。

  • SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系.

8.SpringCloud 与Dubbo的区别

目前成熟的互联网架构(分布式+服务治理Dubbo)

相同点:
SpringCloud 和Dubbo可以实现RPC远程调用框架,可以实现服务治理。

不同点:

1.组件的不同

SpringCloud是一套目前比较网站微服务框架了,整合了分布式常用解决方案遇到了问题。
注册中心Eureka、负载均衡器Ribbon ,客户端调用工具Rest和Feign,分布式配置中心Config,服务保护Hystrix,网关Zuul Gateway ,服务链路Zipkin,消息总线Bus等。

Dubbo内部实现功能没有SpringCloud强大(全家桶),只是实现服务治理,缺少分布式配置中心、网关、链路、总线等,如果需要用到这些组件,需要整合其他框架。

2.通信方式的不同

SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。

3.比喻

Spring Cloud的功能比DUBBO更加强大,涵盖面更广,而且作为Spring的拳头项目,它也能够与Spring Framework、Spring Boot、Spring Data、Spring Batch等其他Spring项目完美融合。就像品牌机,在Spring Source的整合下,做了大量的兼容性测试

用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了

功能 Dubbo Spring Cloud
服务注册与发现中心 ZooKeeper Spring Cloud Netflix Eureka、ZooKeeper
服务调用方式 RPC REST API
服务网关 Spring Cloud Netflix Zuul
断路器 不完善 Spring Cloud Netflix Hystrix
分布式配置 Spring Cloud Config
服务跟踪 Spring Cloud Sleuth
消息总线 Spring Cloud Bus
数据流 Spring Cloud Stream
批量任务 Spring Cloud Task
发布了58 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_32020035/article/details/104949934