⒈Ribbon是什么?
Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡工具。
Ribbon是Netflix發布的開源項目,主要功能是提供客戶端的軟件負載均衡算法,將Netflix的中間層服務連接在一起。我們在配置文件中列出負載均衡所有的機器,Ribbon會自動的幫助我們基於某種規則(如簡單輪詢、隨機連接等等)去連接這些機器。Ribbon客戶端組件提供了一列完善的配置項(如連接超時、重試等等),我們也能很容易的使用Ribbon實現自定義的負載均衡算法。
⒉負載均衡?
負載均衡(Load Balance,簡稱LB),在微服務或分布式集群中經常用到的一種功能,就是將用戶的請求以某種規則平攤到多個服務器上,從而達到系統的高可用。
常見的負載均衡有軟件例如Nginx、LVS等等,硬件F5等等。
相應的在中間件,例如Dubbo和Spring Cloud中均給我們提供了負載均衡,Spring Cloud的負載均衡算法可以自定義。
集中式負載均衡:即在服務的消費方和提供方之間使用獨立的負載均衡設施(可以是硬件,如F5。也可以是軟件,如Nginx),由該設施負責把請求通過某種策略轉發至服務的提供方。
進程內負載均衡:將負載均衡邏輯集成到服務消費方,由消費方從服務注冊中心獲取有那些服務地址可用,然后消費方從這些地址中選擇一個合適的服務器。(Ribbon屬於進程內負載均衡,它只是一個類庫,集成於服務消費方進程,消費方通過它來獲取到服務提供方的地址)
⒊示例
因為Ribbon集成於服務消費方,這里我只展示服務消費方部分代碼,完整代碼請結合https://www.cnblogs.com/fanqisoft/p/10357598.html自行勾畫。
①添加pom依賴
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.springframework.cloud</groupId> 7 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 8 </dependency> 9 <dependency> 10 <groupId>org.springframework.cloud</groupId> 11 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> 12 </dependency>
②修改配置文件
1 server.port=8200 2 3 spring.application.name=user-consumer 4 5 #eureka.instance.prefer-ip-address 注冊服務的時候使用服務的ip地址 6 eureka.instance.prefer-ip-address=true 7 8 eureka.client.service-url.defaultZone:http://localhost:8761/eureka/
③對訪問Rest資源的Bean加上@LoadBalanced負載均衡注解
1 @Bean 2 @LoadBalanced //使用負載均衡機制 3 public RestOperations restTemplate(){ 4 return new RestTemplate(); 5 }
④主程序啟動上添加@EnableDiscoveryClient注解開啟Eureka服務發現(@EnableDiscoveryClient注解也可以)
1 package cn.coreqi; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.client.loadbalancer.LoadBalanced; 6 import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 7 import org.springframework.context.annotation.Bean; 8 import org.springframework.web.client.RestOperations; 9 import org.springframework.web.client.RestTemplate; 10 11 @SpringBootApplication 12 @EnableDiscoveryClient //開啟服務發現功能 13 public class SpringbootcloudserviceconsumerApplication { 14 15 public static void main(String[] args) { 16 SpringApplication.run(SpringbootcloudserviceconsumerApplication.class, args); 17 } 18 }
⑤在控制器中注入RestTemplate並調用遠程服務
1 package cn.coreqi.controller; 2 3 import cn.coreqi.entities.User; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.web.bind.annotation.GetMapping; 6 import org.springframework.web.bind.annotation.RestController; 7 import org.springframework.web.client.RestOperations; 8 9 @RestController 10 public class UserController { 11 @Autowired 12 private RestOperations restTemplate; 13 14 @GetMapping("/userno1") 15 public User getUsersFirst(){ 16 User[] users = restTemplate.getForObject("http://user-provider/users",User[].class); 17 return users[0]; 18 } 19 }
★Ribbon和Eureka整合后服務消費方可以直接調用服務而不用再關心提供服務的地址以及提供服務的端口號。
Ribbon其實就是一個軟負載均衡的客戶端軟件,它可以和其它所需請求的客戶端結合使用,和Eureka結合只是其中的一個實例。
⒋Ribbon核心組件IRule支持的負載均衡算法
名稱 | 特點 |
RoundRobinRule | 輪詢 |
RandomRule | 隨機 |
AvailabilityFilteringRule | 會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態 和並發的連接數量超過閾值的服務,然后對剩余的服 務列表按照輪詢策略進行訪問。 |
WeightedResponseTimeRule | 根據平均響應時間計算所有服務的權重,響應時間越 快服務權重越大被選中的概率越高,剛啟動時如果統 計信息不足,則使用RoundRobinRule(輪詢)策略 ,等到統計信息足夠,則會自動切換回WeightedRe -sponseTimeRule |
RetryRule | 先按照RoundRobinRule的策略獲取服務,如果獲取 服務失敗,則在指定時間內會進行重試,獲取可用的 服務。 |
BestAvailableRule | 會過濾掉由於多次訪問故障而處於斷路器跳閘狀態的 服務,然后選擇一個並發量最小的服務。 |
ZoneAvoidanceRule | 默認規則,復合判斷Server所在區域的性能和Server 的可用性選擇服務器。 |
⒌SpringCloud如何更改默認的負載均衡算法?
1 package cn.coreqi.config; 2 3 import com.netflix.loadbalancer.IRule; 4 import com.netflix.loadbalancer.RandomRule; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Configuration; 7 8 @Configuration 9 public class RibbonConfig { 10 @Bean 11 public IRule myRule(){ 12 return new RandomRule(); 13 } 14 }
⒍SpringCloud如何自定義Ribbon
①添加配置均衡算法的配置類
★這個自定義配置類不能放在@ComponentScan所掃描的當前包及其子包下,否則這個自定義配置類會被所有的Ribbon客戶端所共享,也就達不到特殊化定制的目的了。
1 package myrule; 2 3 import com.netflix.loadbalancer.IRule; 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 @Configuration 8 public class RibbonConfig { 9 @Bean 10 public IRule myRule(){ 11 return new MyRandomRule(); 12 } 13 }
②在主程序啟動類上添加@RibbonClient注解,並指定其name及configuration屬性。從而在啟動該微服務的時候就能去加載我們自定義的Ribbon配置類,使配置生效。
1 package cn.coreqi; 2 3 import myrule.RibbonConfig; 4 import org.springframework.boot.SpringApplication; 5 import org.springframework.boot.autoconfigure.SpringBootApplication; 6 import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7 import org.springframework.cloud.netflix.ribbon.RibbonClient; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.web.client.RestOperations; 10 import org.springframework.web.client.RestTemplate; 11 12 @SpringBootApplication 13 @EnableDiscoveryClient //開啟服務發現功能 14 @RibbonClient(name = "USER-PROVIDER",configuration = RibbonConfig.class) 15 public class SpringbootcloudserviceconsumerApplication { 16 17 public static void main(String[] args) { 18 SpringApplication.run(SpringbootcloudserviceconsumerApplication.class, args); 19 } 20 }
③新建自定義負載均衡算法類並繼承AbstractLoadBalancerRule重寫choose方法
1 package myrule; 2 3 import com.netflix.client.config.IClientConfig; 4 import com.netflix.loadbalancer.AbstractLoadBalancerRule; 5 import com.netflix.loadbalancer.Server; 6 7 public class MyRandomRule extends AbstractLoadBalancerRule { 8 @Override 9 public void initWithNiwsConfig(IClientConfig iClientConfig) { 10 11 } 12 13 @Override 14 public Server choose(Object o) { 15 return null; 16 } 17 }