一、概述
1.1Ribbon是什麼
Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。
簡單的說,Ribbon是Netflix發佈的開源項目,主要功能是提供客戶端的軟件負載均衡算法和服務調用。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,就是在配置文件中列出Load Balancer(簡稱LB)後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器。我們很容易使用Ribbon實現自定義的負載均衡算法。
1.2作用
1.2.1LB負載均衡
LB負載均衡(Load Balance)是什麼?
簡單的說就是將用戶的請求平攤的分配到多個服務上,從而達到系統的HA(高可用)。
常見的負載均衡有軟件Nginx,LVS,硬件F5等。
Ribbon本都負載均衡客戶端 VS Nginx服務端負載均衡區別?
Nginx是服務器負載均衡,客戶端所有請求都會交給nginx,然後由nginx實現轉發請求。即負載均衡是由服務端實現的。
Ribbon本地負載均衡,在調用微服務接口時候,會在註冊中心上獲取註冊信息服務列表之後緩存到JVM本地,從而在本地實現RPC遠程服務調用技術。
集中式LB
即在服務的消費方和提供方之間使用獨立的LB設施(可以是硬件,如F5,也可以是軟件,如nginx),由該設施負責把訪問請求通過某種策略轉發至服務的提供方。
進程內LB
將LB邏輯集成到消費方,消費方從服務註冊中心獲知有哪些地址可用,然後,自己再從這些地址中選擇出一個合適的服務器。
Ribbon就屬於進程內LB,它只是一個類庫,集成與消費方進程,消費方通過它來獲取到服務提供方的地址。
一句話--負載均衡+RestTemplate調用
二、Ribbon負載均衡演示
2.1架構說明
Ribbon在工作時分成兩步:
第一步先選擇EurekaServer,它優先選擇在同一個區域內負載較少的server。
第二步再根據用戶指定的策略,再從server取到的服務註冊列表中選擇一個地址。
其中Ribbon提供了多種策略:比如輪詢、隨機和根據響應時間加權。
2.2POM
2.3 RestTemplate的使用
2.3.1官網
2.3.2getForObject方法/getForEntity方法
package com.atguigu.springcloud.controller;
import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
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;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderController {
//不能寫死
// public static final String PAYMENT_URL = "http://localhost:8001";
//註冊中心上獲取
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment) {
// return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
return restTemplate.postForEntity(PAYMENT_URL+"/payment/create", payment, CommonResult.class).getBody();
}
// 返回對象爲響應體中數據轉化成的對象,基本上可以理解爲Json
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
}
// 返回對象爲ResponseEntity對象,包含了響應中的一些重要信息,比如響應頭、響應狀態碼、響應體等
@GetMapping("/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment2(@PathVariable("id") Long id) {
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
if (entity.getStatusCode().is2xxSuccessful()) {
log.info(entity.getStatusCode()+"\t"+entity.getHeaders());
CommonResult body = entity.getBody();
return body;
} else {
return new CommonResult<>(444, "操作失敗");
}
}
}
2.3.3postForObject/postForEntity
三、Ribbon核心組件IRule
3.1IRule
根據特定算法從服務列表中選取一個要訪問的服務
3.1.1com.netflix.loadbalancer.RoundRobinRule
輪詢
3.1.2com.netflix.loadbalancer.RandomRule
隨機
3.1.3com.netflix.loadbalancer.RetryRule
先按照RoundRobinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試
3.1.4WeightedResponseTimeRule
對RoundRobinRule的擴展,響應速度越快的實例選擇權重越大,越容易被選擇
3.1.5BestAvailableRule
會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後,選擇一個併發量最小的服務
3.1.6AvailabilityFilteringRule
先過濾掉故障實例,再選擇併發較小的實例
3.1.7ZoneAvoidanceRule
默認規則,複合判斷server所在區域的性能和server的可用性選擇服務器
3.2如何替換
3.2.1修改cloud-consumer-order80
3.2.2注意配置細節
不能和springcloud包在一起
3.2.3新建package
com.atguigu.myrule
3.2.4上面包下新建MySelfRule規則類
package com.atguigu.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule();//定義爲隨機
}
}
3.2.5主啓動類添加@RibbonClient
package com.atguigu.springcloud;
import com.atguigu.myrule.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;
@EnableEurekaClient
@SpringBootApplication
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class) //訪問支付微服務
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
3.2.6測試
http://localhost/consumer/payment/get/1
3.3Ribbon負載均衡算法
3.3.1原理