1. 概述
`quarkus-load-shedding 擴展提供了一種機制,在高流量條件下主動拒絕請求,以防止應用程序或服務內的系統過載。該庫還暴露了關鍵的配置屬性,以幫助自定義負載削減的處理方式。
在本教程中,我們將學習如何將此擴展集成到我們的 Quarkus 應用程序中,並自定義其配置以滿足我們的特定需求。`
2. 安裝配置
為了演示 quarkus-load-shedding 擴展的關鍵功能,我們將使用兩個 Web 資源作為 REST 接口暴露:FibonacciResource 和 FactorialResource。 調用這些資源時,它們會在返回結果之前引入 1 到 15 秒的隨機響應延遲。
接下來,讓我們將擴展作為依賴項添加到我們的 Quarkus 項目中:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-load-shedding</artifactId>
</dependency>
當我們啓動應用時,如果處於開發模式,我們應該能夠在開發者 UI 上看到擴展程序:
./mvnw quarkus:dev截至寫作時,此擴展程序仍處於實驗階段:
3. 默認負載削減
一旦添加了擴展,它將默認啓用。它將使用默認配置開始削減請求。
請編輯 application.properties 文件,以調整此配置,使其更嚴格:
quarkus.load-shedding.enabled=true
quarkus.load-shedding.max-limit=10
quarkus.load-shedding.initial-limit=5此配置設置了允許的併發請求的初始和最大限制。<em title="max-limit">max-limit</em> 設置併發請求的上限,而<em title="initial-limit">initial-limit</em> 主要用於計算可接受的隊列大小。
現在,讓我們通過 JMeter 測試我們的配置。在 JMeter 中,我們設置了 7 個用户線程並行運行兩次,並設置了 5 秒的 ramp-up 週期:
運行此測試計劃,我們得到下面的結果,顯示 HTTP 503 錯誤率在兩個端點之間均勻分佈。
| Label | # Samples | Average | Min | Max | Std. Dev. | Error % |
|---|---|---|---|---|---|---|
| Fibonacci HTTP Request | 14 | 5735 | 2 | 12613 | 4517.63 | 28.571% |
| Factorial HTTP Request | 14 | 5195 | 1 | 11470 | 4133.69 | 28.571% |
| TOTAL | 28 | 5465 | 1 | 12613 | 4338.33 | 28.571% |
<em title="quarkus-load-shedding">quarkus-load-shedding</em> 擴展根據 <em title="application.properties">application.properties</em> 中的配置,無差別地拒絕請求。
4. 自定義負載削減
<em>quarkus-load-shedding</em> 擴展暴露了一些配置,使我們能夠自定義負載削減行為。其中一項功能是能夠在系統負載過高時,優先削減哪些請求。 詳細內容請參見下一小節。
4.1. 請求優先級
首先,讓我們在我們的 application.properties 文件中啓用優先級設置:
# ...
quarkus.load-shedding.priority.enabled=true現在,讓我們提供一個 RequestPrioritizer 的實現,以指定我們的請求優先級:
@Provider
public class LoadRequestPrioritizer implements RequestPrioritizer<HttpServerRequestWrapper> {
@Override
public boolean appliesTo(Object request) {
return request instanceof HttpServerRequestWrapper;
}
//...
}我們的 LoadRequestPrioritizer 類被標註為 @Provider 作為 CDI 豆,以便運行時能夠自動發現它。我們還指定它僅處理 HttpServerRequestWrapper 類型的請求。
接下來,我們為特定的目標端點分配優先級:
@Provider
public class LoadRequestPrioritizer implements RequestPrioritizer<HttpServerRequestWrapper> {
//...
@Override
public RequestPriority priority(HttpServerRequestWrapper request) {
String requestPath = request.path();
if (requestPath.contains("fibonacci")) {
return RequestPriority.CRITICAL;
} else {
return RequestPriority.NORMAL;
}
}
}因此,/fibonacci 端點將具有更高的優先級,這意味着 對該端點的請求比其他請求更不容易被拒絕。
4.2. 觸發式負載檢測
由於 quarkus-load-shedding 擴展僅在檢測到系統負載過高時才應用優先級負載削減,接下來,我們模擬 CPU 負載:
@Path("/fibonacci")
public class FibonacciResource {
//...
@PostConstruct
public void startLoad() {
for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {
new Thread(() -> {
while (true) {
Math.pow(Math.random(), Math.random());
}
}).start();
}
}
}首次調用時,FibonacciResource 的 @PostConstruct 觸發了一個 CPU 密集型任務,以確保在測試期間 CPU 負載保持在一定水平。重啓應用程序後,讓我們觸發一個初始請求到 /fibonacci 端點:
curl -X GET http://localhost:8080/api/fibonacci?iterations=9接下來,我們使用相同的參數再次執行 JMeter 測試計劃,生成了以下結果:
| Label | # Samples | Average | Min | Max | Std. Dev. | Error % |
|---|---|---|---|---|---|---|
| Fibonacci HTTP Request | 14 | 5848 | 9 | 13355 | 4280.47 | 14.286% |
| Factorial HTTP Request | 14 | 6915 | 10 | 14819 | 5905.41 | 28.571% |
| TOTAL | 28 | 6381 | 9 | 14819 | 5184.86 | 21.429% |
如表所示,由於該端點的優先級較高,因此在 /fibonacci 端點上的拒絕率較低。
4.3. 系統探測率
probeFactor 配置項影響擴展程序檢查系統請求處理能力波動發生的頻率。
默認情況下,probeFactor 設置為 30。為了比較該設置的影響,我們首先在 FibonacciResource 上僅運行一個 JMeter 測試計劃,使用 11 個用户線程:
下面是運行 JMeter 測試計劃後的結果:
| Label | # Samples | Average | Min | Max | Std. Dev. | Error % |
|---|---|---|---|---|---|---|
| Fibonacci HTTP Request | 33 | 8236 | 3 | 14484 | 4048.21 | 9.091% |
| TOTAL | 33 | 8236 | 3 | 14484 | 4048.21 | 9.091% |
正如預期的那樣,只有三個請求(即 33 個樣本乘以 9.091% 的錯誤率)由於我們在 application.properties 文件中將允許的最大併發請求設置為 10 時而被拒絕。
現在,讓我們將 probeFactor 從 30 的默認值增加到 application.properties 文件中:
quarkus.load-shedding.probe-factor=70然後,讓我們使用之前相同的配置重新運行 JMeter 測試,並查看結果:
| 標籤 | # 樣本 | 平均值 | 最小值 | 最大值 | 標準差 | 誤差 % |
|---|---|---|---|---|---|---|
| Fibonacci HTTP 請求 | 33 | 6515 | 11 | 13110 | 3850.50 | 6.061% |
| 總計 | 33 | 6515 | 11 | 13110 | 3850.50 | 6.061% |
這次,只有兩個請求被拒絕。 設置較高的 <em probeFactor 可以降低系統對負載波動敏感度。
4.4. 隊列管理
<em>alphaFactor</em> 和 <em>betaFactor</em> 配置項控制了基於實際請求隊列大小,從初始值到最大限制值的增量和減量方式。要查看它們的效果,請將它們添加到我們的 <em>application.properties</em> 文件中:
quarkus.load-shedding.alpha-factor=1
quarkus.load-shedding.beta-factor=5再次運行上一節中包含 11 個用户線程的 JMeter 測試,我們得到了以下結果:
從結果中可以看出,限制分配是逐步進行的,導致第六次請求被拒絕,即使最大限制尚未達到。
5. 結論
在本文中,我們瞭解到如何將 quarkus-load-shedding 擴展集成到我們的 Quarkus 應用程序中,從而使我們的系統在負載下能夠有效響應。我們還學習瞭如何自定義擴展以滿足我們的需求,通過調整其配置屬性,並對每個屬性的含義有了更深入的理解。