淺談SpringCloud (三) Ribbon負載均衡
什麽是負載均衡
當一臺服務器的單位時間內的訪問量越大時,服務器壓力就越大,大到超過自身承受能力時,服務器就會崩潰。為了避免服務器崩潰,讓用戶有更好的體驗,我們通過負載均衡的方式來分擔服務器壓力。
我們可以建立很多很多服務器,組成一個服務器集群,當用戶訪問網站時,先訪問一個中間服務器,在讓這個中間服務器在服務器集群中選擇一個壓力較小的服務器,然後將該訪問請求引入該服務器。如此以來,用戶的每次訪問,都會保證服務器集群中的每個服務器壓力趨於平衡,分擔了服務器壓力,避免了服務器崩潰的情況。
Ribbon
Spring Cloud Ribbons是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。
Spring Cloud Ribbon雖然只是一個工具類框架,它不像服務註冊中心、配置中心、API網關那樣需要獨立部署,但是它幾乎存在於每一個Spring Cloud構建的微服務和基礎設施中。因為微服務間的調用,API網關的請求轉發等內容,實際上都是通過Ribbon來實現的,包括後續我們將要介紹的Feign,它也是基於Ribbon實現的工具。所以,對Spring Cloud Ribbon的理解和使用,對於我們使用Spring Cloud來構建微服務非常重要。
SpringCloud使用Ribbon
1.修改客戶端的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springclouddemo</artifactId> <groupId>com.aomeibox</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>customer-order</artifactId> <name>customer-order</name> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>1.4.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Ribbon 相關--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> <version>1.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency> </dependencies> </project>
2.修改客戶端的MyConfig類
package com.aomeibox.config; 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; /** * Created by jl on 2018/12/27. */ @Configuration public class MyConfig { @Bean @LoadBalanced //負載均衡工具 public RestTemplate restTemplate(){ return new RestTemplate(); } }
3.修改客戶端的controller,通過在Eureka中註冊的ApplicaitonName進行訪問
package com.aomeibox.con; import com.aomeibox.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; /** * Created by leo on 2018/12/24. */ @RestController public class OrderController { @Autowired private RestTemplate template;//spring提供的一個用於訪問rest接口的模板對象 private static final String url = "http://PROVIDER-USER"; // @Autowired // private EurekaClient eurekaClient; @GetMapping("/order/{id}") public User getUser(@PathVariable Integer id){ // InstanceInfo eureka = eurekaClient.getNextServerFromEureka("PROVIDER-USER", false); //訪問提供者獲取數據 // User user = template.getForObject(eureka.getHomePageUrl()+"/user/"+ id, User.class);//通過訪問rest 獲取到json數據,然後轉換成User對象 User user = template.getForObject(url+"/user/"+ id, User.class); return user; } }
4.運行項目
Ribbon負載均衡策略
使用負載均衡帶來的好處很明顯:
- 當集群裏的1臺或者多臺服務器down的時候,剩余的沒有down的服務器可以保證服務的繼續使用
- 使用了更多的機器保證了機器的良性使用,不會由於某一高峰時刻導致系統cpu急劇上升
負載均衡有好幾種實現策略,常見的有:
- 隨機 (RandomRuler)
- 輪詢 (RoundRobinRuler) (默認)
- 一致性哈希 (ConsistentHashRuler)
- 哈希 (HashRuler)
- 加權(WeightedRuler)
RoundRobinRule輪詢策略表示每次都取下一個服務器,比如一共有5臺服務器,第1次取第1臺,第2次取第2臺,第3次取第3臺,以此類推。
WeightedResponseTimeRule繼承了RoundRobinRule,開始的時候還沒有權重列表,采用父類的輪詢方式,有一個默認每30秒更新一次權重列表的定時任務,該定時任務會根據實例的響應時間來更新權重列表,choose方法做的事情就是,用一個(0,1)的隨機double數乘以最大的權重得到randomWeight,然後遍歷權重列表,找出第一個比randomWeight大的實例下標,然後返回該實例。
BestAvailableRule策略用來選取最少並發量請求的服務器。
如果需要改變輪訓的策略,需要修改自己的配置類。
package com.aomeibox.config; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; 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; /** * Created by leo on 2018/12/27. */ @Configuration public class MyConfig {//@Configuration + 本類 = applicationContext.xml文件 @Bean @LoadBalanced //負載均衡工具 public RestTemplate restTemplate(){ return new RestTemplate(); } @Bean public IRule myRule(){ return new RandomRule();//隨機策略 } }
自定義負載均衡策略
1.主啟動類新增註解。註意,自己編寫的Rule類,不能和主啟動類放在同一個包下
package com.aomeibox; import com.aomei.MySelfRule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; /** * * 消費者 */ @SpringBootApplication @EnableEurekaClient @RibbonClient(name = "PROVIDER-USER",configuration = MySelfRule.class)//MySelfRule.class不能在本類的包或者子包下 public class CustomerOrder { public static void main( String[] args ) { SpringApplication.run(CustomerOrder.class); } }
2.新增MyRule類。
package com.aomei; import com.netflix.loadbalancer.BestAvailableRule; import com.netflix.loadbalancer.IRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by leo on 2018/12/29. */ @Configuration public class MySelfRule { @Bean public IRule myRule(){ return new BestAvailableRule(); } }
Feign負載均衡
上述的Ribbon功能很強大,可以自定義算法。
Feign 是一個聲明web服務客戶端,這便得編寫web服務客戶端更容易,使用Feign 創建一個接口並對它進行註解,它具有可插拔的註解支持包括Feign註解與JAX-RS註解,Feign還支持可插拔的編碼器與解碼器,Spring Cloud 增加了對 Spring MVC的註解,Spring Web 默認使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的負載均衡的HTTP客戶端 Feign。
上述大部分,我們通常是以微服務的ApplicaitonName進行訪問的。但是在開發編程過程中,我們通常是面向接口編程。因此出現了Feign。Feign可以使用接口+註解,調用其他項目的接口。
@FeignClient("provider-user") public interface UserClient { @RequestMapping(method = RequestMethod.GET, value = "/getuser") public User getuserinfo(); @RequestMapping(method = RequestMethod.GET, value = "/getuser") public String getuserinfostr(); @RequestMapping(method = RequestMethod.GET, value = "/info") public String info(); }
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class FeignApplication { public static void main(String[] args) { SpringApplication.run(FeignApplication.class, args); } }
@RestController public class UserController { @Autowired UserClient userClient; @RequestMapping(value = "/getuserinfo", method = RequestMethod.GET) public User getuserinfo() { return userClient.getuserinfo(); } @RequestMapping(value = "/getuserinfostr", method = RequestMethod.GET) public String getuserinfostr() { return userClient.getuserinfostr(); } @RequestMapping(value = "/info", method = RequestMethod.GET) public String info() { return userClient.info(); } }
淺談SpringCloud (三) Ribbon負載均衡