成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Hystrix工作原理(官方文檔翻譯)

Lycheeee / 2228人閱讀

摘要:使用線程池的好處通過線程在自己的線程池中隔離的好處是該應(yīng)用程序完全可以不受失控的客戶端庫的威脅。簡而言之,由線程池提供的隔離功能可以使客戶端庫和子系統(tǒng)性能特性的不斷變化和動態(tài)組合得到優(yōu)雅的處理,而不會造成中斷。

?

工作流程圖

下面的流程圖展示了當(dāng)使用Hystrix的依賴請求,Hystrix是如何工作的。

? 下面將更詳細(xì)的解析每一個步驟都發(fā)生哪些動作:

構(gòu)建一個HystrixCommand或者HystrixObservableCommand對象。

第一步就是構(gòu)建一個HystrixCommand或者HystrixObservableCommand對象,該對象將代表你的一個依賴請求,向構(gòu)造函數(shù)中傳入請求依賴所需要的參數(shù)。

如果構(gòu)建HystrixCommand中的依賴返回單個響應(yīng),例如:

HystrixCommand command = new HystrixCommand(arg1, arg2);

如果依賴需要返回一個Observable來發(fā)射響應(yīng),就需要通過構(gòu)建HystrixObservableCommand對象來完 成,例如:

HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);

執(zhí)行命令

有4種方式可以執(zhí)行一個Hystrix命令。

execute()—該方法是阻塞的,從依賴請求中接收到單個響應(yīng)(或者出錯時拋出異常)。

queue()—從依賴請求中返回一個包含單個響應(yīng)的Future對象。

observe()—訂閱一個從依賴請求中返回的代表響應(yīng)的Observable對象。

toObservable()—返回一個Observable對象,只有當(dāng)你訂閱它時,它才會執(zhí)行Hystrix命令并發(fā)射響應(yīng)。

K             value   = command.execute();
Future     fValue  = command.queue();
Observable ohValue = command.observe();         //hot observable
Observable ocValue = command.toObservable();    //cold observable

同步調(diào)用方法execute()實(shí)際上就是調(diào)用queue().get()方法,queue()方法的調(diào)用的是toObservable().toBlocking().toFuture().也就是說,最終每一個HystrixCommand都是通過Observable來實(shí)現(xiàn)的,即使這些命令僅僅是返回一個簡單的單個值。

響應(yīng)是否被緩存

如果這個命令的請求緩存已經(jīng)開啟,并且本次請求的響應(yīng)已經(jīng)存在于緩存中,那么就會立即返回一個包含緩存響應(yīng)的Observable(下面將Request Cache部分將對請求的cache做講解)。

回路器是否打開

當(dāng)命令執(zhí)行執(zhí)行時,Hystrix會檢查回路器是否被打開。

如果回路器被打開(或者tripped),那么Hystrix就不會再執(zhí)行命名,而是直接路由到第8步,獲取fallback方法,并執(zhí)行fallback邏輯。

如果回路器關(guān)閉,那么將進(jìn)入第5步,檢查是否有足夠的容量來執(zhí)行任務(wù)。(其中容量包括線程池的容量,隊(duì)列的容量等等)。

線程池、隊(duì)列、信號量是否已滿

如果與該命令相關(guān)的線程池或者隊(duì)列已經(jīng)滿了,那么Hystrix就不會再執(zhí)行命令,而是立即跳到第8步,執(zhí)行fallback邏輯。

HystrixObservableCommand.construct() 或者 HystrixCommand.run()

在這里,Hystrix通過你寫的方法邏輯來調(diào)用對依賴的請求,通過下列之一的調(diào)用:

HystrixCommand.run()—返回單個響應(yīng)或者拋出異常。

HystrixObservableCommand.construct() —返回一個發(fā)射響應(yīng)的Observable或者發(fā)送一個onError()的通知。

如果執(zhí)行run()方法或者construct()方法的執(zhí)行時間大于命令所設(shè)置的超時時間值,那么該線程將會拋出一個TimeoutException異常(或者如果該命令沒有運(yùn)行在它自己的線程中,[or a separate timer thread will, if the command itself is not running in its own thread])。在這種情況下,Hystrix將會路由到第8步,執(zhí)行fallback邏輯,并且如果run()或者construct()方法沒有被取消或者中斷,會丟棄這兩個方法最終返回的結(jié)果。

請注意,沒有任何方式可以強(qiáng)制終止一個潛在[latent]的線程的運(yùn)行,Hystrix能夠做的最好的方式是讓JVM拋出一個InterruptedException異常,如果你的任務(wù)被Hystrix所包裝,并不意味著會拋出一個InterruptedExceptions異常,該線程在Hystrix的線程池內(nèi)會進(jìn)行執(zhí)行,雖然在客戶端已經(jīng)接收到了TimeoutException異常,這個行為能夠滲透到Hystrix的線程池中,[though the load is "correctly shed"],絕大多數(shù)的Http Client不會將這一行為視為InterruptedExceptions,所以,請確保正確配置連接或者讀取/寫入的超時時間。

如果命令最終返回了響應(yīng)并且沒有拋出任何異常,Hystrix在返回響應(yīng)后會執(zhí)行一些log和指標(biāo)的上報(bào),如果是調(diào)用run()方法,Hystrix會返回一個Observable,該Observable會發(fā)射單個響應(yīng)并且會調(diào)用onCompleted方法來通知響應(yīng)的回調(diào),如果是調(diào)用construct()方法,Hystrix會通過construct()方法返回相同的Observable對象。

計(jì)算回路指標(biāo)[Circuit Health]

Hystrix會報(bào)告成功、失敗、拒絕和超時的指標(biāo)給回路器,回路器包含了一系列的滑動窗口數(shù)據(jù),并通過該數(shù)據(jù)進(jìn)行統(tǒng)計(jì)。

它使用這些統(tǒng)計(jì)數(shù)據(jù)來決定回路器是否應(yīng)該熔斷,如果需要熔斷,將在一定的時間內(nèi)不在請求依賴[短路請求](譯者:這一定的時候可以通過配置指定),當(dāng)再一次檢查請求的健康的話會重新關(guān)閉回路器。

獲取FallBack

當(dāng)命令執(zhí)行失敗時,Hystrix會嘗試執(zhí)行自定義的Fallback邏輯:

當(dāng)construct()或者run()方法執(zhí)行過程中拋出異常。

當(dāng)回路器打開,命令的執(zhí)行進(jìn)入了熔斷狀態(tài)。

當(dāng)命令執(zhí)行的線程池和隊(duì)列或者信號量已經(jīng)滿容。

命令執(zhí)行超時。

寫一個fallback方法,提供一個不需要網(wǎng)絡(luò)依賴的通用響應(yīng),從內(nèi)存緩存或者其他的靜態(tài)邏輯獲取數(shù)據(jù)。如果再fallback內(nèi)必須需要網(wǎng)絡(luò)的調(diào)用,更好的做法是使用另一個HystrixCommand或者HystrixObservableCommand。

如果你的命令是繼承自HystrixCommand,那么可以通過實(shí)現(xiàn)HystrixCommand.getFallback()方法返回一個單個的fallback值。

如果你的命令是繼承自HystrixObservableCommand,那么可以通過實(shí)現(xiàn)HystrixObservableCommand.resumeWithFallback()方法返回一個Observable,并且該Observable能夠發(fā)射出一個fallback值。

Hystrix會把fallback方法返回的響應(yīng)返回給調(diào)用者。

如果你沒有為你的命令實(shí)現(xiàn)fallback方法,那么當(dāng)命令拋出異常時,Hystrix仍然會返回一個Observable,但是該Observable并不會發(fā)射任何的數(shù)據(jù),并且會立即終止并調(diào)用onError()通知。通過這個onError通知,可以將造成該命令拋出異常的原因返回給調(diào)用者。

失敗或不存在回退的結(jié)果將根據(jù)您如何調(diào)用Hystrix命令而有所不同:

execute():拋出一個異常。

queue():成功返回一個Future,但是如果調(diào)用get()方法,將會拋出一個異常。

observe():返回一個Observable,當(dāng)你訂閱它時,它將立即終止,并調(diào)用onError()方法。

toObservable():返回一個Observable,當(dāng)你訂閱它時,它將立即終止,并調(diào)用onError()方法。

返回成功的響應(yīng)

如果Hystrix命令執(zhí)行成功,它將以O(shè)bservable形式返回響應(yīng)給調(diào)用者。根據(jù)你在第2步的調(diào)用方式不同,在返回Observablez之前可能會做一些轉(zhuǎn)換。

execute():通過調(diào)用queue()來得到一個Future對象,然后調(diào)用get()方法來獲取Future中包含的值。

queue():將Observable轉(zhuǎn)換成BlockingObservable,在將BlockingObservable轉(zhuǎn)換成一個Future。

observe():訂閱返回的Observable,并且立即開始執(zhí)行命令的邏輯,

toObservable():返回一個沒有改變的Observable,你必須訂閱它,它才能夠開始執(zhí)行命令的邏輯。

回路器

下面的圖展示了HystrixCommandHystrixObservableCommand如何與HystrixCircuitBroker進(jìn)行交互。

回路器打開和關(guān)閉有如下幾種情況:

假設(shè)回路中的請求滿足了一定的閾值(HystrixCommandProperties.circuitBreakerRequestVolumeThreshold()

假設(shè)錯誤發(fā)生的百分比超過了設(shè)定的錯誤發(fā)生的閾值HystrixCommandProperties.circuitBreakerErrorThresholdPercentage()

回路器狀態(tài)由CLOSE變換成OPEN

如果回路器打開,所有的請求都會被回路器所熔斷。

一定時間之后HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds(),下一個的請求會被通過(處于半打開狀態(tài)),如果該請求執(zhí)行失敗,回路器會在睡眠窗口期間返回OPEN,如果請求成功,回路器會被置為關(guān)閉狀態(tài),重新開啟1步驟的邏輯。

隔離

Hystrix采用艙壁模式來隔離相互之間的依賴關(guān)系,并限制對其中任何一個的并發(fā)訪問。

線程和線程池

客戶端(第三方包、網(wǎng)絡(luò)調(diào)用等)會在多帶帶的線程執(zhí)行,會與調(diào)用的該任務(wù)的線程進(jìn)行隔離,以此來防止調(diào)用者調(diào)用依賴所消耗的時間過長而阻塞調(diào)用者的線程。

[Hystrix uses separate, per-dependency thread pools as a way of constraining any given dependency so latency on the underlying executions will saturate the available threads only in that pool]

您可以在不使用線程池的情況下防止出現(xiàn)故障,但是這要求客戶端必須能夠做到快速失敗(網(wǎng)絡(luò)連接/讀取超時和重試配置),并始終保持良好的執(zhí)行狀態(tài)。

Netflix,設(shè)計(jì)Hystrix,并且選擇使用線程和線程池來實(shí)現(xiàn)隔離機(jī)制,有以下幾個原因:

很多應(yīng)用會調(diào)用多個不同的后端服務(wù)作為依賴。

每個服務(wù)會提供自己的客戶端庫包。

每個客戶端的庫包都會不斷的處于變更狀態(tài)。

[Client library logic can change to add new network calls]

每個客戶端庫包都可能包含重試、數(shù)據(jù)解析、緩存等等其他邏輯。

對用戶來說,客戶端庫往往是“黑盒”的,對于實(shí)現(xiàn)細(xì)節(jié)、網(wǎng)絡(luò)訪問模式。默認(rèn)配置等都是不透明的。

[In several real-world production outages the determination was “oh, something changed and properties should be adjusted” or “the client library changed its behavior.]

即使客戶端本身沒有改變,服務(wù)本身也可能發(fā)生變化,這些因素都會影響到服務(wù)的性能,從而導(dǎo)致客戶端配置失效。

傳遞依賴可以引入其他客戶端庫,這些客戶端庫不是預(yù)期的,也許沒有正確配置。

大部分的網(wǎng)絡(luò)訪問是同步執(zhí)行的。

客戶端代碼中也可能出現(xiàn)失敗和延遲,而不僅僅是在網(wǎng)絡(luò)調(diào)用中。

使用線程池的好處

通過線程在自己的線程池中隔離的好處是:

該應(yīng)用程序完全可以不受失控的客戶端庫的威脅。即使某一個依賴的線程池已滿也不會影響其他依賴的調(diào)用。

應(yīng)用程序可以低風(fēng)險(xiǎn)的接受新的客戶端庫的數(shù)據(jù),如果發(fā)生問題,它會與出問題的客戶端庫所隔離,不會影響其他依賴的任何內(nèi)容。

當(dāng)失敗的客戶端服務(wù)恢復(fù)時,線程池將會被清除,應(yīng)用程序也會恢復(fù),而不至于使得我們整個Tomcat容器出現(xiàn)故障。

如果一個客戶端庫的配置錯誤,線程池可以很快的感知這一錯誤(通過增加錯誤比例,延遲,超時,拒絕等),并可以在不影響應(yīng)用程序的功能情況下來處理這些問題(可以通過動態(tài)配置來進(jìn)行實(shí)時的改變)。

如果一個客戶端服務(wù)的性能變差,可以通過改變線程池的指標(biāo)(錯誤、延遲、超時、拒絕)來進(jìn)行屬性的調(diào)整,并且這些調(diào)整可以不影響其他的客戶端請求。

除了隔離的優(yōu)勢之外,擁有專用的線程池可以提供內(nèi)置的請求任務(wù)的并發(fā)性,可以在同步客戶端上構(gòu)建異步門面。

簡而言之,由線程池提供的隔離功能可以使客戶端庫和子系統(tǒng)性能特性的不斷變化和動態(tài)組合得到優(yōu)雅的處理,而不會造成中斷。

注意:雖然多帶帶的線程提供了隔離,但您的底層客戶端代碼也應(yīng)該有超時和/或響應(yīng)線程中斷,而不能讓Hystrix的線程池處于無休止的等待狀態(tài)。

線程池的缺點(diǎn)

線程池最主要的缺點(diǎn)就是增加了CPU的計(jì)算開銷,每個命令都會在多帶帶的線程池上執(zhí)行,這樣的執(zhí)行方式會涉及到命令的排隊(duì)、調(diào)度和上下文切換。

Netflix在設(shè)計(jì)這個系統(tǒng)時,決定接受這個開銷的代價(jià),來換取它所提供的好處,并且認(rèn)為這個開銷是足夠小的,不會有重大的成本或者是性能影響。

線程成本

Hystrix在子線程執(zhí)行construct()方法和run()方法時會計(jì)算延遲,以及計(jì)算父線程從端到端的執(zhí)行總時間。所以,你可以看到Hystrix開銷成本包括(線程、度量,日志,斷路器等)。

Netflix API每天使用線程隔離的方式處理10億多的Hystrix Command任務(wù),每個API實(shí)例都有40多個線程池,每個線程池都有5-20個線程(大多數(shù)設(shè)置為10)

下圖顯示了一個HystrixCommand在單個API實(shí)例上每秒執(zhí)行60個請求(每個服務(wù)器每秒執(zhí)行大約350個線程執(zhí)行總數(shù)):

在中間位置(或者下線位置)不需要多帶帶的線程池。

在第90線上,多帶帶線程的成本為3ms。

在第99線上,多帶帶的線程花費(fèi)9ms。但是請注意,線程成本的開銷增加遠(yuǎn)小于多帶帶線程(網(wǎng)絡(luò)請求)從2跳到28而執(zhí)行時間從0跳到9的增加。

對于大多數(shù)Netflix用例來說,這樣的請求在90%以上的開銷被認(rèn)為是可以接受的,這是為了實(shí)現(xiàn)韌性的好處。

對于非常低延遲請求(例如那些主要觸發(fā)內(nèi)存緩存的請求),開銷可能太高,在這種情況下,可以使用另一種方法,如信號量,雖然它們不允許超時,提供絕大部分的有點(diǎn),而不會產(chǎn)生開銷。然而,一般來說,開銷是比較小的,以至于Netflix通常更偏向于通過多帶帶的線程來作為隔離實(shí)現(xiàn)。

請求合并

您可以使用請求合并器(HystrixCollapser是抽象父代)來提前發(fā)送HystrixCommand,通過該合并器您可以將多個請求合并為一個后端依賴項(xiàng)調(diào)用。

下面的圖展示了兩種情況下的線程數(shù)和網(wǎng)絡(luò)連接數(shù),第一張圖是不使用請求合并,第二張圖是使用請求合并(假定所有連接在短時間窗口內(nèi)是“并發(fā)的”,在這種情況下是10ms)。

為什么使用請求合并

事情請求合并來減少執(zhí)行并發(fā)HystrixCommand請求所需要的線程數(shù)和網(wǎng)絡(luò)連接數(shù)。請求合并以自動方式執(zhí)行的,不需要代碼層面上進(jìn)行批處理請求的編碼。

全局上下文(所有的tomcat線程)

理想的合并方式是在全局應(yīng)用程序級別來完成的,以便來自任何用戶的任何Tomcat線程的請求都可以一起合并。

例如,如果將HystrixCommand配置為支持任何用戶請求獲取影片評級的依賴項(xiàng)的批處理,那么當(dāng)同一個JVM中的任何用戶線程發(fā)出這樣的請求時,Hystrix會將該請求與其他請求一起合并添加到同一個JVM中的網(wǎng)絡(luò)調(diào)用。

請注意,合并器會將一個HystrixRequestContext對象傳遞給合并的網(wǎng)絡(luò)調(diào)用,為了使其成為一個有效選項(xiàng),下游系統(tǒng)必須處理這種情況。

用戶請求上下文(單個tomcat線程)

如果將HystrixCommand配置為僅處理單個用戶的批處理請求,則Hystrix僅僅會合并單個Tomcat線程的請求。

例如,如果一個用戶想要加載300個影片的標(biāo)簽,Hystrix能夠把這300次網(wǎng)絡(luò)調(diào)用合并成一次調(diào)用。

對象建模和代碼的復(fù)雜性

有時候,當(dāng)你創(chuàng)建一個對象模型對消費(fèi)的對象而言是具有邏輯意義的,這與對象的生產(chǎn)者的有效資源利用率不匹配。

例如,給你300個視頻對象,遍歷他們,并且調(diào)用他們的getSomeAttribute()方法,但是如果簡單的調(diào)用,可能會導(dǎo)致300次網(wǎng)絡(luò)調(diào)用(可能很快會占滿資源)。

有一些手動的方法可以解決這個問題,比如在用戶調(diào)用getSomeAttribute()方法之前,要求用戶聲明他們想要獲取哪些視頻對象的屬性,以便他們都可以被預(yù)取。

或者,您可以分割對象模型,以便用戶必須從一個位置獲取視頻列表,然后從其他位置請求該視頻列表的屬性。

這些方法可以會使你的API和對象模型顯得笨拙,并且這種方式也不符合心理模式與使用模式(譯者:不太懂什么意思)。由于多個開發(fā)人員在代碼庫上工作,可能會導(dǎo)致低級的錯誤和低效率開發(fā)的問題。因?yàn)閷σ粋€用例的優(yōu)化可以通過執(zhí)行另一個用例和通過代碼的新路徑來打破。

通過將合并邏輯移到Hystrix層,不管你如何創(chuàng)建對象模型,調(diào)用順序是怎樣的,或者不同的開發(fā)人員是否知道是否完成了優(yōu)化或者是否完成。

getSomeAttribute()方法可以放在最適合的地方,并以任何適合使用模式的方式被調(diào)用,并且合并器會自動將批量調(diào)用放置到時間窗口。

####請求Cache

*

HystrixCommand和HystrixObservableCommand實(shí)現(xiàn)可以定義一個緩存鍵,然后用這個緩存鍵以并發(fā)感知的方式在請求上下文中取消調(diào)用(不需要調(diào)用依賴即可以得到結(jié)果,因?yàn)橥瑯拥恼埱蠼Y(jié)果已經(jīng)按照緩存鍵緩存起來了)。

以下是一個涉及HTTP請求生命周期的示例流程,以及在該請求中執(zhí)行工作的兩個線程:

請求cache的好處有:

不同的代碼路徑可以執(zhí)行Hystrix命令,而不用擔(dān)心重復(fù)的工作。

這在許多開發(fā)人員實(shí)現(xiàn)不同功能的大型代碼庫中尤其有用。

例如,多個請求路徑都需要獲取用戶的Account對象,可以像這樣請求:

Account account = new UserGetAccount(accountId).execute();
//or
Observable accountObservable = new UserGetAccount(accountId).observe();

Hystrix RequestCache將只執(zhí)行一次底層的run()方法,執(zhí)行HystrixCommand的兩個線程都會收到相同的數(shù)據(jù),盡管實(shí)例化了多個不同的實(shí)例。

整個請求的數(shù)據(jù)檢索是一致的。

每次執(zhí)行該命令時,不再會返回一個不同的值(或回退),而是將第一個響應(yīng)緩存起來,后續(xù)相同的請求將會返回緩存的響應(yīng)。

消除重復(fù)的線程執(zhí)行。

由于請求緩存位于construct()或run()方法調(diào)用之前,Hystrix可以在調(diào)用線程執(zhí)行之前取消調(diào)用。

如果Hystrix沒有實(shí)現(xiàn)請求緩存功能,那么每個命令都需要在構(gòu)造或者運(yùn)行方法中實(shí)現(xiàn),這將在一個線程排隊(duì)并執(zhí)行之后進(jìn)行。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70801.html

相關(guān)文章

  • 拜托!面試請不要再問我Spring Cloud底層原理

    摘要:不過大多數(shù)講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務(wù)。 歡迎關(guān)注微信公眾號:石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準(zhǔn)時送上! 目錄 一、業(yè)務(wù)場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...

    wums 評論0 收藏0
  • 拜托!面試請不要再問我Spring Cloud底層原理

    摘要:不過大多數(shù)講解還停留在對功能使用的層面,其底層的很多原理,很多人可能并不知曉。每個線程池里的線程就僅僅用于請求那個服務(wù)。 歡迎關(guān)注微信公眾號:石杉的架構(gòu)筆記(id:shishan100) 每日更新!精品技術(shù)文章準(zhǔn)時送上! 目錄 一、業(yè)務(wù)場景介紹 二、Spring Cloud核心組件:Eureka 三、Spring Cloud核心組件:Feign 四、Spring Cloud核心組件:R...

    wangjuntytl 評論0 收藏0
  • 外行人都能看懂的SpringCloud,錯過了血虧!

    摘要:集群系統(tǒng)中的單個計(jì)算機(jī)通常稱為節(jié)點(diǎn),通常通過局域網(wǎng)連接,但也有其它的可能連接方式。這樣就高興了,可以專心寫自己的,前端就專門交由小周負(fù)責(zé)了。于是,小周和就變成了協(xié)作開發(fā)。都是為了項(xiàng)目正常運(yùn)行以及迭代。 一、前言 只有光頭才能變強(qiáng) 認(rèn)識我的朋友可能都知道我這陣子去實(shí)習(xí)啦,去的公司說是用SpringCloud(但我覺得使用的力度并不大啊~~)... 所以,這篇主要來講講SpringClou...

    沈建明 評論0 收藏0
  • 外行人都能看懂的SpringCloud,錯過了血虧!

    摘要:集群系統(tǒng)中的單個計(jì)算機(jī)通常稱為節(jié)點(diǎn),通常通過局域網(wǎng)連接,但也有其它的可能連接方式。這樣就高興了,可以專心寫自己的,前端就專門交由小周負(fù)責(zé)了。于是,小周和就變成了協(xié)作開發(fā)。都是為了項(xiàng)目正常運(yùn)行以及迭代。 一、前言 只有光頭才能變強(qiáng) 認(rèn)識我的朋友可能都知道我這陣子去實(shí)習(xí)啦,去的公司說是用SpringCloud(但我覺得使用的力度并不大啊~~)... 所以,這篇主要來講講SpringClou...

    enda 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<