(编写不易,转载请注明:http://shihlei.iteye.com/blog/2404997)
一 概述
负载均衡,简单说即将 “负载” 按照一定策略分摊到不同的执行单元中执行。
服务的负载均衡目前主要实现策略:
1)服务器端反向代理:硬负载 F5, 软负载 LVS,Nginx;可以透明接入,但要独立搭建高可用架构。
2)客户单端负载均衡器:lib形式提供,可以根据需要灵活控制策略,但需要客户端集成。
Ribbon 属于客户端负载均衡器,主要应用于服务消费者,支持RestTemplate,Feign等请求技术集成,支持从配置文件或从Eureka重拉取Server实例列表,其他需要原生开发。
负载均衡算法:
随机,轮询,响应时间加权等等
git:https://github.com/Netflix/ribbon
本文规划:
1)Ribbon 原生使用及自定义rule。
2)SpringCloud RestClient集成Ribbon及简要说明实现机制。
二 Ribbon demo
1) 原生demo
(1)添加依赖
<dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-loadbalancer</artifactId> <version>2.2.5</version> </dependency>
(2)demo
package x.demo.netflix.ribbon; import java.util.Arrays; import java.util.List; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.LoadBalancerBuilder; import com.netflix.loadbalancer.NoOpPing; import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.Server; /** * LoadBalancerDemo */ public class LoadBalancerDemo { public static void main(String[] args) { // 负载均衡规则 IRule rule = new RoundRobinRule(); // ping 规则 IPing ping = new NoOpPing(); // 添加Server 列表 List<Server> serverList = Arrays.asList( new Server("server1"), new Server("server2"), new Server("server3"), new Server("server4"), new Server("server5") ); //初始化LoadBalancer ILoadBalancer loadBalancer = LoadBalancerBuilder .newBuilder() .withRule(rule) .withPing(ping) .buildFixedServerListLoadBalancer(serverList); // 简单查看效果 for (int i = 0; i < 10; i++) { System.out.println(loadBalancer.chooseServer(null)); } } }
2)Ribbon 结果简单分析
Ribbon 源码比较简单,结构也比较清晰,很方便看,主要体系:LoadBalancer,Rule,Ping 可以简单看看。
(1)LoadBalancer 体系:
【1】 接口级别:
a)ILoadBalancer:定义LoadBalancer的基本行为,主要是从ServerList中根据策略选择一个Server实例进行请求。
核心方法:
- addServers:向LoadBalancer增加Server实例。
- chooseServer:通过某种策略,从ServerList选择一个Server实例。
- markServerDown:通知LoadBalancer某个Server实例已Down,下次请求可以忽略。
- getReachableServers:获取可用的Server实例列表。
- getAllServers:获取所有Server实例列表。
b)AbstractLoadBalancer:抽象LoadBalancer的一般操作。
【2】实现级别:
c)BaseLoadBalancer:基础实现,把实现依赖抽象成如下几大块,做用户定制和扩展,
主要依赖:
- IClientConfig:提供配置信息,如ping 超时时间等。
- IRule:提供Server实例选择策略。
- IPing:提供验证实例是否可用策略。
d)DynamicServerListLoadBalancer:可动态添加ServerList(yml文件等),并提供Filter过滤能力
e) ZoneAwareLoadBalancer:提供Zone 负载均衡
(2)Rule体系
【1】接口级别:
a)IRule:提供Server选择策略
核心方法:Server choose(in Object key)
b)AbstractLoadBalancerRule:抽象Rule的一般操作,主要维护一个ILoadBalancer实例,提供get,set方法,完成绑定,以便获得SeverList供选择使用
【2】实现级别:
d)RandomRule
e)RoundRobinRule(及ClientConfigEnabledRoundRobinRule),
f)WeightedResponseTimeRule(返回时间权重规则)
g)BestAvailableRule(最低并发规则)
【3】其他包装类:
h)RetryRule:支持重试的规则
(3)Ping体系
【1】接口级别:
a)IPing:提供判读Sever实例是否可用的策略
核心方法:boolean isAlive(Server server)
b)AbstractLoadBalancerPing:主要维护一个ILoadBalancer实例,提供get,set方法,完成绑定,以便获得SeverList以便尝试时使用
【2】实现级别:
c)NoOpPing:无任何操作,永远返回true,有效。
d)DummyPing:也是永远返回true。
e)NIWSDiscoveryPing:基于发现的Ping规则
3)自定义一个Rule实现只使用第一个服务器
package x.demo.springcloud.webfront.service.impl.ribbon; import java.util.List; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.Server; /** * 只请求第一台server * */ public class FirstServerRule extends AbstractLoadBalancerRule { @Override public Server choose(Object key) { List<Server> servers = getLoadBalancer().getReachableServers(); return servers.get(0); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { } }
三 SpringCloud Ribben + RestClient
1)概述
SpringCloud 对 LoadBalancer 进行了高层抽象,用于多种Http客户端获得负载均衡的能力。Ribbon作为一种基础实现,通过SpringCloud AutoConfiguration机制集成。
注:demo 默认使用《SpringCloud文章系列》的 “microservice-time” 时间微服务,作为服务提供者,为简化项目复杂度,禁用Eureka 服务发现能力。
具体项目环境可参见《SpringCloud(一): SpringBoot 创建简单的微服务》
本文主要改造微服务客户端项目:
spring-cloud-webfront:服务调用者,调用“时间”微服务,返回当前时间。
2)集成使用Demo
(1)添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
(2)RestClient 集成 Ribbon
只需要通过在@Configuration中添加创建RestTemplate的Bean,并使用@LoadBalanced进行注解即可
package x.demo.springcloud.webfront.service.impl.ribbon; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** * RestTemplateRibbon * */ @Configuration public class RestTemplateRibbonConfiguration { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
(3)配置服务器信息
a)yml 文件配置方式
spring: profiles: Standalone application: name: webfront server: port: 20001 # 自定义配置 timeMisroService: v1: uri: http://microservice-time/time/v1 # Ribbon 负载均衡配置 # 取消eureka 依赖 ribbon: eureka: enabled: false # microservice-time 相对于虚拟主机,RestTemplate 必须使用microservice-time 访问 才能走复杂均衡策略 microservice-time: ribbon: # LoadBalancer NFLoadBalancerClassName: com.netflix.loadbalancer.DynamicServerListLoadBalancer # 由于禁用了Ribbon Eureka获取服务ip端口,需要手动提供 listOfServers: 127.0.0.1:10001,127.0.0.1:10002 # 负载均衡策略 NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule # ping策略 NFLoadBalancerPingClassName: com.netflix.loadbalancer.NoOpPing
注:
microservice-time.ribbon 是针对 microservice-time 的 ribbon配置,microservice-time 相当于虚拟主机,使用时host需要使用 microservice-time 作为虚拟主机,如地址http://microservice-time/time/v1,Ribbon根据策略获取实际的IP和端口,这里是通过microservice-time.ribbon.listOfServers获取的
其他定制项:
- NFLoadBalancerClassName: 默认 DefaultClientConfigImpl
- NFLoadBalancerPingClassName: 默认 DummyPing
- NFLoadBalancerRuleClassName: 默认 ZoneAvoidanceRule
- NIWSServerListClassName: 默认 ConfigurationBasedServerList
- NIWSServerListFilterClassName: 默认 ZonePreferenceServerListFilter
b)程序配置方式:
package x.demo.springcloud.webfront.service.impl.ribbon; import java.util.Arrays; import java.util.List; import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.NoOpPing; import com.netflix.loadbalancer.RandomRule; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerList; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.Bean; /** * Ribbon 负载均衡配置 * <p> * 特别注意: * 这里是针对 name = "microservice-time" 的服务进行的配置,所以不能 添加 @Configuration ,否则接入容器,会全局生效 * */ @RibbonClient(name = "microservice-time", configuration = TimeMicroServiceConfiguration.class) public class TimeMicroServiceConfiguration { @Bean public IRule rule() { return new RandomRule(); } @Bean public IPing ping() { return new NoOpPing(); } @Bean public ServerList<Server> serverList() { List<Server> servers = Arrays.asList(new Server("127.0.0.1", 10001), new Server("127.0.0.1", 10002)); ServerList<Server> serverList = new ServerList<Server>() { @Override public List<Server> getInitialListOfServers() { return servers; } @Override public List<Server> getUpdatedListOfServers() { return servers; } }; return serverList; } }
(4)service 层
package x.demo.springcloud.webfront.service; public interface TimeService { /** * 获取当前时间 * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss */ String now(); } package x.demo.springcloud.webfront.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import x.demo.springcloud.webfront.service.TimeService; @Service public class TimeServiceRestClientImpl implements TimeService { @Value("${timeMisroService.v1.uri}") private String timeMicroServiceV1Uri; @Autowired private RestTemplate restTemplate; /** * 获取当前时间 * * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss */ @Override public String now() { String url = timeMicroServiceV1Uri + "/now"; ProtocolResult<String> result = restTemplate.getForObject(url, ProtocolResult.class); return result.getBody(); } }
(5)启动类
package x.demo.springcloud.webfront; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringCloudWebfrontApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudWebfrontApplication.class, args); } }
(6)查看结果(略)
(7)SpringCloud Ribbon + FeignClien:
四 SpringCloud LoadBalancer 源码分析
1)概述
(1)LoadBalancerClient体系
a)ServiceInstanceChooser:Service实例选择器接口
核心方法:ServiceInstance choose(String serviceId) :根据serviceId 选择一个 Service 实例。
b)LoadBalancerClient:负载均衡客户端接口,具有选择服务实例,执行请求的能力,继承自 ServiceInstanceChooser;
核心方法:
执行请求方法:
T execute(String serviceId, LoadBalancerRequest<T> request)
T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request)
重建请求链接方法:
URI reconstructURI(ServiceInstance instance, URI original);
c)RibbonLoadBalancerClient:基于Ribbon实现的LoadBalancerClient,内部依赖 Ribbon的ILoadBalancer体系
(2) ClientHttpRequestInterceptor体系:
a)RestTemplate:Rest请求客户端,提供Rest服务访问能力
b)ClientHttpRequestInterceptor:RestTemplate提供的拦截器,可以在请求之根据需要进行拦截,一般用实现Header头改写,添加Token等通用的面向切面编程。
c)RetryLoadBalancerInterceptor:实现了ClientHttpRequestInterceptor,拦截Http请求,依赖 LoadBalancerClient 选择Service实例,重新发起请求。实现负载均衡。
(3)AutoConfiguration体系:
a)LoadBalancerAutoConfiguration:配置负载均衡客户端(di主要通过这个进行配置)如果是 RestTemplate 的形式,则在restTemplate 中通过添加RetryLoadBalancerInterceptor; 用于拦截请求。
b)RibbonAutoConfiguration:查看spring.factories文件,拉起Ribbon的默认配置及组装点
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
相关推荐
Spring Cloud Ribbon 实现客户端负载均衡的方法 Spring Cloud Ribbon 是基于 Netflix OSS 的一个开源项目,提供了客户端负载均衡的功能。在本篇文章中,我们将介绍如何使用 Spring Cloud Ribbon 来实现客户端负载...
而Ribbon是Netflix开源的客户端负载均衡器,它与Spring Cloud结合,可以自动地在多个服务器实例间分配请求,提高系统的可用性和可靠性。 首先,我们要了解Ribbon的工作原理。Ribbon是一个客户端负载均衡器,它驻留...
Spring Cloud是构建微服务架构的一套工具集,其中Ribbon是它提供的一个客户端负载均衡器,可以帮助我们实现服务间的智能路由。本篇文章将详细探讨如何在Spring Cloud中使用Ribbon实现负载均衡。 首先,我们要理解...
Spring Cloud中的Ribbon是实现客户端负载均衡的关键组件。在传统的服务端负载均衡中,像Nginx这样的代理服务器会接收请求并根据预设的算法(如轮询、权重轮询、随机等)转发到后端服务。而在客户端负载均衡模式下,...
客户端负载均衡器Ribbon是Netflix开发的一个开源组件,主要用于实现微服务架构中的客户端负载均衡功能。在本实验代码中,我们将深入理解Ribbon的工作原理及其在实际应用中的配置与使用。 Ribbon是一个轻量级的库,...
在Spring Cloud生态系统中,Spring Cloud Ribbon是一个至关重要的组件,它主要负责实现客户端的负载...通过对`RestTemplate`方法的灵活运用,我们可以方便地处理HTTP请求,同时享受到Ribbon带来的客户端负载均衡优势。
Ribbon是一个客户端负载均衡器,它可以很好地控制HTTP和TCP客户端的行为。
SpringCloud的复杂均衡 属于客户端;nginx辅助均衡属于服务器端 ,restTemplate 进行RPC调用.对外使用 rest http方式。DiscoveryClient 可以自己实现一个负载均衡的算法(使用请求总数 % 服务列表个数).算法文件跟新...
spring cloud gateway的负载均衡和动态路由的实现 demo_01,demo_02,demo_03 这三个服务相当于是集群的微服务 gateway这个服务是 springcloude gateway + ribbon 做的负载均衡 gateway_01 这个服务 是动态路由的...
总的来说,SpringCloud 通过 Ribbon 和 OpenFeign 提供了灵活的客户端负载均衡解决方案,可以根据不同的场景和需求选择合适的工具和策略。无论是自定义负载均衡规则还是利用默认策略,都能帮助开发者有效地管理和...
本教程将详细讲解两种常用的客户端负载均衡器——Ribbon和LoadBalancer,以及它们在Spring Cloud Alibaba框架中的实践。 首先,负载均衡的基本概念是将工作负载分布到多个操作单元,以协同处理任务。在微服务场景下...
cloud-sample-tutorial-consumer`,并在`pom.xml`中添加对`spring-cloud-starter-eureka`和`spring-cloud-starter-ribbon`的依赖,这两个依赖分别用于Eureka服务发现和Ribbon客户端负载均衡。 在`application....
Spring Cloud集成Ribbon或Netflix Eureka实现了客户端负载均衡。当`uri`以`lb://`开头时,Spring Cloud Gateway会使用Ribbon进行负载均衡,自动轮询调用服务实例。Ribbon会根据配置的策略(如轮询、随机等)选择一...
其中,Spring Cloud Ribbon是一个客户端负载均衡器,它可以与Spring Cloud Netflix Eureka结合使用,实现服务间的智能路由和负载均衡。在这个"springcloud-ribbon负载均衡demo"中,我们将探讨Ribbon的基本概念、工作...
Spring Cloud Netflix:核心组件,可以对多个Netflix OSS开源套件进行整合,包括以下几个组件: Eureka:服务治理组件,包含服务注册与发现 Hystrix:容错管理组件,实现了熔断器 Ribbon:客户端负载均衡的服务调用...
该项目是一款基于SpringCloud框架的Idea集成Ribbon客户端负载均衡设计源码,总文件量达86个,涵盖33个Java源文件、12个XML配置文件、6个HTML文件、5个Git忽略文件、4个数据库文件、4个JAR包、4个属性文件、4个YAML...
* Spring Cloud Ribbon:客户端负载均衡 * Spring Cloud Feign:声明性的 Web 服务客户端 * Spring Cloud Hystrix:断路器 * Spring Cloud Config:分布式统一配置管理 Spring Cloud 和 SpringBoot 的关系 * ...
在Spring Cloud生态中,Ribbon是一个重要的客户端负载均衡器,它与Netflix的Eureka服务注册中心结合,使得微服务间的调用能够实现智能路由和负载均衡。本篇将深入探讨Spring Cloud Ribbon的工作原理、功能特性以及...
Ribbon是客户端负载均衡器,而Eureka是服务发现组件。在Spring Cloud中,通常使用Eureka来注册和发现服务,Ribbon则会自动选择Eureka中的一个服务实例进行请求。引入`spring-cloud-starter-netflix-eureka-client`和...