搭建框架需要工具默认基于 maven 的分布式工程,我们知道在一个项目中,多个微服务是属于同一个工程,只不过是提供不同的服务而已,因此使用 maven 分布式工程来搭建微服务架构。搭建基于 maven 分布式的 Spring Cloud 微服务工程架构。这个是目前比较流行的搭建方式,其实我们可以这样想,服务从原始的RPC开始,至今spring cloud和web service,再到最后soa服务治理。服务的调用拙见完善,目前市场上出现的服务框架dubbo和spring cloud比较流行。
1.dubbo架构
2.spring cloud内部组成:
实际上,Spring Cloud是一个全家桶式的技术栈,包含了很多组件。本文先从其最核心的几个组件入手,来剖析一下其底层的工作原理。也就是Eureka、Ribbon、Feign、Hystrix、Zuul这几个组件。
先来给大家说一个业务场景,假设咱们现在开发一个跨境电商网站,要实现支付订单的功能,基本流程如下:
以上业务流程我们需要有订单服务(order)、库存服务(sku)、仓储服务(erp)、积分服务(point)。整个流程的思路如下: 即使没有用户登录我们然后可以这样操作,只是到添加购物车的时候,我们需要提示用户去登录或者去注册。也是购物车的实现原理
至此,整个支付订单的业务流程结束
下图随便找张支付流程图,清晰表明了各服务间的调用过程:
重点一:这里最重要的是我们分布式事务管理。针对springboot搭建的项目我们选择 lcn分布式框架进行事务管理。
重点二:针对系统而言我们可能有推送服务,我们建议使用 rabbitmq消息队列进行推送服务和消息通知。
重点三:里面的服务调用通用异步机制,
下面我们就开始讲解Spring Cloud微服务架构,在项目中这几个组件如何相互协作,各自发挥的作用以及其背后的原理。
eureka解决的问题服务如何调用,就上面 订单服务想要调用库存服务、仓储服务,或者积分服务,怎么调用呢?
第一个问题:订单服务压根不知道库存服务在哪台机器上,发起一个请求,都不知道发送给谁。
问题解决方案:Spring Cloud Eureka完美解决问题。Eureka是微服务架构中的注册中心,专门负责服务的注册与发现。
下面就是eureka工作的整个流程:
重要一:库存服务、仓储服务、积分服务中都有一个Eureka Client组件
这个组件专门负责将这个服务的信息注册到Eureka Server中。说白了,就是告诉Eureka Server,自己在哪台机器上,监听着哪个端口。而Eureka Server是一个注册中心,里面有一个注册表,保存了各服务所在的机器和端口号
订单服务里也有一个Eureka Client组件,这个Eureka Client组件会找Eureka Server问一下:库存服务在哪台机器啊?监听着哪个端口啊?仓储服务呢?积分服务呢?然后就可以把这些相关信息从Eureka Server的注册表中拉取到自己本地缓存起来。
这时如果订单服务想要调用库存服务,不就可以找自己本地的Eureka Client问一下库存服务在哪台机器?监听哪个端口吗?收到响应后,紧接着就可以发送一个请求过去,调用库存服务扣减库存的那个接口!同理,如果订单服务要调用仓储服务、积分服务,也是如法炮制。
总结:
服务各自知道对方的端口和ip后。我们就需要去请求,调用这些服务,这里如果不用feign也可以自定义一个http协议封装一下。
问题一:各个服务之间如何建立网络连接呢?
例如:
解决办法:Feign提供了优雅的解决方案。
例如:订单服务调用库存服务的代码
feign为我们省去了底层的建立连接、构造请求、解析响应的代码,直接就是用注解定义一个 FeignClient接口,然后调用那个接口就可以了。Feign Client会在底层根据自定义的注解,跟指定的服务建立连接、构造请求、发起靕求、获取响应、解析响应。
Feign实现原理:Feign的一个关键机制就是使用了动态代理。
如下
下面重点解决分布式服务的解决方案:
上面我们解决了,
1.服务各个之间的发现和注册,
2.以及各个服务之间网络通信问题。
下面我们看看分布式各个服务之间如何发现的。
如果库存服务部署在了5台机器上,端口一致,如下所示:
Feign怎么知道该请求哪台机器呢?
我们可以使用 Spring Cloud Ribbon,它的作用是负载均衡,会帮我们在每次请求时选择一台机器,均匀的把请求分发到各个机器上
Ribbon特点:
总结三者工作调用流程:Ribbon是和Feign以及Eureka紧密协作,完成工作的,具体流程如下:
如下图:
在微服务架构里,一个系统会有很多的服务。如果其中一个服务挂掉,不能影响其他服务的正常调用。就此案例来说:订单服务如果调用三个服务。现在假设订单服务自己最多只有50个线程可以处理请求。在这其中,积分服务如果挂了,每次订单服务调用积分服务的时候,都会卡住一段时间等候处理,然后抛出—个超时异常。浪费时间。
上面这个,就是微服务架构中恐怖的服务雪崩问题,如下图所示:
一般而言,我们各个服务都应该设置成异步多线程调用的。
如上图,如果其中多服务互相调用,要是不做任何保护的话,某一个服务挂了,就会引起连锁反应,导致别的服务也挂。比如积分服务挂了,会导致订单服务的线程全部卡在请求积分服务这里,没有一个线程可以工作,瞬间导致订单服务也挂了,别人请求订单服务全部会卡住,无法响应。
这就是里面没有加入消息队列机制处理。如果加入消息队列机制,我们就会发现服务之间出现异常互不影响。这里面还没有我们说的,缓存机制。也可以加进去。
就单单业务来看:支付订单的时候,只要把库存扣减了,然后通知仓库发货就算功能实现了
解决方案:
一,加入消息队列机制。异步执行。
二。使用Hystrix。因为Hystrix是隔离、熔断以及降级的一个框架。
Hystrix实现原理:
Hystrix会搞很多个小小的线程池,比如订单服务请求库存服务是一个线程池,请求仓储服务是一个线程池,请求积分服务是一个线程池。每个线程池里的线程就仅仅用于请求那个服务。
打个比方:现在很不幸,积分服务挂了,会咋样?
当然会导致订单服务里那个用来调用积分服务的线程都卡死不能工作了啊!但由于订单服务调用库存服务、仓储服务的这两个线程池都是正常工作的,所以这两个服务不会受到任何影响。
这个时候如果别人请求订单服务,订单服务还是可以正常调用库存服务扣减库存,调用仓储服务通知发货。只不过调用积分服务的时候,每次都会报错。但是如果积分服务都挂了,每次调用都要去卡住几秒钟干啥呢?有意义吗?当然没有!所以我们直接对积分服务熔断不就得了,比如在5分钟内请求积分服务直接就返回了,不要去走网络请求卡住几秒钟,这个过程,就是所谓的熔断!
如果积分服务挂了你就熔断,道理说不通,不能直接就返回!,还需要降级:每次调用积分服务,你就在数据库里记录一条消息,说给某某用户增加了多少积分,因为积分服务挂了,导致没增加成功!这样等积分服务恢复了,你可以根据这些记录手工加一下积分。这个过程,就是所谓的降级。
梳理一下Hystrix隔离、熔断和降级的全流程:
这个处理方案就比如我们soa治理差不多,只不过,那是dubbo经常用的框架,我们这是springcloud用的框架。
处理机制都差不多。
上面我们几乎把管理搭建springcloud分布式常用的框架说完了,下面我们看看网络分片问题。
Zuul概念:Zuul,就是微服务网关。这个组件是负责网络路由的。
zuul工作流程:
问题一;
假设我们后台部署了上百个服务,如果我们系统是前后端分离。那么前端开发人员如何调用我们这几百个服务呢?
比如:前端开发人员要请求一下库存服务,我们不可能让人家记着这服务的名字叫做inventory-service?部署在5台机器上?就算人家肯记住这一个,你后台可有几百个服务的名称和地址呢?难不成人家请求一个,就得记住一个?
解决方案:
一般微服务架构中都必然会设计一个网关在里面,像android、ios、pc前端、微信小程序、H5等等,不用去关心后端有几百个服务,就知道有一个网关,所有请求都往网关走,网关会根据请求中的一些特征,将请求转发给后端的各个服务。而且有一个网关之后,还有很多好处,比如可以做统一的降级、限流、认证授权、安全,等等。
总结,上述几个Spring Cloud核心组件,在微服务架构中,分别扮演的角色:
以上就是我们通过一个电商业务场景,阐述了Spring Cloud微服务架构几个核心组件的在现实项目中的实现原理。
Spring Cloud的5个核心组件通过一张图串联起来,包括底层的架构原理: