服務雪崩的6種解決方案(基於ribbon)
第一節,服務雪崩簡介
服務雪崩就是:一個服務不可用,導致一系列服務不可用,而這種後果往往無法預料。
造成雪崩原因可以歸結為以下三個:
1,服務提供者不可用(硬體故障,程式bug,快取擊穿,使用者大量請求)
2,重試加大流量(使用者重試,程式碼邏輯重試)
3,服務呼叫者不可用(同步等待造成的資源耗盡)
解決方案有如下5個,其中隔離包括兩種:
1,降級:超時降級,資源不足時(執行緒或訊號量)降級,降級後可以配合降級介面放回託底資料。實現一個fallback方法,當請求後端服務出現異常的時候,可以使用fallback方法返回的值;
2,隔離(執行緒池隔離和訊號量隔離):限制呼叫分散式服務的資源使用,某一個呼叫的服務出現問題不會影響其他服務呼叫;
3,熔斷:當失敗率(如因網路故障或超時 造成的失敗率高)達到閾值自動觸發降級,熔斷器觸發的快速失敗會進行快速恢復;
4,快取:提供了請求快取;
5,請求合併:提供了請求合併。
下面的雪崩解決方案是基於ribbon的,即在傳送請求的時候,需要自己手工構造遠端呼叫。
解決方案
服務降級
場景:比如一個訂單系統請求一個庫存系統,一個請求發過去,由於各種原因,網路超時,在規定的時間內沒有返回響應結果,這個時候更多的請求過來了,不斷地請求庫存服務,不斷的建立執行緒,由於沒有返回,也就沒有資源的釋放。時間一長,必將耗盡系統資源,導致系統崩潰。本來你的訂單系統好好的,但是請求了一個有問題的庫存系統,導致訂單系統也崩潰了,然後訂單系統又不斷呼叫其他的依賴系統,然後導致其他依賴系統也崩潰了,造成服務雪崩。這個時候hystrix可以實現快速失敗。
如果hystrix在一段時間內偵測到許多類似的錯誤,會強迫其以後的多個呼叫快速失敗,不再訪問遠端伺服器,從而防止應用程式不斷地嘗試執行可能會失敗的操作而導致系統資源被耗盡。這時hystrix進行fallback操作來服務降級。
Fallback相當於是降級操作。對於查詢操作,我們可以實現一個fallback方法,當請求後端服務出現異常的時候,可以使用fallback方法返回的值。fallback方法的返回值一般是預設的值或者是從快取中得到的值,通知後面的請求服務暫時不可用了。
package com.twf.e.book.consumer.hystrix.ribbon.fallback.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
import com.twf.e.book.consumer.hystrix.ribbon.fallback.domain.Product;
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; // ribbon的負載均衡客戶端
// @HystrixCommand這個註解指定了fallbackMethod為fallback。
@HystrixCommand(fallbackMethod="fallback",commandProperties={
@HystrixProperty(name=HystrixPropertiesManager.FALLBACK_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS,value="15")
})
public List<Product> listProduct() {
ServiceInstance si = loadBalancerClient.choose("e-book-product");
StringBuffer sb = new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef = new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, typeRef);
List<Product> plist = resp.getBody();
return plist;
}
// 當呼叫遠端服務出現異常的時候,會呼叫這個方法
public List<Product> fallback() {
List<Product> list = new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
服務請求快取
比如一個請求過來請求我userId=1的資料,你後面的請求也過來請求同樣的資料,這時我不會繼續走原來的那條請求鏈路了,而是把第一次請求快取過了,把第一次的請求結果返回給後面的請求,這樣在一定程度上減少了請求的次數,降低網路資源的壓力,減少雪崩發生的概率。
@EnableCaching // 開啟快取
@EnableCircuitBreaker // 開啟服務降級斷路器
@EnableEurekaClient
@SpringBootApplication
public class ConsumerHystrixRibbonCacheApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerHystrixRibbonCacheApplication.class, args);
}
}
服務請求合併
請求合併就是將單個請求合併成一個請求,去呼叫服務提供者,從而降低服務提供者負載的,一種應對高併發的解決方法。
在傳統的執行緒池中,有多少個請求就啟動多少個執行緒,比如上圖有6個請求就會啟動6條執行緒,這6條執行緒再去請求provider。如果一下子來了1000個請求,那麼執行緒池中的佇列就會被撐爆。這樣怎麼辦呢?我們就來做一個請求合併。
現在將6個請求合併成一個請求,再由執行緒池執行,這樣就可以解決執行緒池被撐爆的局面。
原理:通過請求合併器設定延遲時間,將延遲時間內的多個請求的請求引數取出來,封裝成一個引數list,作為batchMethod指定的方法(比如該方法名稱為batchProduct)的引數,然後呼叫這個batchProduct()方法。返回的物件list再通過一個方法(mapResponseToRequests方法),按照請求的次序將結果物件對應的裝到Request對應的Response中返回結果。
package com.twf.e.book.consumer.hystrix.ribbon.batch.service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import org.springframework.stereotype.Service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.twf.e.book.consumer.hystrix.ribbon.batch.domain.Product;
@Service
public class ProductService {
// 利用hystrix合併請求
@HystrixCollapser(batchMethod = "batchProduct", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL, collapserProperties = {
// 請求時間間隔在20ms之內的請求會被合併為一個請求
@HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
// 設定觸發批處理執行之前,在批處理中允許的最大請求數
@HystrixProperty(name = "maxRequestsInBatch", value = "200") })
public Future<Product> getProduct(Integer id) {
System.out.println("---------" + id + "----------");
return null;
}
@HystrixCommand
public List<Product> batchProduct(List<Integer> ids) {
for (Integer id : ids) {
System.out.println(id);
}
List<Product> list = new ArrayList<Product>();
list.add(new Product(1, "登山包"));
list.add(new Product(2, "登山杖"));
list.add(new Product(3, "衝鋒衣"));
list.add(new Product(4, "帳篷"));
list.add(new Product(5, "睡袋"));
list.add(new Product(6, "登山鞋"));
return list;
}
}
服務熔斷
熔斷機制相當於電路的跳閘功能。
例如:我們可以配置熔斷策略為當請求錯誤比例在10s內>50%時,該服務將進入熔斷狀態,後續請求都會進入fallback。
隔離技術之執行緒池隔離
場景:consumer端有一個執行緒池,裡面有兩個介面,短時間內介面A有10萬次請求,介面B有10次請求,由於介面A的大併發量導致整個執行緒池癱瘓,也就會導致B介面的不可用。最後整個consumer端不可用。
解決的方法:進行執行緒池隔離。
給A介面單獨設定一個執行緒池,給B介面也設定一個執行緒池,這樣當A介面癱瘓之後,不會影響B介面的執行。
通過每次都開啟一個單獨執行緒執行。它的隔離是通過執行緒池,即每個隔離粒度都是個執行緒池,互相不干擾。
執行緒池隔離方式,等於多了一層的保護措施,可以通過hytrix直接設定超時,超時後直接返回。
package com.twf.e.book.consumer.hystrix.ribbon.threadpool.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.twf.e.book.consumer.hystrix.ribbon.threadpool.domain.Product;
@Service
public class ProductService {
@Autowired
private LoadBalancerClient loadBalancerClient; // ribbon的負載均衡客戶端
@HystrixCommand(groupKey="e-book-product",commandKey="listProduct",
threadPoolKey="e-book-product",
threadPoolProperties={
@HystrixProperty(name="coreSize",value="30"), // 執行緒池大小
@HystrixProperty(name="maxQueueSize",value="100"), // 最大佇列長度
@HystrixProperty(name="keepAliveTimeMinutes",value="2"), // 執行緒存活時間
@HystrixProperty(name="queueSizeRejectionThreshold",value="15") // 拒絕請求
},
fallbackMethod = "fallback")
public List<Product> listProduct() {
ServiceInstance si = loadBalancerClient.choose("e-book-product");
StringBuffer sb = new StringBuffer("");
sb.append("http://");
sb.append(si.getHost());
sb.append(":");
sb.append(si.getPort());
sb.append("/product/list");
System.out.println(sb.toString());
RestTemplate restTemplate = new RestTemplate();
ParameterizedTypeReference<List<Product>> typeRef = new ParameterizedTypeReference<List<Product>>(){};
ResponseEntity<List<Product>> resp = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, typeRef);
List<Product> plist = resp.getBody();
return plist;
}
// 當呼叫遠端服務出現異常的時候,會呼叫這個方法
public List<Product> fallback() {
List<Product> list = new ArrayList<Product>();
list.add(new Product(-1,"fallback"));
return list;
}
}
轉載自:
https://blog.csdn.net/tanwenfang/article/details/86478786
todo,還有很多,這只是我挑能懂的複製了些
相關文章
- 一種基於柔性事務的分散式事務解決方案設計探究分散式
- 基於RocketMq的分散式事務解決方案MQ分散式
- Spring Cloud OpenFeign:基於Ribbon和Hystrix的宣告式服務呼叫SpringCloud
- 微服務架構 | 4.1 基於 Ribbon 的負載均衡詳解微服務架構負載
- hystrix-go 服務雪崩解決利器Go
- 基於代理服務的介面合併方案
- 關於AppDelegate瘦身的多種解決方案APP
- 基於i.MX6ULL的水質監測儀解決方案
- ES6 中的 三種非同步解決方案非同步
- 什麼是快取雪崩?伺服器雪崩的場景與解決方案快取伺服器
- React 服務端渲染方案完美的解決方案React服務端
- Redis 快取擊穿、穿透、雪崩的原因以及解決方案Redis快取穿透
- 使用rsync服務+nas方案解決伺服器儲存安全性問題的一種方案伺服器
- React 服務端渲染完美的解決方案React服務端
- 基於 Swoole 搭建 WebSocket 服務詳解Web
- 基於可靠訊息方案的分散式事務(四):接入Lottor服務分散式
- 分散式事務解決方案——柔性事務與服務模式分散式模式
- 微服務分散式事務4種解決方案實戰微服務分散式
- 關於0xc000007b的一種解決方案
- Redis系列 - 快取雪崩、擊穿、穿透及解決方案Redis快取穿透
- Redis 快取穿透、快取雪崩原理及解決方案Redis快取穿透
- 《白皮書》:公共服務中人臉安全解決方案
- 乾貨:基於scss的主題配色解決方案CSS
- Verizon和Novell推出基於雲的安全解決方案
- 基於mpvue的小程式markdown適配解決方案Vue
- AntV G6 關於多邊繪製的解決方案
- 常用的分散式事務解決方案介紹有多少種?分散式
- 從不可描述的服務雪崩到初探Hystrix
- 分散式事務解決方案(三)【基於可靠訊息的最終一致性(獨立訊息服務實現)】分散式
- 【FAQ】整合分析服務的常見問題及解決方案
- IT技術助力於業務流程:RPA解決方案的策
- 【FAQ】推送服務常見問題及解決方案
- combineLatest 使用的一個陷阱和基於 debounceTime 的解決方案
- 基於.NET的程式讀取Excel檔案的解決方案Excel
- 基於springboot的ShardingSphere5.X的分庫分表的解決方案之資料加密之已上線業務的解決方案(十二)Spring Boot加密
- 基於Spring的Web專案執行時切換資料來源的一種解決方案SpringWeb
- 爬蟲受限的三種解決方案爬蟲
- 高精度定位的幾種解決方案