一、負載均衡
負載均衡是分佈式系統架構設計必須考慮的因素之一。負載均衡指的是將請求均勻分攤到多個操作單元上執行,關鍵在於均勻。均與只是負載均衡的策略之一,可以根據不同的策略來達到最佳的性能。
負載均衡有兩種模式,一種是集中式負載均衡,在消費者和服務提供方之間使用獨立代理進行負載,例如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