自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

徹底搞懂響應(yīng)式編程

開發(fā) 前端
今天我們系統(tǒng)分析了傳統(tǒng)服務(wù)調(diào)用存在的問題,從而引出響應(yīng)式編程概念和實(shí)現(xiàn)方法。從技術(shù)演進(jìn)的過程和趨勢而言,響應(yīng)式編程的出現(xiàn)有其必然性。

我們知道,系統(tǒng)面對大流量、高并發(fā)的訪問請求時,就可能會出現(xiàn)一系列性能問題,導(dǎo)致服務(wù)喪失了即時的響應(yīng)性。如何時刻確保系統(tǒng)具有應(yīng)對請求壓力的能力,是架構(gòu)設(shè)計的核心問題之一。

經(jīng)典的服務(wù)隔離、限流、降級以及熔斷等機(jī)制能夠在一定程度上確保系統(tǒng)的響應(yīng)性。但這些機(jī)制更多的是從系統(tǒng)架構(gòu)和應(yīng)用部署的角度出發(fā)解決問題,而不是編程技術(shù)本身。今天我們要介紹的是構(gòu)建系統(tǒng)響應(yīng)性的一種嶄新的解決方案,這就是響應(yīng)式編程(Reactive Programming)。

我們知道,傳統(tǒng)的編程模型采用的是同步阻塞式(Blocking)的請求響應(yīng)過程,這是現(xiàn)有各種經(jīng)典解決方案所不得不面對的一種限制。 而響應(yīng)式編程打破了這種限制,采用了異步非阻塞式(Non-Blocking)的編程模型,從而提高服務(wù)的響應(yīng)能力。

這里提到了同步阻塞和異步非阻塞這兩個核心概念,正確理解這兩個概念是你掌握響應(yīng)式編程的前提條件。所以接下來,我們就來看看響應(yīng)式編程技術(shù)是如何基于它們誕生的。

為什么需要響應(yīng)式編程?

如果你使用 Spring 框架開發(fā)過 Web 應(yīng)用程序,那么你一定對下面這種開發(fā)方式非常熟悉:

public Order getRemoteOrderByOrderNumber(String orderNumber) {
      RestTemplate restTemplate = new RestTemplate();
      ResponseEntity<Order> result= restTemplate.exchange(
                    "http://orderservice/orders/{orderNumber}", HttpMethod.GET, null, Order.class, orderNumber);
      Order order= result.getBody();
      processOrder(order);
      return order;
}

這是一個查詢訂單(Order)信息的應(yīng)用場景,我們使用了 Spring 中的 RestTemplate 模板工具類,通過該類所提供的 exchange() 方法對遠(yuǎn)程 Web 服務(wù)所暴露的 HTTP 端點(diǎn)發(fā)起了請求。

這種實(shí)現(xiàn)方式在日常開發(fā)中非常有代表性, 基于 Spring Cloud 開發(fā)的微服務(wù)系統(tǒng),本質(zhì)上,也是通過這種方式完成服務(wù)與服務(wù)之間的遠(yuǎn)程調(diào)用。但是,這個方法實(shí)際上存在明顯的缺陷,因為處理過程是阻塞式的。

正是因為同步阻塞的存在才導(dǎo)致了異步非阻塞相關(guān)技術(shù)的誕生和發(fā)展,進(jìn)而才有了今天要介紹的響應(yīng)式編程技術(shù)。那么,究竟什么是阻塞式呢?

同步阻塞

我們首先來分析代碼中的線程模型,看看問題出在哪里。為了更好的分析整個調(diào)用過程,我們假設(shè)服務(wù)的提供者為服務(wù) A,而服務(wù)的消費(fèi)者為服務(wù) B,那么這兩個服務(wù)的交互過程應(yīng)該是這樣的。

服務(wù) A 和服務(wù) B 的交互過程圖服務(wù) A 和服務(wù) B 的交互過程圖

可以看到,當(dāng)服務(wù) B 向服務(wù) A 發(fā)送 HTTP 請求時,線程 B,只在發(fā)起請求和響應(yīng)結(jié)果的一小部分時間內(nèi)有效使用 CPU,而更多時間則是在阻塞式地等待來自服務(wù) A 中線程的處理結(jié)果。顯然,整個過程的 CPU 利用效率是很低的,很多時間被浪費(fèi)在了 I/O 阻塞上,無法執(zhí)行其他處理過程。

更進(jìn)一步,我們繼續(xù)分析服務(wù) A 中的處理過程。

如果我們采用典型的三層架構(gòu),那么沿著 Web 服務(wù)層->業(yè)務(wù)邏輯層->數(shù)據(jù)訪問層整個調(diào)用鏈路,每一步的操作過程都存在著前面描述的線程等待問題。也就是說,整個技術(shù)棧中的每一個環(huán)節(jié)都可能是同步阻塞的。

這樣的話,整個調(diào)用鏈路的資源利用率都會變低,導(dǎo)致請求的處理過程出現(xiàn)延遲,而喪失了我們想要的即時響應(yīng)性。

Web 應(yīng)用程序三層架構(gòu)Web 應(yīng)用程序三層架構(gòu)

異步非阻塞

為了解決同步阻塞問題,可以引入異步非阻塞的相關(guān)技術(shù)。異步非阻塞技術(shù)能夠通過多線程技術(shù),將整個請求處理過程交由不同線程并行處理,提高了系統(tǒng)資源利用率。

在 Java 世界中,一般會采用回調(diào)(Callback)和 Future 這兩種機(jī)制,但這兩種機(jī)制都存在一定局限性:

回調(diào)的核心問題在于,處理過程會形成一種嵌套結(jié)構(gòu),給代碼的開發(fā)和調(diào)試帶來很大的挑戰(zhàn)。

Future 機(jī)制本質(zhì)上是一種多線程技術(shù),大量線程之間的相互協(xié)作需要頻繁進(jìn)行上下文切換,同樣會導(dǎo)致資源利用效率低下。

其實(shí)引入響應(yīng)式編程技術(shù),我們就可以很好地解決這種類型的問題。

響應(yīng)式編程采用全新的響應(yīng)式數(shù)據(jù)流(Stream),實(shí)現(xiàn)異步非阻塞式的網(wǎng)絡(luò)通信和數(shù)據(jù)訪問機(jī)制,能夠減低不必要的線程等待時間。那么,所謂的響應(yīng)式編程到底是什么樣子的呢?

什么是響應(yīng)式編程?

響應(yīng)式編程技術(shù)的核心是數(shù)據(jù)流,而數(shù)據(jù)流又是構(gòu)建在傳統(tǒng)的事件驅(qū)動架構(gòu)與發(fā)布訂閱模式之上。在講解響應(yīng)式編程技術(shù)之前,我們先來看一下發(fā)布訂閱模式和事件處理相關(guān)的技術(shù)體系。

發(fā)布訂閱模式和事件處理

相信你應(yīng)該對設(shè)計模式中經(jīng)典的觀察者模式不陌生。觀察者模式擁有一個主題(Subject)以及針對這個主題的一個依賴者列表,這些依賴者被稱為觀察者(Observer)。

而發(fā)布訂閱(Publish-Subscribe)模式可以認(rèn)為是對觀察者模式的一種改進(jìn)。在這種模式中,發(fā)布者和訂閱者相互之間可以沒有直接的依賴關(guān)系,而是通過發(fā)送事件到事件處理平臺上完成整合。

針對開頭提到的訂單查詢操作,我們可以基于發(fā)布訂閱模式重構(gòu)流程。通過構(gòu)建發(fā)布訂閱模式以及事件處理平臺,我們具備了傳播和處理異步事件的能力,從而為實(shí)現(xiàn)響應(yīng)式編程提供了基礎(chǔ)。(圖 3)

發(fā)布 - 訂閱模式下的訂單信息獲取過程發(fā)布 - 訂閱模式下的訂單信息獲取過程

再來看單個服務(wù)的內(nèi)部,在三層架構(gòu)中整個調(diào)用鏈路同樣可以用發(fā)布訂閱模式來重構(gòu)。這時,數(shù)據(jù)庫中的數(shù)據(jù)一有變化就會通知到上游組件,而不是上游組件通過主動拉取的方式獲取數(shù)據(jù)。這樣做相當(dāng)于,讓處于調(diào)用鏈路中的各個組件由同步調(diào)用轉(zhuǎn)化為了異步調(diào)用,圖中的虛線和箭頭方向表達(dá)了這層含義。

基于響應(yīng)式實(shí)現(xiàn)方法的數(shù)據(jù)流轉(zhuǎn)時序圖基于響應(yīng)式實(shí)現(xiàn)方法的數(shù)據(jù)流轉(zhuǎn)時序圖

數(shù)據(jù)流和響應(yīng)式

顯然,上圖中異步事件傳播的思想可以擴(kuò)展到整個系統(tǒng)。

你可以想象系統(tǒng)中會存在著很多類似 OderEvent 這樣的事件。每一種事件會被用戶的操作或者系統(tǒng)自身的行為觸發(fā),并形成了事件的集合。我們可以把這個集合看成是一串串連起來的數(shù)據(jù)流,而系統(tǒng)的響應(yīng)能力就體現(xiàn)在對這些數(shù)據(jù)流的即時響應(yīng)過程上。

全流程數(shù)據(jù)流示意圖全流程數(shù)據(jù)流示意圖

對于技術(shù)實(shí)現(xiàn)過程而言,數(shù)據(jù)流是一個全流程的概念。也就是說,無論是底層數(shù)據(jù)庫、服務(wù)層、Web 服務(wù)層,或是在這個流程中所包含的任意中間層組件,整個數(shù)據(jù)傳遞鏈路都應(yīng)該采用事件驅(qū)動的方式來運(yùn)作。這樣,我們就可以不用傳統(tǒng)的同步調(diào)用的方式來處理數(shù)據(jù),而是由處于全流程中的各層組件自行執(zhí)行事件,實(shí)現(xiàn)了全流程的異步非阻塞處理機(jī)制。這就是響應(yīng)式編程的核心特點(diǎn)。

相較傳統(tǒng)開發(fā)普遍采用的“拉”模式,在響應(yīng)式編程下,基于事件的觸發(fā)和訂閱機(jī)制,這就形成了一種類似“推”的工作方式。

推模式下的數(shù)據(jù)流處理方式示意圖推模式下的數(shù)據(jù)流處理方式示意圖

這種工作方式的優(yōu)勢就在于,生成事件和消費(fèi)事件的過程是異步執(zhí)行的,所以線程的生命周期都很短,也就意味著資源之間的競爭關(guān)系較少,服務(wù)器的響應(yīng)能力也就越高。這就是響應(yīng)式編程的精髓,也是解決系統(tǒng)性能問題的關(guān)鍵所在。

講到這里,你可能會問,我們?nèi)绾蝸硎褂庙憫?yīng)式編程技術(shù)來開發(fā)業(yè)務(wù)系統(tǒng)呢?不用擔(dān)心,到目前為止,業(yè)界已經(jīng)誕生了諸如 RxJava、Project Reactor、Akka 等一大批優(yōu)秀的響應(yīng)式編程框架。

而在 Spring 5 中,也引入了 WebFlux、Reactive Spring Data 等新一代的編程組件來實(shí)現(xiàn)響應(yīng)式 Web 服務(wù)和響應(yīng)式數(shù)據(jù)訪問。這種框架和工具,可以很好的解決傳統(tǒng)同步阻塞式處理方式所存在的性能問題。

總結(jié)

今天我們系統(tǒng)分析了傳統(tǒng)服務(wù)調(diào)用存在的問題,從而引出響應(yīng)式編程概念和實(shí)現(xiàn)方法。

從技術(shù)演進(jìn)的過程和趨勢而言,響應(yīng)式編程的出現(xiàn)有其必然性。

但是響應(yīng)式編程也不是一種完全顛覆式的技術(shù)體系,而是在現(xiàn)有的異步調(diào)用、觀察者模式、發(fā)布訂閱模式等的基礎(chǔ)上發(fā)展起來的一種全新的編程模式,能夠給系統(tǒng)帶來即時響應(yīng)性的優(yōu)點(diǎn)。

責(zé)任編輯:武曉燕 來源: 程序員技術(shù)充電站
相關(guān)推薦

2022-07-15 08:16:56

Stream函數(shù)式編程

2024-03-08 10:38:07

Vue響應(yīng)式數(shù)據(jù)

2022-04-12 08:00:17

socket 編程網(wǎng)絡(luò)編程網(wǎng)絡(luò) IO 模型

2025-04-21 04:00:00

2021-07-14 13:12:51

2024-01-03 13:39:00

JS,Javascrip算法

2023-10-18 10:55:55

HashMap

2025-01-13 16:00:00

服務(wù)網(wǎng)關(guān)分布式系統(tǒng)架構(gòu)

2025-04-11 05:55:00

2022-06-16 13:08:30

Combine響應(yīng)式編程訂閱

2017-12-05 17:44:31

機(jī)器學(xué)習(xí)CNN卷積層

2020-10-14 08:50:38

搞懂 Netty 線程

2021-12-29 17:29:07

KubernetesEvents集群

2023-09-28 08:15:05

SpringBean加載

2021-10-11 11:58:41

Channel原理recvq

2023-05-29 08:12:38

2025-03-17 00:21:00

2021-10-09 19:05:06

channelGo原理

2022-11-11 08:19:03

redis分布式

2021-07-28 20:13:04

響應(yīng)式編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號