百度
360搜索
搜狗搜索

springcloud原理和机制,SpringCloud系列-2Ribbon简介与应用详细介绍

本文目录一览: springcloud原理是什么?

springcloud原理如下和组成部分:
Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉取注册表,从而知道其他服务在哪里
Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从一个服务的多台机器中选择一台
Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
Hystrix:发起请求是通过Hystrix的线程池来走的,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题
Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务
Spring Cloud是一系列微软服务框架的有序集合。
注意:
集合与集合的元素是两个不同的概念,教科书中是通过描述给出的,这与平面几何中的点与直线的概念类似。
集合中的元素具有确定性、互异性和无序性({a,b}与{b,a}表示同一个集合)。集合具有两方面的意义,即:凡是符合条件的对象都是它的元素;只要是它的元素就必须符号条件。

SpringCloud微服务组件介绍

Spring Cloud是一系列框架的有序集合(框架集),他利用Spring Boot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等。
SpringCloud利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,SpringCloud为开发人员提供了快速构建分布式系统的一些工具,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等,它们都可以用SpringBoot的开发风格做到一键启动和部署。
SpringCloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包
下面是Spring Cloud的整体架构图:
注册中心可以说是微服务架构中的“通讯录”,他记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其他服务时,就在这里找到对应服务的地址,进行调用。
注册中心的主要作用
Ribbon是Netflix发布的一个负载均衡,有助于控制HTTP和TCP客户端行为。在Spring Cloud中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
在Spring Cloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务。
Ribbon原理
几种负载均衡策略:
Hystrix是Netflix开源的一款容错框架,包含常用的容错方法。在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等。Hystrix利用熔断、线程池隔离、信号量隔离、降级回退等方法来处理依赖隔离,使系统变得高可用。
Hystrix主要提供了以下几种容错方法:
Spring Cloud Gateway是Spring官方推出的服务网关的实现框架,相对于服务网关的概念有点类似于传统的反向代理服务器(如nginx),但反向代理一般都只是做业务无关的转发请求,而服务网关与服务的整合程度更高,可以看作也是整个服务体系的组成部分,通过过滤器等组件可以在网关中集成一些业务处理的操作(比如权限认证等)。
核心功能:
Spring Cloud Stream是一个用来为微服务应用构建消息驱动能力的框架。
特点: 屏蔽底层 MQ 实现细节,Spring Cloud Stream 的 API 是统一的。如果从 Kafka 切到 RocketMQ,可以直接修改配置。 与 Spring 生态整合更加方便。Spring Cloud Data Flow的流计算都是基于 Spring Cloud Stream;Spring Cloud Bus 消息总线内部也是用的 Spring Cloud Stream。
配置中心功能:
分布式链路追踪,就是将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时,请求具体到达哪台机器上、每个服务节点的请求状态等等。
分布式链路追踪方案:

SpringCloud

微服务的优点:

1易于开发和维护,只需要关注每个服务的单独业务即可,不需要关心其他

2启动较快

3局部修改容易部署

4技术栈不受限

5按需伸缩

微服务的缺点:

1运维成本较高

3分布式复杂

4接口调整成本高

SpringCloud 的特点:

1约定优于配置

2开箱即用、快速启动

3适用于各种环境

4轻量级的组件,比如 服务发现组件 Eureka? ribbon? zuul

5组件的支持很丰富,功能很齐全 包含:配置中心,注册中心,智能路由

6选型中立 比如服务发现组件,不限制必须使用某一种,例如 Eureka,Zookeeper,Consul

Eureka作为服务注册中心,Eureka比Zookeeper好在哪里

著名的CAP理论指出,在一个分布式系统中, 一致性 (Consistency)、 可用性 (Availability)、分区容忍性(Partition tolerance 分区相当于对通信的时限要求)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

一致性(C):在 分布式系统 中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

可用性(A):在集群中一部分节点故障后, 集群 整体是否还能响应 客户端 的读写请求。(对数据更新具备高可用性)

分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。

由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。

传统分布式的模式的缺点

传统式是通过restTemplate硬编码硬性指定ip和端口一旦ip和端口改变name系统直接瘫痪,这个ip和端口改变是不可避免的。

springcloud是通过eureka作为服务的发现也就是注册中心就可以解决这个问题

eureka的集群:

? 就是多个服务之间互相依赖你中有我我中有你

失效剔除和自我保护

默认每间隔60s服务就会通过心跳检测,检测超过90s没有响应的服务就会剔除,这时候在eureka的面板上就会有提示。

Ribbin 负载均衡

工作原理:

第一步先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略

负载均衡的侧率:

1默认轮训,

2,随机

3,根据响应速度

开启默认负载均衡只需要价格注解LoadBalanced

@Bean

@LoadBalanced

public RestTemplate restTemplate() {

? ? return new RestTemplate(new OkHttp3ClientHttpRequestFactory());

}

修改调用方式,不再手动获取ip和端口,而是直接通过服务名称调用:

「SpringCloud原理」Ribbon核心组件以及运行原理万字源码剖析

大家好,本文我将继续来剖析SpringCloud中负载均衡组件Ribbon的源码。本来我是打算接着OpenFeign动态代理生成文章直接讲Feign是如何整合Ribbon的,但是文章写了一半发现,如果不把Ribbon好好讲清楚,那么有些Ribbon的细节理解起来就很困难,所以我还是打算单独写一篇文章来剖析Ribbon的源码,这样在讲Feign整合Ribbon的时候,我就不再赘述这些细节了。好了,话不多说,直接进入主题。

这是个很简单的东西,就是服务实例数据的封装,里面封装了服务实例的ip和端口之类的,一个服务有很多台机器,那就有很多个Server对象。

ServerList是个接口,泛型是Server,提供了两个方法,都是获取服务实例列表的,这两个方法其实在很多实现类中实现是一样的,没什么区别。这个接口很重要,因为这个接口就是Ribbon获取服务数据的来源接口,Ribbon进行负载均衡的服务列表就是通过这个接口来的,那么可以想一想是不是只要实现这个接口就可以给Ribbon提供服务数据了?事实的确如此,在SpringCloud中,eureka、nacos等注册中心都实现了这个接口,都将注册中心的服务实例数据提供给Ribbon,供Ribbon来进行负载均衡。

通过名字也可以知道,是用来更新服务注册表的数据,他有唯一的实现,就是PollingServerListUpdater,这个类有一个核心的方法,就是start,我们来看一下start的实现。

通过这段方法我们可以看出,首先通过isActive.compareAndSet(false, true)来保证这个方法只会被调用一下,然后封装了一个Runnable,这个Runnable干了一件核心的事,就是调用传入的updateAction的doUpdate方法,然后将Runnable扔到了带定时调度功能的线程池,经过initialDelayMs(默认1s)时间后,会调用一次,之后都是每隔refreshIntervalMs(默认30s)调用一次Runnable的run方法,也就是调用updateAction的doUpdate方法。

所以这个类的核心作用就是每隔30s会调用一次传入的updateAction的doUpdate方法的实现,记住这个结论。

IRule是负责负载均衡的算法的,也就是真正实现负载均衡获取一个服务实例就是这个接口的实现。比如说实现类RandomRule,就是从一堆服务实例中随机选取一个服务实例。

就是一个配置接口,有个默认的实现DefaultClientConfigImpl,通过这个可以获取到一些配置Ribbon的一些配置。

这个接口的作用,对外主要提供了获取服务实例列表和选择服务实例的功能。虽然对外主要提供获取服务的功能,但是在实现的时候,主要是用来协调上面提到的各个核心组件的,使得他们能够协调工作,从而实现对外提供获取服务实例的功能。

这个接口的实现有好几个实现类,但是我讲两个比较重要的。

BaseLoadBalancer

核心属性

allServerList:缓存了所有的服务实例数据

upServerList:缓存了能够使用的服务实例数据。

rule:负载均衡算法组件,默认是RoundRobinRule

核心方法

setRule:这个方法是设置负载均衡算法的,并将当前这个ILoadBalancer对象设置给IRule,从这可以得出一个结论,IRule进行负载均衡的服务实例列表是通过ILoadBalancer获取的,也就是 IRule 和 ILoadBalancer相互引用。setRule(rule)一般是在构造对象的时候会调用。

chooseServer:就是选择一个服务实例,是委派给IRule的choose方法来实现服务实例的选择。

BaseLoadBalancer这个实现类总体来说,已经实现了ILoadBalancer的功能的,所以这个已经基本满足使用了。

说完BaseLoadBalancer这个实现类,接下来说一下DynamicServerListLoadBalancer实现类。DynamicServerListLoadBalancer继承自BaseLoadBalancer,DynamicServerListLoadBalancer主要是对BaseLoadBalancer功能进行扩展。

DynamicServerListLoadBalancer

成员变量

serverListImpl:上面说过,通过这个接口获取服务列表

filter:起到过滤的作用,一般不care

updateAction:是个匿名内部类,实现了doUpdate方法,会调用updateListOfServers方法

serverListUpdater:上面说到过,默认就是唯一的实现类PollingServerListUpdater,也就是每个30s就会调用传入的updateAction的doUpdate方法。

这不是巧了么,serverListUpdater的start方法需要一个updateAction,刚刚好成员变量有个updateAction的匿名内部类的实现,所以serverListUpdater的start方法传入的updateAction的实现其实就是这个匿名内部类。

那么哪里调用了serverListUpdater的start方法传入了updateAction呢?是在构造的时候调用的,具体的调用链路是调用 restOfInit -> enableAndInitLearnNewServersFeature(),这里就不贴源码了

所以,其实DynamicServerListLoadBalancer在构造完成之后,默认每隔30s中,就会调用updateAction的匿名内部类的doUpdate方法,从而会调用updateListOfServers。所以我们来看一看 updateListOfServers 方法干了什么。

这个方法实现很简单,就是通过调用 ServerList 的getUpdatedListOfServers获取到一批服务实例数据,然后过滤一下,最后调用updateAllServerList方法,进入updateAllServerList方法。

其实很简单,就是调用每个服务实例的setAlive方法,将isAliveFlag设置成true,然后调用setServersList。setServersList这个方法的主要作用是将服务实例更新到内部的缓存中,也就是上面提到的allServerList和upServerList,这里就不贴源码了。

其实分析完updateListOfServers方法之后,再结合上面源码的分析,我们可以清楚的得出一个结论,那就是默认每隔30s都会重新通过ServerList组件获取到服务实例数据,然后更新到BaseLoadBalancer缓存中,IRule的负载均衡所需的服务实例数据,就是这个内部缓存。

从DynamicServerListLoadBalancer的命名也可以看出,他相对于父类BaseLoadBalancer而言,提供了动态更新内部服务实例列表的功能。

为了便于大家记忆,我画一张图来描述这些组件的关系以及是如何运作的。

说完一些核心的组件,以及他们跟ILoadBalancer的关系之后,接下来就来分析一下,ILoadBalancer是在ribbon中是如何使用的。

ILoadBalancer是一个可以获取到服务实例数据的组件,那么服务实例跟什么有关,那么肯定是跟请求有关,所以在Ribbon中有这么一个抽象类,AbstractLoadBalancerAwareClient,这个是用来执行请求的,我们来看一下这个类的构造。

通过上面可以看出,在构造的时候需要传入一个ILoadBalancer。

AbstractLoadBalancerAwareClient中有一个方法executeWithLoadBalancer,这个是用来执行传入的请求,以负载均衡的方式。

这个方法构建了一个LoadBalancerCommand,随后调用了submit方法,传入了一个匿名内部类,这个匿名内部类中有这么一行代码很重要。

这行代码是根据给定的一个Server重构了URI,这是什么意思呢?举个例子,在OpenFeign那一篇文章我说过,会根据服务名拼接出类似 http:// ServerA 的地址,那时是没有服务器的ip地址的,只有服务名,假设请求的地址是 http:// ServerA/api/sayHello ,那么reconstructURIWithServer干的一件事就是将ServerA服务名替换成真正的服务所在的机器的ip和端口,假设ServerA所在的一台机器(Server里面封装了某台机器的ip和端口)是192.168.1.101:8088,那么重构后的地址就变成 http:// 192.168.1.101:8088/api/ sayHello ,这样就能发送http请求到ServerA服务所对应的一台服务器了。

之后根据新的地址,调用这个类中的execute方法来执行请求,execute方法是个抽象方法,也就是交给子类实现,子类就可以通过实现这个方法,来发送http请求,实现rpc调用。

那么这台Server是从获取的呢?其实猜猜也知道,肯定是通过ILoadBalancer获取的,因为submit方法比较长,这里我直接贴出submit方法中核心的一部分代码

就是通过selectServer来选择一个Server的,selectServer我就不翻源码了,其实最终还是调用ILoadBalancer的方法chooseServer方法来获取一个服务,之后就会调用上面的说的匿名内部类的方法,重构URI,然后再交由子类的execut方法来实现发送http请求。

所以,通过对AbstractLoadBalancerAwareClient的executeWithLoadBalancer方法,我们可以知道,这个抽象类的主要作用就是通过负载均衡算法,找到一个合适的Server,然后将你传入的请求路径 http:// ServerA/api/sayHello 重新构建成类似 http:// 192.168.1.101:8088/api/ sayHello 这样,之后调用子类实现的execut方法,来发送http请求,就是这么简单。

到这里其实Ribbon核心组件和执行原理我就已经说的差不多了,再来画一张图总结一下

说完了Ribbon的一些核心组件和执行原理之后,我们再来看一下在SpringCloud环境下,这些组件到底是用的哪些实现,毕竟有写时接口,有的是抽象类。

Ribbon的自动装配类:RibbonAutoConfiguration,我拎出了核心的源码

RibbonAutoConfiguration配置类上有个@RibbonClients注解,接下来讲解一下这个注解的作用

SpringClientFactory是不是感觉跟OpenFeign中的FeignContext很像,其实两个的作用是一样的,SpringClientFactory也继承了NamedContextFactory,实现了配置隔离,同时也在构造方法中传入了每个容器默认的配置类RibbonClientConfiguration。至于什么是配置隔离,我在OpenFeign那篇文章说过,不清楚的小伙伴可以后台回复feign01即可获得文章链接。

配置优先级问题

优先级最低的就是FeignContext和SpringClientFactory构造时传入的配置类

至于优先级怎么来的,其实是在NamedContextFactory中createContext方法中构建AnnotationConfigApplicationContext时按照配置的优先级一个一个传进去的。

RibbonClientConfiguration提供的默认的bean

接下来我们看一下RibbonClientConfiguration都提供了哪些默认的bean

配置类对应的bean,这里设置了ConnectTimeout和ReadTimeout都是1s中。

IRule,默认是ZoneAvoidanceRule,这个Rule带有过滤的功能,过滤哪些不可用的分区的服务(这个过滤可以不用care),过滤成功之后,继续采用线性轮询的方式从过滤结果中选择一个出来。至于这个propertiesFactory,可以不用管,这个是默认读配置文件的中的配置,一般不设置,后面看到都不用care。

至于为什么容器选择NacosServerList而不是ConfigurationBasedServerList,主要是因为NacosRibbonClientConfiguration这个配置类是通过@RibbonClients导入的,也就是比SpringClientFactory导入的RibbonClientConfiguration配置类优先级高。

ServerListUpdater,就是我们剖析的PollingServerListUpdater,默认30s更新一次BaseLoadBalancer内部服务的缓存。

那么在springcloud中,上图就可以加上注册中心。

三、总结

本文剖析了Ribbon这个负载均衡组件中的一些核心组件的源码,并且将这些组件之间的关系一一描述清楚,同时也剖析了在发送请求的时候是如何通过ILoadBalancer获取到一个服务实例,重构URI的过程。希望本篇文章能够让你知道Ribbon是如何工作的。

SpringCloud整体构架设计介绍

SpringClound整体核心架构只有一点:Rest服务,也就是说在整个SpringCloud配置过程之中,所有的配置处理都是围绕着Rest完成的,在这个Rest处理之中,一定要有两个端:服务的提供者(Provider)、服务的消费者(Consumer)。
SpringClound整体核心架构只有一点:Rest服务,也就是说在整个SpringCloud配置过程之中,所有的配置处理都是围绕着Rest完成的,在这个Rest处理之中,一定要有两个端:服务的提供者(Provider)、服务的消费者(Consumer),所以对于整个SpringCloud基础的结构就如下所示:
既然SpringCloud的核心是Restful结构,那么如果要想更好的去使用Rest这些微服务还需要考虑如下几个问题。
1、所有的微服务地址一定会非常的多,所以为了统一管理这些地址信息,也为了可以及时的告诉用户哪些服务不可用,所以应该准备一个分布式的注册中心,并且该注册中心应该支持有HA机制,为了高速并且方便进行所有服务的注册操作,在SpringCloud里面提供有一个Eureka的注册中心。
对于整个的WEB端的构架(SpringBoot实现)可以轻松方便的进行WEB程序的编写,而后利用Nginx或Apache实现负载均衡处理,但是你WEB端出现了负载均衡,那么业务端呢?应该也提供有多个业务端进行负载均衡。那么这个时候就需要将所有需要参与到负载均衡的业务端在Eureka之中进行注册。
在进行客户端使用Rest架构调用的时候,往往都需要一个调用地址,即使现在使用了Eureka作为注册中心,那么它也需要有一个明确的调用地址,可是所有的操作如果都利用调用地址的方式来处理,程序的开发者最方便应用的工具是接口,所以现在就希望可以将所有的Rest服务的内容以接口的方式出现调用,所以它又提供了一个Feign技术,利用此技术可以伪造接口实现。
在进行整体的微架构设计的时候由于牵扯的问题还是属于RPC,所以必须考虑熔断处理机制,实际上所有的熔断就好比生活之中使用保险丝一样,有了保险丝在一些设备出现了故障之后依然可以保护家庭的电器可以正常使用,如果说现在有若干的微服务,并且这些微服务之间可以相互调用,例如A微服务调用了B微服务,B微服务调用了C微服务。
如果在实际的项目设计过程之中没有处理好熔断机制,那么就会产生雪崩效应,所以为了防止这样的问题出现,SpringCloud里面提供有一个Hystrix熔断处理机制,以保证某一个微服务即使出现了问题之后依然可以正常使用。
通过Zuul的代理用户只需要知道指定的路由的路径就可以访问指定的微服务的信息,这样更好的提现了java中的“key=value”的设计思想,而且所有的微服务通过zuul进行代理之后也更加合理的进行名称隐藏。
、在SpringBoot学习的时候一直强调过一个问题:在SpringBoot里面强调的是一个“零配置”的概念,本质在于不需要配置任何的配置文件,但是事实上这一点并没有完全的实现,因为在整个在整体的实际里面,依然会提供有application.yml配置文件,那么如果在微服务的创建之中,那么一定会有成百上千个微服务的信息出现,于是这些配置文件的管理就成为了问题。例如:现在你突然有一天你的主机要进行机房的变更,所有的服务的IP地址都可能发生改变,这样对于程序的维护是非常不方便的,为了解决这样的问题,在SpringCloud设计的时候提供有一个SpringCloudConfig的程序组件,利用这个组件就可以直接基于GIT或者SVN来进行配置文件的管理。
在整体设计上SpringCloud更好的实现了RPC的架构设计,而且使用Rest作为通讯的基础,这一点是他的成功之处,由于大量的使用了netflix公司的产品技术,所以这些技术也有可靠的保证。

SpringCloud系列-2Ribbon简介与应用

阅读更多 >>>  linux启动停止服务命令行

负载均衡:建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡说白了其实就是伴随着微服务架构的诞生的产物;过去的单体架构,前端页面发起请求,然后后台接收请求直接处理,这个时候不存在什么负载均衡;但是随着单体架构向微服务架构的演变,每个后台服务可能会部署在多台服务器上面,这个时候页面请求进来,到底该由哪台服务器进行处理呢?所以得有一个选择,而这个过程就是负载均衡;同时选择的方案有很多种,例如随机挑选一台或者一台一台轮着来,这就是负载均衡算法。
也可以通过例子来帮助自己记忆,就好比古代皇帝翻牌子,最开始皇帝只有一个妃子,那不存在翻牌子这回事,再怎么翻也只能是这一个妃子侍寝。但是随着妃子多了,就得有选择了,不能同时让所有妃子一起侍寝。
工作原理图如下:
HTTP重定向服务器是一台普通的应用服务器,其唯一个功能就是根据用户的HTTP请求计算出一台真实的服务器地址,并将该服务器地址写入HTTP重定向响应中返回给用户浏览器。用户浏览器在获取到响应之后,根据返回的信息,重新发送一个请求到真实的服务器上。DNS服务器解析到IP地址为192.168.8.74,即HTTP重定向服务器的IP地址。重定向服务器计根据某种负载均衡算法算出真实的服务器地址为192.168.8.77并返回给用户浏览器,用户浏览器得到返回后重新对192.168.8.77发起了请求,最后完成访问。
这种负载均衡方案的优点是比较简单,缺点是浏览器需要两次请求服务器才能完成一次访问,性能较差;同时,重定向服务器本身的处理能力有可能成为瓶颈,整个集群的伸缩性规模有限;因此实践中很少使用这种负载均衡方案来部署。
DNS(Domain Name System)是因特网的一项服务,它作为域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。人们在通过浏览器访问网站时只需要记住网站的域名即可,而不需要记住那些不太容易理解的IP地址。在DNS系统中有一个比较重要的的资源类型叫做主机记录也称为A记录,A记录是用于名称解析的重要记录,它将特定的主机名映射到对应主机的IP地址上。如果你有一个自己的域名,那么要想别人能访问到你的网站,你需要到特定的DNS解析服务商的服务器上填写A记录,过一段时间后,别人就能通过你的域名访问你的网站了。DNS除了能解析域名之外还具有负载均衡的功能,下面是利用DNS工作原理处理负载均衡的工作原理图:
由上图可以看出,在DNS服务器中应该配置了多个A记录,如: www.woshuaiqi.com IN A 192.168.8.75; www.woshuaiqi.com IN A 192.168.8.76; www.woshuaiqi.com IN A 192.168.8.77;
因此,每次域名解析请求都会根据对应的负载均衡算法计算出一个不同的IP地址并返回,这样A记录中配置多个服务器就可以构成一个集群,并可以实现负载均衡。上图中,用户请求www.woshuaiqi.com,DNS根据A记录和负载均衡算法计算得到一个IP地址192.168.8.77,并返回给浏览器,浏览器根据该IP地址,访问真实的物理服务器192.168.8.77。所有这些操作对用户来说都是透明的,用户可能只知道www.woshuaiqi.com这个域名。
DNS域名解析负载均衡有如下优点:
同时,DNS域名解析也存在如下缺点:
请求过程:
用户发来的请求都首先要经过反向代理服务器,服务器根据用户的请求要么直接将结果返回给用户,要么将请求交给后端服务器处理,再返回给用户。
反向代理负载均衡
优点:
缺点:
代码实现
由于不同的服务器配置不同,因此它们处理请求的能力也不同,给配置高的服务器配置相对较高的权重,让其处理更多的请求,给配置较低的机器配置较低的权重减轻期负载压力。加权轮询可以较好地解决这个问题。
1.思路
根据权重的大小让其获得相应被轮询到的机会。
可以根据权重我们在内存中创建一个这样的数组{s1,s2,s2,s3,s3,s3},然后再按照轮询的方式选择相应的服务器。
2.缺点:请求被分配到三台服务器上机会不够平滑。前3次请求都不会落在server3上。
Nginx实现了一种平滑的加权轮询算法,可以将请求平滑(均匀)的分配到各个节点上。
代码实现
代码实现
思路:这里我们是利用区间的思想,通过一个小于在此区间范围内的一个随机数,选中对应的区间(服务器),区间越大被选中的概率就越大。
已知:
s1:[0,1] s2:(1,3] s3 (3,6]
代码实现
代码实现
REST(Representational State Transfer)表象化状态转变(表述性状态转变),基于HTTP、URI、XML、JSON等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是Web服务的一种新的架构风格(一种思想)。
符合上述REST原则的架构方式称为RESTful
在Restful之前的操作: http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据 http://127.0.0.1/user/save POST 新增用户 http://127.0.0.1/user/update POST 修改用户信息 http://127.0.0.1/user/delete/1 GET/POST 删除用户信息
RESTful用法: http://127.0.0.1/user/1 GET 根据用户id查询用户数据 http://127.0.0.1/user POST 新增用户 http://127.0.0.1/user PUT 修改用户信息 http://127.0.0.1/user DELETE 删除用户信息
之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了query,新增的时候用了save,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.
幂等性:对同一REST接口的多次访问,得到的资源状态是相同的。
安全性:对该REST接口访问,不会使用服务器端资源的状态发生改变。
SpringMVC原生态的支持了REST风格的架构设计
所涉及到的注解:
---@RequestMapping ---@PathVariable ---@ResponseBody
传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。
定义一个简单的restful接口
使用RestTemplate访问该服务
从这个例子可以看出,使用restTemplate访问restful接口非常的 简单粗暴无脑 。(url, requestMap, ResponseBean.class)这三个参数分别代表 请求地址、请求参数、HTTP响应转换被转换成的对象类型。
RestTemplate方法的名称遵循命名约定,第一部分指出正在调用什么HTTP方法,第二部分指示返回的内容。本例中调用了restTemplate.postForObject方法,post指调用了HTTP的post方法,Object指将HTTP响应转换为您选择的 对象类型 。
RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。
实际上,由于Post 操作的非幂等性,它几乎可以代替其他的CRUD操作.
目前主流的负载方案分为以下两种:
Ribbon 是一个基于 HTTP和TCP的客户端负载均衡工具。通过 Spring Cloud 的封装,可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。
Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个 Spring Cloud 构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 来实现的(https://github.com/Netflix/ribbon)。
Ribbon主要提供:
Ribbon模块介绍:
与Nginx的对比
应用场景的区别:
1.先创建两个服务,用于负载均衡
Server 1 和Server2 的端口号要不同,不然起不来
Server 1接口如下:
Server 2接口如下:
启动类都是一样的,如下:
2.创建一个调用方来请求这个接口
引依赖包
配置启动类,并注入 RestTemplate
配置一下 application.properties,如下:
3.验证
再创建一个 测试方法来验证是否生效,放在test 目录下面,代码如下:
先启动 两个server ,然后在 测试 测试类 ,结果如下:
从结果可以看出实现了负载均衡,默认是 轮询策略,Client1和 clien2 依次调用。
Ribbon 中有两种和时间相关的设置,分别是请求连接的超时时间和请求处理的超时时间,设置规则如下:
Ribbon可以通过下面的配置项,来限制httpclient连接池的最大连接数量、以及针对不同host的最大连接数量。
负载均衡的核心,是通过负载均衡算法来实现对目标服务请求的分发。Ribbion中默认提供了7种负载均衡算法:
验证方法:
1.在BaseLoadBalancer.chooseServer()方法中加断点
2.在RandomRule.choose()方法增加断点,观察请求是否进入。
自定义负载均衡的实现主要分几个步骤:
ILoadBalancer 接口实现类做了以下的一些事情:
修改application.properties文件
在ribbon负载均衡器中,提供了ping机制,每隔一段时间,就会去ping服务器,由 com.netflix.loadbalancer.IPing 接口去实现。
单独使用ribbon,不会激活ping机制,默认采用DummyPing(在RibbonClientConfiguration中实例化),isAlive()方法直接返回true。
ribbon和eureka集成,默认采用NIWSDiscoveryPing(在EurekaRibbonClientConfiguration中实例化的),只有服务器列表的实例状态为up的时候才会为Alive。
IPing中默认内置了一些实现方法如下。
在网络通信中,有可能会存在由网络问题或者目标服务异常导致通信失败,这种情况下我们一般会做容错设计,也就是再次发起请求进行重试。
Ribbon提供了一种重试的负载策略:RetryRule,可以通过下面这个配置项来实现
由于在单独使用Ribbon的机制下,并没有开启Ping机制,所以所有服务默认是认为正常的,则这里并不会发起重试。如果需要演示重试机制,需要增加PING的判断。
1.引入依赖包
2.创建一个心跳检查的类
3.修改mall-portal中application.properties文件,添加自定义心跳检查实现,以及心跳检查间隔时间。
4.在goods-service这个模块中,增加一个心跳检查的接口
5.测试服务启动+停止,对于请求的影响变化。
LoadBalancer 是Spring Cloud自研的组件,支持WebFlux。
由于Ribbon停止更新进入维护状态,所以Spring Cloud不得不研发一套新的Loadbalancer机制进行替代。
1.引入Loadbalancer相关jar包
2.定义一个配置类,这个配置类通过硬编码的方式写死了goods-service这个服务的实例列表,代码如下
3.创建一个配置类,注入一个LoadBalancerClient
4.修改测试类
5.为了更好的看到效果,修改goods-service模块,打印每个服务的端口号码。

SpringCloud入门简述

微服务,是一个小型的服务,也是一种设计理念,将一个大型繁杂的系统拆分为多个小型的服务,进行独立部署,这些服务在独立进程中运行,通过特定的协议进行通信
优点:
缺点:
在服务通信性能上RPC更强,但是Rest更为灵活
SpringCloud是基于SpringBoot实现的微服务框架,为开发人员提供了很多快速构建分布式系统中常见模式的工具,包括配置管理、服务发现、断路器、智能路由、微代理,控制总线等。
Spring Cloud专注于为典型的用例提供良好的开箱即用体验,并为其他用例提供扩展性机制。
参考地址:
Eureka是Netflix开发的基于Rest的服务发现框架,SpringCloud基于此进行二次封装,实现服务的管理。
创建一个Eureka服务:https://www.cnblogs.com/william-m/p/15991511.html
如果没有Eureka,如何进行服务之间的调用?
使用Rest进行调用,先将RestTemplate注册到Bean,然后:
Eureka遵循的是AP原则,Eureka各个节点都是平等的,部分服务节点的下线不会影响正常服务的调用,只要该服务还剩下一个节点在线就可以进行正常的服务访问,即保证了服务可用,但是并不能保证查询到的信息是最新的。Zookeeper的CP原则与之不同,Zookeeper会有一个master节点来保证一致性,一旦master节点挂掉,剩余的节点会重新选举一个leader,而选择的过程需要时间,这期间会使得该服务瘫痪,所以需要满足高可用的话该情况是不能够容忍的。
Spring Cloud Ribbon是一个基于HTTP和TCP的 客户端负载均衡 工具,基于Netflix Ribbon实现,通过轮询、随机等算法选择一个可用服务。
目的:将用户的请求平摊的分配到多个服务上,实现高可用
最大区别:服务清单所存储的位置
客户端先发送请求到负载均衡服务器,然后由负载均衡服务器通过负载均衡算法,在众多可用的服务器之中选择一个来处理请求。
客户端自己维护一个可用服务器地址列表,在发送请求前先通过负载均衡算法选择一个将用来处理本次请求的服务器,然后再直接将请求发送至该服务器。
逻辑时序:RestTemplate发起请求 负载均衡器拦截器拦截 LoadBalanceClient获取ILoadBalance 获取服务列表 根据负载均衡器选择一个server 发起请求 记录调用信息
Ribbon基于HTTP和TCP客户端的负载均衡器可以自己构建HTTP请求,使用RestTemplate发送服务
Feign基于Ribbon进行改进,采用接口的方式,将需要调用的服务的方法定义成抽象方法
Consumer应用
启动类
为了调用Product应用服务的接口类
Product应用
controller
Hystrix是一个服务容错与保护的组件,用于 服务降级 、 服务熔断 、 服务限流 等等,能够保证在其中一个服务出现问题的时候,不会出现级联故障,防止雪崩,提高分布式服务的健壮性。
将某些服务停掉会i这不进行业务处理,释放资源来维持主要服务的功能。
应对服务雪崩的一种保险措施,是微服务的链路保护机制,是服务降级的一种特殊处理方式。
为了应对某个服务故障的情况,保证系统的整体可用性,熔断器会切断对该服务的请求,返回一个比较友好的错误响应,直到服务恢复正常
熔断机制的三种状态:
示例:
熔断:直接切断服务的调用
降级:牺牲非核心业务保证核心服务的正常
限流:服务访问量达到阈值后拒绝多余的调用
Zuul是一个微服务网关。网关:是一个网络系统的前置入口。也就是说要想访问一个有网关的网络系统请求相应的服务,需要先进入网关,然后路由到相应的服务。
通常是组成一个系统的微服务很多、或者有权限要求时需要用到网关。
Zuul提供一个过滤器,父类为ZuulFilter,用来过滤代理请求,提供额外的功能逻辑(这点类似于AOP),包括前置过滤、路由后过滤、后置过滤、异常过滤。
ZuulFilter包含的抽象方法:filterType、filterOrder、shouldFilter、run

当微服务众多的时候,想要管理各个服务的配置时过于繁杂,SpringCloud Config则可以用来对每个微服务的配置进行集中的管理。可以实现权限管控、灰度发布、版本管理、格式检验、安全配置等。
作用:
特点:
文章来自https://www.cnblogs.com/william-m/p/16153557.html

SpringCloud系列之Feign-5.@EnableFeignClients底层机制深度解析

@EnableFeignClients 源码比较值得一读,读完之后我们就学会了如何自己写一个注解并成功运用起来了
1.首先我们进入到 @EnableFeignClients注解里面可以看到这个注解里面声明了几个属性,通过名称大概可以看到比如basePackages应该是包路径,value的话应该是个basePackages别名,我们暂且不管,看下这个注解上面有个@Import的注解,点进去这个类来看一下
2.如图可以看到FeignClientsRegistrar这个类实现了三个Spring的类,根据名称大概猜一下,第一个应该是关于类定义注册的类,第二个第三个相信大家可能用过或者了解过就是Spring的Aware的一些类,大致就是加载资源或者环境变量的类
那我们看一下ImportBeanDefinitionRegistrar类里面是什么:
可以看到里面定义了一个方法,那么我们重新返回到FeignClientsRegistrar看下他是怎么实现这个方法的:
这个方法主要干了两件事儿,第一个方法是注册了默认的配置信息,第二个就是注册FeignClients,我们挨个一个个详细的看下:
到了较为详细的源码时候,如果看不懂,我们最好是打断点,当我们启动了Eureka-server,Eureka-client,然后再启动Feign-consumer的时候,断点就可以进来,我们可以看到一些传参的信息:
可以看到这个metedata里面的数据刚好就是在启动类上面的三个注解,并且还带有三个注解的属性信息,下面再给大家看下主类对照下就懂了:
然后我们继续往下面学习:
这一步就比较好理解了,我们拿到EnableFeignClients这个注解的属性信息。
然后就是拼接了一个名称,这个名称就是启动类的前端加了个default.而已,然后registry没变还是传参过来,defaultAttrs.get("defaultConfiguration")这个属性从刚刚断点来看也是空的。调用了一个registerClientConfiguration方法:
这个方法就是使用了Spring的BeanDefinitionBuilder把FeignClientSpecification这个bean给注册到Spring容器中了。
然后我们继续放回到主方法中看下一个方法:
这个方法根据名称registerFeignClients来说应该就是注册FeignClients类了,进入方法中,第一个scanner我们看下:
有点看不懂,没关系,猜一下,可能是扫描类的工具把。
我们继续王下面走,scanner加载了一个resourceLoader这个类,这个类我们可以查一下,他是Spring框架中与资源相关的类,然后再往下看
下面还是获取主类中的注解EnableFeignClients的属性信息
再往下,我们可以从图中看到在属性中获取关于clients的信息,但是没有,然后scanner就加了一个类似过滤器的东东,然后调用了getBasePackages的方法
下面我们看下getBasePackages方法:
看过之前的方法,这个方法就好理解了,首先就还是获取EnableFeignClients的所有属性信息,然后把值都给取出来,取得属性分别是value还是basePackages等关于包路径的属性值,如果都没有获取到,就获取一个默认的包路径
这个包路径断点可以看到就是主类的包路径,所以整体上看,这些逻辑就是首先看注解中有没有关于FeignClient的包路径信息,如果没有配置,那程序就准备从主程序所在的包路径下找所有的FeignClient了。
我们再详细看下:
然后继续看这个registerClientConfiguration方法:
这个方法我们之前看过就是把某个类加载到Spring中所以继续下一步,看registerFeignClient方法:
获取到这个FeignClient的所有属性之后,我们就进行数据处理,把属性信息都赋值给definition
这个方法表示我们把这个类以 按照类型注入 作为属性,然后
这块逻辑就是为了防止两个有同一个父类的FeignClient出现问题所做的,我们应该都遇到过一个问题就是 使用 @Autowire注入类的时候发现报错,说是有两个类不知道注入哪一个,而如果其中一个有@primary注解的话,spring是会优先注入这个类的。
下面就没什么了,直到最后执行了
整个@EnableFeignClients的实现到此执行完毕,这个注解的源码相对来说看起来算是比较清晰明了了,而且对于我们如果有做一个新注解的需求的话,完全可以参照着做,非常具有模板意义。

阅读更多 >>>  物联网时代我能干什么

SpringCloud + Zookeeper + Feign整合及Feign原理

Spring Cloud 与 Zookeeper的整合只需要添加相关的starter依赖和增加相关注解即可完成。

pom.xml 如下:

bootstrap.yml 如下:

最后开启服务的注册与发现

service 和controller实现

笔者加入了swagger,如果需要只需加入如下依赖和配置:

至此,spring cloud与zookeeper的整合就完成了,调用结果如下:

为了测试与Feign的整合,再构建一个消费者:与上述构建的过程类似。

pom.xml 增加spring-cloud-starter-openfeign依赖

bootstrap.yaml:

开启服务注册与发现,@EnableFeignClients注解注册FeignClient

@FeignClient注册声明定义FeignClient,笔者以两种方式定义了两个FeignClient:

1.通过请求路径定义FeignClient

2.通过生产者(即上述构建的helloService)暴露出来的接口定义FeignClient

controller 测试:

测试结果如下:

知道了如何将SpringCloud, Zookeeper 和Feign进行整合,我们知道了怎么使用,更重要的是要知道里面的原理,做到知其然更要知其所以然。

通过上述对整合过程的描述中可以发现,@EnableFeignClients和@FeignClient两个注解是将Feign整合进Spring Cloud的重要组成部分,因此,从这两个注解入手来了解Feign。

@EnableFeignClients注解通过@Import引入了FeignClientsRegistrar进行feign客户端的注册, 同时FeignClientsRegistrar通过实现ImportBeanDefinitionRegistrar来将bean注册spring容器中:

至此,我们知道了通过@EnableFeignClients和@FeignClient两个注解以及其相关属性,在服务启动时,将每个feign client 以及其对应的配置和每个客户端通用的配置以bean的方式注册完到spring容器中。

当使用@Autowired注解自动注入FeignClient时,Spring容器会使用注册FeignClient用到的FeignClientFactoryBean为其生成FeignClient实例。

默认使用的targeter是HystrixTargeter,根据builder的类型设置不同的属性,并生产Feign client

从上面的分析可以得出,当服务启动时,通过@EnableFeignClients注解,启动对标注了@FeignClient注解的类进行扫描和注册,通过FeignClientFactoryBean将FeignClient注册到Spring容器中。当使用@Autowired注解进行自动注入时,注册到Spring容器中FeignClient会以动态代理的形式注入,这些动态代理中包含了接口方法的methodHandler用以处理调用转发。

网站数据信息

"springcloud原理和机制,SpringCloud系列-2Ribbon简介与应用"浏览人数已经达到19次,如你需要查询该站的相关权重信息,可以点击进入"Chinaz数据" 查询。更多网站价值评估因素如:springcloud原理和机制,SpringCloud系列-2Ribbon简介与应用的访问速度、搜索引擎收录以及索引量、用户体验等。 要评估一个站的价值,最主要还是需要根据您自身的需求,如网站IP、PV、跳出率等!