技术笔记:springcloud深入学习(四)

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介: 技术笔记:springcloud深入学习(四)

基本概念


1、Registe 一一服务注册


当eureka Client向Eureka Server注册时,Eureka Client提供自身的元数据,比如IP地址、端口、运行状况指标的Uri、主页地址等信息。


2、Renew一一服务续约


Eureka lient在默认的情况下会每隔30秒发送一次心跳来进行服务续约,代表自己依然存活。如果eureka server在90秒内没有收到心跳消息,将eureka client从实例注册列表中删除。


3、Fetch Registries一一获取服务注册列表信息


Eureka Client从Eureka Server获取服务注册表信息,井将其缓存在本地。Eureka Client会使用服务注册列表信息查找其他服务的信息,从而进行远程调用,该注册列表每30秒更新一次。Eureka Client


和Eureka Server 可以使用 JSON XML 数据格式进行通信。在默认的情况下, Eureka Client


使用JSON 格式的方式来获取服务注册列表的信息。


4、Cancel-一服务下线


Eureka Client在程序关闭时可以向Eureka Server发送下线请求。不过下线请求不会自动完成,需要在程序关闭时调用如下代码:


DiscoveryManager.getinstance().shutdownComponent();


5、Eviction一一服务剔除


当Eureka Client90秒没有向Eureka Server发送服务续约(即心跳)时,Eureka Server会将该服务实例从服务注册列表删除,即服务剔除。


Register服务注册


boolean register() throws Throwable {


logger.info(PREFIX + appPathidentifier + ”: registering service ... ” );


EurekaHttpResponse httpResponse;


try {


httpResponse = eurekaTransport.registrationClient.register(instanceinfo);


}catch(Exception e) {


logger.warn(”{} - registration failed {} ”, PREFIX + appPathidentifier, e.getMessage(), e};


throw e;


}


if logger.isInfoEnabled()) {


logger.info(”{} - registration status: {} ”, PREFIX + appPathidentifier, httpResponse.getStatusCode());


}


return httpResponse.getStatusCode() == 204 ;


}


服务续约


boolean renew () {


EurekaHttpResponse httpResponse;


try {


httpResponse = eurekaTransport.registrationClient.sendHeartBeat(InstanceInfo.getAppName(), instanceinfo.getid() ,instanceinfo , null);


logger.debug (”{) - Heartbeat status: {) ”, PREFIX + appPathidentifier, httpResponse.getStatusCode());


if {httpResponse. getStatusCode {) == 4 04) {


REREGISTER COUNTER.increment() ;


logger.info(” {) - Re-registering apps/{) ”, PREFIX + appPathidentifier, instanceinfo.getAppName{));


return register();


}


return httpResponse. getStatusCode () == 200;


)catch(Throwable e) {


logger.error(” {) - was unable to send heartbeat !”, PREFIX + appPathidentifier, e);


return false;


为什么获取服务实例特别慢?


1、Eureka Client的注册延迟


Eureka Client启动之后,不是立即向Eureka Server注册的,而是有一个延迟向服务端注册的时间。通过跟踪源码,可以发现默认的延迟时间为 40 秒。


2、Eureka Server的响应缓存


Eureka Server维护每30秒更新一次响应缓存,可通过更改配置eureka.server.responseCacheUpdatelntervalMs来修改。


3、LoadBalancer的缓存


Ribbon的负载平衡器从本地的Eureka Consumer获取服务注册列表信息。Ribbon本身还维护了缓存,以避免每个请求都需要从Eureka Consumer获取服务注册列表。此缓存每30秒刷新一次。


Ribbon


概念


Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。


RestTemplate


RestTemplate是用来消费REST服务的,所以RestTemplate的主要方法都与REST的http协议的一些方法紧密相连,例如HEAD GET POST PUT DELETE OPTIONS等方法,对应的RestTemplate中的方法为headForHeaders()、getForObject()、postForObject()、put()和delete()等。


示例:获取百度的html


@RestController


public class RestTestController {


@GetMapping (”/testRest”)


public String testRest() {


RestTemplate restTemplate=new RestTemplate() ;


//代表发送get请求,并且返回结果为String类型


return restTemplate.getForObject(” String.class) ;


}


}


负载均衡


LB,即负载均衡(Load Balance),在微服务或分布式集群中经常用的一种应用。负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA。常见的负载均衡有软件Nginx,LVS,硬件 F5等。相应的在中间件,例如:dubbo和SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。分为集中式LB以及进程内LB:


1、集中式LB


集中式LB即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;


2、进程内LB


进程内LB 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。


简单来说,一个在服务端做负载均衡,一种则提前在客户端做负载均衡,Ribbon则是后面一种。


Ribbon


Spring Cloud构建的微服务系统中,Ribbon作为服务消费者的负载均衡器,有两种使用方式,一种是和RestTemplate相结合,另一种是和Feign 相结合。


在本人的上一篇博文中有Ribbon的demo:spring cloud深入学习(三)-----服务消费


@Configuration


public class RibbonConfig {


@Bean


@LoadBalanced


RestTemplate restTemplate () {


return new RestTemplate();


}


}


Ribbon实现方式:RestTemplate + @LoadBalanced


LoadBalancerClient


LoadBalancerClient是实现负载均衡的核心类,可以通过如下方式获取到服务实例:


@RestController


public class RibbonController {


@Autowired


private LoadBalancerClient loadBalancer;


@GetMapping(”/testRibbon”)


public String testRibbon() {


Serviceinstance instance = loadBalancer.choose(”eureka-provider");


return instance.getHost() + ”:” + instance.getPort();


}


}


总结:RestTemplate加上@LoadBalance注解后,维护了一个被@LoadBalance注解的RestTemplate列表;


RestTemplate列表中的对象通过拦截器将调用交给Ribbon的LoadBalancerClient去处理;


LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等,获取注册列表的信息,默认10秒向EurekaClient 发送一次“ping”,检查是否要更新服务的注册列表信息;


在得到服务注册列表信息后,ILoadBalancer根据IRule策略进行负载均衡。


IRule


Ribbon的负载算法默认分为七种:


RoundRobinRule、RandomRule、AvailabilityFilteringRule、WeightedResponseTimeRule、RetryRule、BestAvailableRule、ZoneAvoidanceRule


RoundRobinRule


轮询,默认就是这种算法,例如provider会有三台服务器,那么顺序可能就是1-->2-->3-->1-->2-->3..


RandomRule


随机,每一次调用都是从可用的provider中随机选取一台


AvailabilityFilteringRule


会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问


WeightedResponseTimeRule


根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule


RetryRule


先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务


BestAvailableRule


会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务


ZoneAvoidanceRule


默认规则,复合判断server所在区域的性能和server的可用性选择服务器


自定义负载策略


@Configuration


public class ConfigBean //boot -->spring applicationContext.xml --- @Configuration配置 ConfigBean = applicationContext.xml


{


@Bean


@LoadBalanced//Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。


public RestTemplate getRestTemplate()


{


return new RestTemplate();


}


@Bean


public IRule myRule()


{


//return new RoundRobinRule();


//return new RandomRule();//达到的目的,用我们重新选择的随机算法替代默认的轮询。


//这地方可以实现自己的负载策略即可


return new RetryRule();


}


}


Feign


官网解释:


Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡,只需要创建一个接口,然后在上面添加注解即可。前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。 Feign集成了Ribbon利用Ribbon维护了MicroServiceCloud-Dept的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。


Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。


1、pom.xml


<?xml version="1.0" encoding="UTF-8"?>


[/span>project xmlns="" xmlns:xsi=""


xsi:schemaLocation=" "

[/span>modelVersion

[/span>parent

[/span>groupId

[/span>artifactId

[/span>version

[/span>relativePath/>



[/span>groupId

[/span>artifactId

[/span>version

[/span>name

style="color: rgba(0, 0, 255, 1)"]

[/span>description

[/span>properties

[/span>java.version


[/span>dependencies

[/span>dependency

[/span>groupId

[/span>artifactId


[/span>dependency

[/span>groupId

[/span>artifactId

[/span>scope


[/span>dependency

[/span>groupId

[/span>artifactId


[/span>dependency

[/span>groupId

[/span>artifactId

[/span>version


[/span>dependency

[/span>groupId

[/span>artifactId

[/span>version



[/span>dependencyManagement

[/span>dependencies

[/span>dependency

[/span>groupId

[/span>artifactId

[/span>version

[/span>type




[/span>build

[/span>plugins

[/span>plugin

[/span>groupId

[/span>artifactId

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
2月前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
3月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
484 37
|
2月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
6月前
|
JSON Java 程序员
马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day1最快 最全(2)
马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day1最快 最全(2)
62 3
|
6月前
|
程序员 测试技术 Docker
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day3 全网最全
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day3 全网最全(1)
444 1
|
6月前
|
SQL Java 程序员
马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day1最快 最全(1)
马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day1最快 最全(1)
231 1
|
5月前
|
Java API 网络架构
Spring Cloud中的服务路由与过滤技术实现
Spring Cloud中的服务路由与过滤技术实现
|
6月前
|
关系型数据库 MySQL Shell
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day2 全网最快最全(下)
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day2 全网最快最全(下)
284 0
|
6月前
|
Java 程序员 Docker
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day2 全网最快最全(上)
黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day2 全网最快最全(上)
243 0
|
6月前
|
Java API Nacos
SpringCloud Demo入门学习
SpringCloud Demo入门学习
70 0
下一篇
DataWorks