快速入門全棧 - 13 SpringCloud 負載均衡與熔斷器

一、負載均衡

負載均衡是分佈式系統架構設計必須考慮的因素之一。負載均衡指的是將請求均勻分攤到多個操作單元上執行,關鍵在於均勻。均與只是負載均衡的策略之一,可以根據不同的策略來達到最佳的性能。

負載均衡有兩種模式,一種是集中式負載均衡,在消費者和服務提供方之間使用獨立代理進行負載,例如Nginx;另一種是客戶端負載,根據自己的請求情況做負載,Ribbon就是Netflix開源的一款負載均衡的軟件。客戶端負載由客戶端決定來調用哪個服務,而集中式負載均衡由獨立的代理端來決定調用哪個服務。

二、SpringCloud Ribbon

1. Ribbon

Ribbon是Netflix的負載均衡項目,爲客戶端通信提供支持,有以下的特性

  • 負載均衡器,支持插拔式負載均衡規則
  • 支持HTTP、TCP、UCP等協議
  • 繼承負載均衡功能的客戶端

Ribbon有以下主要模塊:

  • ribbon-loadbalancer:負載均衡模塊,可獨立使用,集成了負載均衡算法
  • ribbon-eureka:基於Eureka封裝
  • ribbon-transport:基於Netty實現多協議支持
  • ribbon-httpclient:基於httpclient封裝REST客戶端,繼承了負載均衡模塊

在使用的時候,客戶端通過負載均衡器,來決定調用哪個集羣節點上的服務。

2. RestTemplate

在實際開始使用Ribbon之前,我們再看一下什麼是RestTemplate。RestTemplate是Spring提供的訪問Rest服務的接口,提供了簡單的API來調用Http服務,大大提高客戶端編寫效率。

Rest是一種軟件架構規範,強調HTTP以資源爲中心,規範了URI和HTTP請求動作,例如

CRUD請求 普通CRUD restfulCRUD
查詢 getStudent student --get
添加 addStudent?xxxx student --post
修改 updateStudent?id=xx student --put
刪除 delStudent?id=xx student --delete

RestTemplate本身不具有負載均衡的功能,如果需要,則需要添加@LoadBalanced註解。RestTemplate有如下的方法

HTTP method RestTemplate methods
DELETE delete
GET getForObject
getForEntity
HEAD headForHeaders
OPTIONS optionsForAllow
POST postForLocation
postForObject
PUT put
any exchange
execute

GET請求

// 1.getForObject
User user1 = this.restTemplate.getForObject(uri, User.class);
// 2.getForEntity
ResponseEntity<User> responseEntity1 = this.restTemplate.getForEntity(uri, User.class);
HttpStatus statusCode = responseEntity1.getStatusCode();
HttpHeaders header = responseEntity1.getHeaders();
User user2 = responseEntity1.getBody();
// 3.exchange
RequestEntity requestEntity = RequestEntity.get(new URI(uri)).build();
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
User user3 = responseEntity2.getBody();

POST請求

// 1. postForObject
User user1 = this.restTemplate.postForObject(uri, user, User.class);
// 2. postForEntity
ResponseEntity<User> repsonseEntity1 = this.restTemplate.postForEntity(uri, user, User.class);
// 3.exchange
RequestEntity<User> requestEntity = RequestEntity.post(new URI(uri)).body(user);
ResponseEntity<User> responseEntity2 = this.restTemplate.exchange(requestEntity, User.class);
3. Ribbon + RestTemplate實戰

下面我們來在代碼中查看客戶端如何使用Ribbon和RestTemplate。首先我們新建一個SpringBoot應用並添加依賴

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

然後我們要寫明服務的調用

@Autowired
RestTemplate restTemplate;

String serverUrl = "xxx";

@GetMapping("/consumer")
public String consumer(String word){
	ResponseEntity<String> entity = restTemplate.getForEntity(serverUrl + "/hello?word={1}", 
																String.class, word);
	return "調用服務返回:" + entity.getBody();
}

我們還需要配置RestTemplate

@Bean
@LoadBalanced
RestTemplate restTemplate(){
	return new RestTemplate();
}

三、SpringCloud Feign

Feign是netflix開發的聲明式、模塊化的HTTP客戶端。在SpringCloud中,使用Feign非常的簡單,只需要創建一個接口,並且在接口上添加一些註解即可。Spring Cloud對Feign進行了增強,使其支持了Spring MVC的註解,並整合了Ribbon和Eureka。

下面我們在代碼中來看如何使用Feign。首先引入依賴

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

編寫接口類

@FeignClient("SERVER-PROVIDE")
public interface HelloFeignService{
	@RequestMapping("/hello")
	public String hello(@RequestParam("word") String word){
		// xxx
	}
}

然後按普通的接口類來調用即可

最後記得要在啓動類中添加註解@EnableFeignClients

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@Slf4j
public class ConsumerApplication{
	public static void main(String[] args) throws Exception{
		StringApplication.run(ConsumerApplication.class, args);
		log.info("Consumer服務啓動");	
	}
}

四、SpringCloud Hystrix

1. 服務熔斷

SpringCloud Hystrix負責熔斷處理。在微服務中,由於存在很多個微服務,各個微服務通過網絡進行通訊,難免會出現依賴關係,若某一個單元出現故障,就很容易因依賴關係而引發故障的蔓延,造成“雪崩效應”,最終導致整個系統的癱瘓。

爲了解決雪崩效應,我們有以下幾種解決方法:

  • 請求設置超時時間
  • 使用熔斷器模式:防止級聯錯誤,問題服務隔離

熔斷器就像是保險絲,如果保險絲斷掉了,電路就無法運行了。正常情況下,熔電器是關閉的,可正常請求依賴服務。當一段時間內,請求失敗率到達一定閾值,熔斷器就會打開,此時,不會再去請求依賴的服務。熔斷器打開一段時間之後,會自動進入半開狀態,此時,熔斷器可允許一個請求訪問依賴的服務,如果請求調用成功,則關閉熔斷器,否則繼續保持打開。

2. SpringCloud Hystrix

Hystrix是Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或第三方庫,防止級聯失敗,從而提升系統的可用性和易錯性。Hystrix的容錯機制如下:

  • 包裹請求:使用HystrixCommand包裹對以來的調用邏輯,每個命令在獨立線程中執行(命令模式)
  • 跳閘機制:當某服務的錯誤率超過一定閾值的時候,Hystrix可以手動或者自動跳閘,停止請求該服務一段時間
  • 資源隔離:Hystrix爲每個以來都維護了一個小型的線程池,如果該線程池已滿,發往該以來的請求就立即拒絕,而不是排隊等候,從而加速判定失敗
  • 監控:Hystrix可以近乎實時的監控運行指標和配置的變化。如成功、失敗、超時、被拒絕的請求等
  • 回退機制:當請求失敗、超時、被拒絕,或者當斷路器打開的時候,執行回退邏輯,可自定義
  • 自我修復:斷路器打開一段時間後,會自動進入半開狀態,斷路器打開、關閉、半開的邏輯轉換
3. Hystrix實戰

我們在使用Hystrix的時候,首先要定義依賴

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

然後修改控制層,添加@HystrixCommand註解

@GetMapping("/consumer")
@HystrixCommand(fallbackMethod = "consumerFallback")
public String consumer(String word){
	ResponseEntity<String> entity = restTemplate.getForObject(serverUrl + "hello?word={1}",
																		String.class,word);
	return "服務返回值爲: " + entity.getBody();
}

public String consumerFallback(String word){
	return "發生熔斷";
}

最後要在啓動類添加@EnableCircuitBreaker註解

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@Slf4j
public ConsumerApplication{
	public static void main(String[] args){
		SpringApplication.run(ConsumerApplication.class, args);
		log.info("服務啓動");
	}
}
4. Hystrix Dashboard

Hystrix還有一個監控服務的服務,叫做Dashboard。Dashboard還需要新添加依賴

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-actuator</artifactId>
</dependency>

我們在application.yml中定義服務的端口,並在啓動類中添加註解@EnableHystrixDashboard。啓動服務後,輸入URL:http://localhost:端口號/hystrix即可訪問Dashboard的主頁面,輸入要監控的服務URL即可,要記得在URL最後添加.stream後綴。


我和幾位大佬建立了一個微信公衆號,歡迎關注後查看更多技術乾貨文章
歡迎加入交流羣QQ1107710098
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章