使用Kubernetes API進行分頁和異步調用
- Kubernetes
1.簡介
在本教程中,我們將繼續探索Kubernetes API for Java。這次,我們將重點介紹它的兩個功能:分頁和異步調用。
2.分頁
簡而言之,分頁使我們能夠以塊(也稱為頁面)的形式對較大的結果集進行迭代,因此使用了此方法。在Kubernetes Java API的上下文中,此功能可用於返回資源列表的所有方法。這些方法始終包含兩個可選參數,可用於迭代結果:
-
limit
:單個API調用中返回的最大項目數 -
continue
:continuation token
,它告訴服務器返回的結果集的起點
使用這些參數,我們可以遍歷任意數量的項目,而不會對服務器造成太大的壓力。更好的是,客戶端保存結果所需的內存量也受到限制。
現在,讓我們看看如何使用這些參數使用此方法獲取集群中所有可用吊艙的列表:
ApiClient client = Config.defaultClient();
CoreV1Api api = new CoreV1Api(client);
String continuationToken = null;
do {
V1PodList items = api.listPodForAllNamespaces(
null,
continuationToken,
null,
null,
2,
null,
null,
null,
10,
false);
continuationToken = items.getMetadata().getContinue();
items.getItems()
.stream()
.forEach((node) -> System.out.println(node.getMetadata()));
} while (continuationToken != null);
listPodForAllNamespaces()
API調用的第二個參數包含繼續令牌,第五個是limit
參數。雖然該limit
通常只是一個固定值,但continue
需要一些額外的努力。
對於第一個調用,我們發送一個null
值,向服務器發出信號,這是分頁請求序列的第一個調用。收到響應後,我們將從相應的列表元數據字段中獲取要使用continue
當沒有更多結果可用時,此值將為null
,因此我們使用此事實來定義迭代循環的退出條件。
2.1 分頁陷阱
分頁機制非常簡單,但是我們必須牢記一些細節:
- 目前,該API不支持服務器端排序。鑑於當前缺乏存儲級別的排序支持,這不太可能很快改變
- 兩次調用之間的所有調用參數(
continue
除外)都必須相同 -
continue
值必須視為不透明的句柄。我們永遠不要對它的價值做任何假設 - 迭代是單向的
.
我們無法使用先前收到的continue
代幣 - 即使返回的列表元數據包含
remainingItemCount
字段,其值也不可靠,也不為所有實現所支持
2.2 列出數據一致性
由於Kubernetes集群是一個非常動態的環境,因此與分頁調用序列關聯的結果集有可能在被客戶端讀取時被修改。在這種情況下,Kubernetes API的行為如何?
如Kubernetes文檔中所述,列表API支持resourceVersion
參數,該參數與resourceVersionMatch
一起定義如何選擇要包含的特定版本。但是,對於分頁結果集的情況,其行為始終是相同的:“繼續令牌,精確”。
這意味著返回的資源版本對應於分頁列表調用開始時可用的資源版本。儘管此方法提供了一致性,但將不包括隨後修改的結果。例如,當我們完成對大型集群中所有Pod的迭代時,其中一些可能已經終止。
3.異步呼叫
到目前為止,我們已經以同步方式使用Kubernetes API,這對於簡單的程序來說很好,但是從資源使用的角度來看並不是很有效,因為它會阻塞調用線程,直到我們從集群接收到響應並對其進行處理為止。例如,如果我們開始在GUI線程中進行這些調用,則此行為將嚴重損害應用程序的響應能力。
幸運的是,該庫支持基於回調的異步模式,該模式可立即將控件返回給調用者。
在檢查CoreV1Api
類時,我們會注意到,對於每個同步xxx()
方法,還有一個xxxAsync()
變體。 listPodForAllNamespaces()
的異步方法是listPodForAllNamespacesAsync()
。參數是相同的,只是為回調實現添加了一個額外的參數。
3.1 回調詳細信息
回調參數對象必須實現通用接口ApiCallback<T>,
該接口僅包含四個方法:
-
onSuccess:
僅當呼叫成功時才調用。第一個參數類型與同步版本將返回的參數相同 -
onFailure:
調用服務器時發生錯誤,或者答复包含錯誤代碼 -
onUploadProgress
:在上載期間調用。我們可以使用此回調在冗長的操作中向用戶提供反饋 -
onDownloadProgress
:同onUploadProgress
,但下載
異步調用也不會返回常規結果。相反,它們返回OkHttp的(Kubernetes API使用的底層REST客戶端) Call
實例,該實例用作正在進行的調用的句柄。我們可以使用該對象輪詢完成狀態,或者,如果需要,可以在完成之前取消它。
3.2 異步呼叫示例
可以想像,在任何地方實現回調都需要大量樣板代碼。為了避免這種情況,我們將使用一個調用助手來簡化此任務:
// Start async call
CompletableFuture<V1NodeList> p = AsyncHelper.doAsync(api,(capi,cb) ->
capi.listNodeAsync(null, null, null, null, null, null, null, null, 10, false, cb)
);
p.thenAcceptAsync((nodeList) -> {
nodeList.getItems()
.stream()
.forEach((node) -> System.out.println(node.getMetadata()));
});
// ... do something useful while we wait for results
在這裡,幫助程序包裝了異步調用調用,並將其調整為更標準的CompletableFuture
。這使我們可以將其與其他庫一起使用,例如Reactor Project中的庫。在此示例中,我們添加了一個完成階段,該階段將所有元數據打印到標準輸出中。
和往常一樣,在處理期貨時,我們必須意識到可能會出現的並發問題。該代碼的在線版本包含一些調試日誌,這些日誌清楚地表明,即使對於這個簡單的代碼,也至少使用了三個線程:
-
main
線程,
啟動異步調用 - OkHttp的線程用於進行實際的HTTP調用
- 完成線程,用於處理結果
4 結論
在本文中,我們已經看到瞭如何在Kubernetes Java API中使用分頁和異步調用。