10.rabbion負載均衡和服務呼叫
阿新 • • 發佈:2022-05-29
spring cloud ribbon是基於NetflixRibbon實現的一套客戶端(注意是客戶端)負載均衡工具 LB負載均衡(Load Balance)是什麼 簡單的說就是將使用者的請求平攤到多個伺服器上,從而達到系統的HA(高可用) 常見的負載均衡有軟體Nginx,LXS,硬體F5等 Ribbon本地負載均衡客戶端 VS Nginx服務端負載均衡區別 1.Nginx是伺服器負載均衡,客戶所有請求都會交給Nginx,然後由Nginx實現轉發請求。即負載均衡是由服務端實現的。 2.Ribbon是本地負載均衡,在呼叫微服務介面時候,會在註冊中心上獲取註冊服務列表後快取到JVM本地,從而在本地實現RPC遠端服務呼叫技術! 集中式LB: 即在服務的消費方換和提供方之間使用獨立的LB設施(可以是硬體,如F5,也可以是軟體,如Nginx),由該設施負責將訪問請求通過某種策略轉發到 服務的提供方! 程序內LB: 將LB邏輯整合到消費方,消費方從服務註冊中心獲知到有哪些地址可用,然後自己再從這些地址中選擇出一個合適的伺服器! Ribbon就屬於程序內LB,它只是一個類庫,集成於消費方程序,消費方通過它獲取到服務提供方的地址!
Ribbon其實就是一個軟負載均衡的客戶端元件,它可以和其他所需請求的客戶端結合使用,和eureka結合只是其中的一個例項!
Ribbon在工作時分成兩步:
1.先選擇EurekaServer,它優先選擇在同一個區域內負載較少的server
2.再根據使用者指定的策略,在從server渠道的服務註冊列表中選擇一個地址
其中的ribbon提供了多種策略;比如輪詢、隨機和根據響應時間加權等等!
總結:重要
ribbon:就是負載均衡+RestTemplate呼叫
RestTemplate的常用方法解析:
1.返回Object物件 2.getForEntity()返回的是ResponseEntity物件Rabbion的核心元件IRule介面: IRule:根據特定演算法從服務列表中選取一個要訪問的服務(有以下7種演算法) 1.com.netflix.loadbalancer.RoundRobinRule:輪詢 2.com.netflix.loadbalancer.RandomRule:隨機 3.com.netflix.loadbalancer.RetryRule:先安裝RoundRobinRule的策略獲取服務,如果獲取服務失敗,則在指定時間內進行重試,獲取可用服務 4.WeightedResponseTimeRule:對RoundRobinRule的擴充套件,響應速度越快的示例選擇權重越大,月容易被選中 5.BestAvailableRule:會先過濾掉多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最小的服務 6.AvailabilityFilteringRule:會先過濾掉故障例項,再選擇併發較小的例項 7.ZoneAvoidanceRule:預設規則,複合判斷Server所在的區域的效能和server的可用性選擇伺服器 重點1:ribbon的負載均衡策略更換(ribbon的預設負載演算法是輪詢) pom檔案的解釋: 因為在客戶端引入了: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> spring-cloud-starter-netflix-eureka-client裡包含有 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency> 如圖所示:無需再單獨引入ribbon的包
1.注意點,ribbon選擇自己的負載方法時,需要建立自己的配置類,該配置類不能在springboot的包掃描範圍內!
1.在自定義配置類中程式碼如下: @Configuration public class MyRule { @Bean public RandomRule getRandomRule() //重點1:隨機策略 return new RandomRule(); } } 2.在springboot啟動類上加上該註解:@RibbonClient 1.value:表示呼叫的服務在eureka的註冊名稱,configuration:是指自定義的配置類位置 @SpringBootApplication @EnableEurekaClient @RibbonClient(value = "CLOUD-PROVIDER",configuration = MyRule.class) public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class, args); } }
如何編寫自己的負載均衡
原理解析:
1.主要用到的是:List<ServiceInstance> instances =discoveryClient.getInstances(serverName)根據服務註冊中心中的註冊服務名稱獲取服務例項
2.根據下表獲取到具體的ServiceInstance服務例項,String uri = instances.get(index).getUri().toString(),獲取遠端呼叫的uri即(http://192.168.137)
3.需要考慮的是代表訪問次數的數字執行緒安全問題,因為會有多個客戶端呼叫更改該數字:這裡涉及到了CAS和自旋解鎖等問題,等後面學習了JUC會明白
具體的程式碼設計如下:設計自己的輪詢演算法
1.負載均衡的介面
//傳入遠端服務的名稱,獲取到具體服務例項的URI
public interface MyLB {
String getUri(String serverName);
}
2.介面實現如下:這就是簡單的輪詢演算法,可以在此基礎上加上自己的邏輯等等,
但重點是:
1.discoveryClient獲取服務相關資訊
2.AtomicInteger:CAS和自旋解鎖等JUC知識
@Component
@Slf4j
public class MyLbImp implements MyLB{
//重點1:使用discoveryClient獲取服務相關資訊
@Resource
private DiscoveryClient discoveryClient;
//重點2:使用AtomicInteger執行緒安全的去自增數字
private AtomicInteger atomicInteger;
public MyLbImp() {
this.atomicInteger = new AtomicInteger(0);
}
@Override
public String getUri(String serverName) {
List<ServiceInstance> instances = discoveryClient.getInstances(serverName);
int size = instances.size();
int current;
int next;
do {
current = atomicInteger.get();
next = current >= Integer.MAX_VALUE ? 0 : current + 1;
} while (!atomicInteger.compareAndSet(current, next));
log.info("current:" + current + " next:" + next);
int index = next % size;
String uri = instances.get(index).getUri().toString();
log.info("訪問URI:" + uri);
return uri;
}
}
3.控制層呼叫:
@Resource
private MyLB myLB;
public CommResult queryUserById(@PathVariable("id") int id){
log.info("客戶端根據id查詢使用者,使用者id:"+id);
//重點1:根據服務名稱獲取對應的輪詢訪問地址!
String uri=myLB.getUri("PRODUCER-USER-API") + "/producer/queryUserById/" + id;
log.info("訪問路徑:"+uri);
CommResult result = restTemplate.getForObject(uri, CommResult.class);
return result;
}