簡體   English   中英

Spring Reactor Webflux 調度程序並行

[英]Spring Reactor Webflux Scheduler Parallelism

對於完全非阻塞的端到端響應式調用,是否建議顯式調用 publishOn 或 subscribeOn 來切換調度程序? 對於 CPU 消耗或非消耗任務,總是使用並行通量來優化性能是否有利?

值得說明的是,我假設這里的上下文是 Webflux 而不是一般的反應器(因為問題是這樣標記的。)如果我們在不考慮 Webflux 的情況下談論通用反應器用例,那么建議當然會有很大差異。

對於完全非阻塞的端到端響應式調用,是否建議顯式調用 publishOn 或 subscribeOn 來切換調度程序?

一般建議是不要顯式調用這些方法,除非您有理由這樣做。 (在正確的上下文中使用它們並沒有錯,但這樣做“僅僅因為”可能不會帶來任何好處。)

對於 CPU 消耗或非消耗任務,總是使用並行通量來優化性能是否有利?

這取決於您要實現的目標,以及“CPU 消耗”(或 CPU 密集型)任務的含義。 請注意,我在這里談論的是真正的 CPU 密集型任務,而不是阻塞代碼 - 在這種情況下,我理想地將 CPU 密集型部分分配給另一個微服務,使您能夠根據需要進行擴展,與您的 Webflux 服務分開。

使用並行通量(並在並行調度程序上運行)應該使用所有可用的內核來處理數據——這很可能會導致處理得更快。 但請記住,默認情況下,您還為每個內核運行一個事件循環,因此您基本上從事件循環中“竊取”了一些可用容量以實現這一目標。 這是否理想取決於您的用例,但通常不會帶來太多好處。

相反,我推薦兩種方法:

  • 如果您可以將 CPU 密集型任務分解為小的、低強度的塊,請這樣做 - 然后您可以將其保留在事件循環中。 這允許事件循環保持及時運行,同時這些 CPU 密集型任務按其可能的方式安排。
  • 如果您無法將其分解,請啟動一個單獨的調度程序(可以選擇具有低優先級,因此不太可能從事件循環中竊取資源),然后將所有 CPU 密集型任務分配給該調度程序。 這具有創建更多線程的缺點,但又使事件循環保持空閑。 默認情況下,您將擁有與事件循環的內核一樣多的線程 - 您可能希望減少線程數,以便為您的“CPU 密集型”調度程序提供更多可使用的內核。

對於完全非阻塞的端到端響應式調用,是否建議顯式調用 publishOn 或 subscribeOn 來切換調度程序?

當您將數據發布到下游時使用publishOn ,而當您從上游消費數據時使用subscribeOn 所以這真的取決於你想從事什么樣的工作。

對於 CPU 消耗或非消耗任務,總是使用並行通量來優化性能是否有利?

絕對不是,考慮這個例子:

Flux.range(1, 10)
        .parallel(4)
        .runOn(Schedulers.parallel())
        .sequential()
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

上面的代碼完全是浪費,因為i幾乎會立即被處理。 以下代碼將比上面的代碼執行得更好:

Flux.range(1, 10)
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

現在考慮一下:

public static <T> T someMethodThatBlocks(T i, int ms) {
    try { Thread.sleep( ms ); }
    catch (InterruptedException e) {}
    return i;
}

// some method here
Flux.range(1, 10)
        .parallel(4)
        .runOn(Schedulers.parallel())
        .map(i -> someMethodThatBlocks(i, 200))
        .sequential()
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

output 類似於:

 [210,3]  [5,1]  [0,2]  [0,4]  [196,6]  [0,8]  [0,5]  [4,7]  [196,10]  [0,9] 

如您所見,第一個響應在210毫秒后出現,然后是 3 個響應,其間經過的時間接近0 該循環一次又一次地重復。 這是您應該使用平行助焊劑的地方。 請注意,創建更多數量的線程並不能保證性能,因為當有更多數量的線程時,上下文切換會增加很多開銷,因此應該在部署之前對代碼進行測試。 如果有很多阻塞調用,每個 cpu 有超過 1 個線程可能會提高性能,但如果調用是 cpu 密集型的,那么每個 cpu 有多個線程會由於上下文切換而降低性能。

所以總而言之,它總是取決於你想要實現什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM