本文探討了我們在軟體專案中放棄反應式架構的決定。我們將深入研究反應式系統的核心原則、非阻塞 I/O 的好處以及反應式方法所面臨的挑戰。
Reactive 包含一系列旨在建立響應式分散式系統和應用程式的原則和指南,其特點是:
反應式系統的一個主要好處是它們使用非阻塞 I/O。這種方法避免了 I/O 操作期間阻塞線程,允許單一線程同時處理多個請求。與傳統的阻塞 I/O 相比,這可以顯著提高系統效率。
在傳統的多執行緒中,阻塞操作對最佳化系統提出了重大挑戰(圖 1)。消耗過多記憶體的貪婪應用程式效率低下,並且會懲罰其他應用程序,通常需要請求額外的資源,如記憶體、CPU 或更大的虛擬機。
圖 1 – 傳統多執行緒
I/O 操作是現代系統不可或缺的一部分,有效管理它們對於防止貪婪行為至關重要。反應式系統採用非阻塞 I/O,使少量的作業系統執行緒能夠處理大量並發 I/O 操作。
雖然非阻塞 I/O 提供了巨大的好處,但它引入了一種不同於傳統框架的新穎的執行模型。響應式程式設計的出現就是為了解決這個問題,因為它可以緩解阻塞操作期間平台執行緒空閒的低效率問題(圖 2)。
圖 2 – 響應式事件循環
Quarkus 利用 Eclipse Vert.x 和 Netty 提供支援的反應式引擎,促進非阻塞 I/O 互動。 Mutiny 是使用 Quarkus 編寫反應式程式碼的首選方法,它採用事件驅動範例,其中反應由接收到的事件觸發。
Mutiny 提供兩種事件驅動和惰性類型:
雖然反應式系統提供了好處,但我們在開發過程中遇到了一些挑戰:
「事實上,閱讀與寫作所花費的時間之比遠遠超過10 比1。我們不斷地閱讀舊程式碼,作為編寫新程式碼的一部分。...[因此,]使其易於閱讀使得寫起來更容易。 ―
Robert C. Martin,《整潔程式碼:敏捷軟體製程手冊》
Multi.createFrom().ticks().every(Duration.ofSeconds(15)) .onItem().invoke(() - > Multi.createFrom().iterable(configs()) .onItem().transform(configuration - > { try { return Tuple2.of(openAPIConfiguration, RestClientBuilder.newBuilder() .baseUrl(new URL(configuration.url())) .build(MyReactiveRestClient.class) .getAPIResponse()); } catch (MalformedURLException e) { log.error("Unable to create url"); } return null; }).collect().asList().toMulti().onItem().transformToMultiAndConcatenate(tuples - > { AtomicInteger callbackCount = new AtomicInteger(); return Multi.createFrom().emitter(emitter - > Multi.createFrom().iterable(tuples) .subscribe().with(tuple - > tuple.getItem2().subscribe().with(response - > { emitter.emit(callbackCount.incrementAndGet()); if (callbackCount.get() == tuples.size()) { emitter.complete(); } }) )); }).subscribe().with(s - > {}, Throwable::printStackTrace, () - > doSomethingUponComplete())) .subscribe().with(aLong - > log.info("Tic Tac with iteration: " + aLong));
Project Loom 是 Java 生態系統的最新開發項目,有望緩解與阻塞操作相關的問題。透過在不更改硬體的情況下創建數千個虛擬線程,Project Loom 可能在許多情況下消除對反應式方法的需求。
「Loom 專案將殺死響應式程式設計」
―布萊恩·戈茨
總之,我們決定放棄反應式架構風格,採用務實的方法來實現專案的長期可維護性。雖然反應式系統提供了潛在的好處,但它們為我們團隊帶來的挑戰超過了我們特定環境中的這些優勢。
重要的是,這種轉變並沒有影響性能。這是一個積極的結果,因為它表明設計良好的非反應式(命令式)架構可以提供必要的效能,而不會帶來與我們案例中的反應式架構相關的複雜性。
展望未來,我們的重點仍然是建立一個程式碼庫,該程式碼庫不僅實用,而且易於所有經驗水平的開發人員理解和維護。這不僅減少了開發時間,也促進了團隊內更好的協作和知識共享。
在下圖中,X 軸 代表我們的程式碼庫在發展過程中不斷增加的複雜性,而 Y 軸 則描述了這些開發變化所需的時間。
以上是為什麼我們從程式碼中放棄反應式系統架構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!