www.e4938.cn-老师你下面太紧了拔不出来,99re8这里有精品热视频免费,国产第一视频一区二区三区,青青草国产成人久久

<button id="60qo0"></button>

<strike id="60qo0"></strike>
<del id="60qo0"></del>
<fieldset id="60qo0"><menu id="60qo0"></menu></fieldset>
  • 響應(yīng)式API的設(shè)計、實現(xiàn)和應(yīng)用

    2018-03-20 17:01:48 InfoQ  點擊量: 評論 (0)
    這篇文章來自于SpringOne的一個演講。在過去的幾年里,Java世界中在大力推動響應(yīng)式編程的。無論是NodeJS開發(fā)人員使用非阻塞api的成功,還是
    這篇文章來自于SpringOne的一個演講。

    在過去的幾年里,Java世界中在大力推動響應(yīng)式編程的。無論是NodeJS開發(fā)人員使用非阻塞api的成功,還是引發(fā)延遲的微服務(wù)的爆炸式增長,還是僅僅是想要更有效地利用計算資源,許多開發(fā)人員都開始將響應(yīng)式編程看作一種可行的編程模型。 

    幸運的是,涉及到響應(yīng)式框架以及如何正確使用它們時,Java開發(fā)人員被選擇給寵壞了。沒有太多編寫響應(yīng)式代碼的“錯誤”方法,但是,這同時也是問題所在;也沒多少編寫響應(yīng)式代碼的“正確”方法。

    在本文中,我們的目的是給你一些關(guān)于如何編寫響應(yīng)式代碼的意見。這些觀點來自多年來開發(fā)一個大規(guī)模的響應(yīng)式API的經(jīng)驗,雖然它們可能并不適合你,但我們希望它們在你開始你的響應(yīng)式之旅時能給你一些方向。

    本文中的示例都來自于Cloud Foundry Java客戶端。這個項目使用Reactor項目的響應(yīng)式框架。我們?yōu)檫@個Java客戶端選擇Reactor的原因,是因為它與Spring團隊有緊密的集成,但是我們討論的所有概念也都適用于其他的響應(yīng)式框架,比如RxJava。如果你對Cloud Foundry有一些了解,這將很有幫助,但這不是必需的。這些例子有自解釋性命名,在解釋每個響應(yīng)式概念時它們將助你更好地理解。

    響應(yīng)式編程是一個巨大的主題,它遠(yuǎn)遠(yuǎn)超出了本文的范圍,但是為了實現(xiàn)我們的目的,讓我們寬泛地把它定義為一種用更流暢的方式定義事件驅(qū)動系統(tǒng)的方法,而不是傳統(tǒng)的命令式編程風(fēng)格。其目標(biāo)是將命令式邏輯轉(zhuǎn)換為異步、非阻塞、函數(shù)式的樣式,這種樣式更容易理解和推理。 

    為這些做法(threads、NIO、callbacks等等)設(shè)計的命令式API并未考慮如何正確、可靠和方便地使用,許多情況下,在應(yīng)用程序代碼中使用這些API仍需要大量顯式地管理。響應(yīng)式框架的承諾是,這些關(guān)注點可以在幕后處理,從而讓開發(fā)人員能夠把主力精力放在應(yīng)用程序功能代碼的編寫上。

    我應(yīng)該使用響應(yīng)式編程嗎?

    在設(shè)計響應(yīng)式API時,首先要問自己的問題是,你是否想要一個響應(yīng)式API! 響應(yīng)式api不可能適用于所有的一切。響應(yīng)式編程有顯而易見的缺點(目前最大的問題是調(diào)試,但框架和ide都正在積極解決此問題)。相反,當(dāng)價值明顯大于缺點時,你就選擇響應(yīng)式API吧。在作出這個判斷時,有幾個用于響應(yīng)式編程的模式非常適合。

    網(wǎng)絡(luò)化

    網(wǎng)絡(luò)請求本質(zhì)上就撇不開(相對)較大的延遲,而且等待這些響應(yīng)返回通常是系統(tǒng)中最大的資源浪費。在非響應(yīng)式應(yīng)用程序中,那些等待中的請求通常會阻塞線程并消耗堆棧內(nèi)存,空閑著等待響應(yīng)到達(dá)。遠(yuǎn)程故障和超時通常沒有得到系統(tǒng)地、明確地處理,因為提供的API不容易做到這一點。最后,遠(yuǎn)程調(diào)用的負(fù)載通常是未知的、無邊界的,導(dǎo)致堆內(nèi)存耗盡。響應(yīng)式編程與非阻塞IO相結(jié)合,解決了這類問題,因為它為你提供了一個清晰的和顯式的API。

    高并發(fā)操作

    它也很適合用于協(xié)調(diào)高并發(fā)操作(如網(wǎng)絡(luò)請求或可并行化cpu密集型計算)。響應(yīng)式框架,雖然允許顯式管理線程,但采用自動線程管理也很出色。像.flatmap()這樣的操作符透明地并行化行為,最大化地利用可用資源。

    大規(guī)模可擴展應(yīng)用

    每個鏈接一個線程的servlet 模型已經(jīng)為我們服務(wù)了很多年了。但是,隨著微服務(wù)的出現(xiàn),我們已經(jīng)開始看到應(yīng)用程序大規(guī)模地擴展(25、50甚至100個單個無狀態(tài)應(yīng)用程序的實例)來處理連接負(fù)載,即使CPU使用率處于空閑狀態(tài)。選擇非阻塞IO加響應(yīng)式編程效果更佳,打破了鏈接與線程間的這種聯(lián)系,使可用資源得到更有效的利用。很明顯,這樣的優(yōu)勢通常是驚人的。它常常需要在Tomcat上構(gòu)建一個應(yīng)用程序的更多實例,這些應(yīng)用程序需要成百上千的線程來處理相同的負(fù)載,就像同一應(yīng)用程序構(gòu)建在擁有8個線程的Netty上一樣。

    雖然以上所列不能完全用來評判響應(yīng)式編程在哪里適用,但關(guān)鍵是要記住,如果你的應(yīng)用不適合以上任何一種,那么你用它可能只是徒增復(fù)雜度,而不會增加任何價值。

    響應(yīng)式API應(yīng)該返回什么?

    如果你回答了第一個問題,判定出你的應(yīng)用會從響應(yīng)式API得到收益,那么就到了設(shè)計API的時候了。決定你的響應(yīng)式API應(yīng)該返回什么基本類型是一個好的起點。

    Java世界中的所有響應(yīng)式框架(包括Java 9的Flow)都是在響應(yīng)式流程規(guī)范之上通信的。這個規(guī)范定義了一個低級的交互API,但是它不被認(rèn)為是一個響應(yīng)式框架(也就是說,它未針對流指定可用的操作符)。

    在Reactor 項目中有兩種主要的類型。Flux類型表示流經(jīng)該系統(tǒng)的0到N個值。Mono類型表示0到1個值。在Java客戶端中,我們幾乎只使用Mono,因為它清楚地映射到單個請求、單個響應(yīng)模型。

    Flux<Application> listApplications() {...}
    
    Flux<String> listApplicationNames() {
      return listApplications()
        .map(Application::getName);
    }
    
    void printApplicationName() {
      listApplicationNames()
        .subscribe(System.out::println);
    }

    在本例中,listApplications()方法執(zhí)行一個網(wǎng)絡(luò)調(diào)用,并返回0到N個應(yīng)用程序?qū)嵗腇lux。然后,我們使用.map()操作符將每個應(yīng)用程序轉(zhuǎn)換為其名稱的字符串。然后將以應(yīng)用程序命名的Flux消費并輸出到控制臺。

    Flux<Application> listApplications() {...}
    
    Mono<List<String>> listApplicationNames() {
      return listApplications()
        .map(Application::getName)
        .collectList();
    }
    
    Mono<Boolean> doesApplicationExist(String name) {
      return listApplicationNames()
        .map(names -> names.contains(name));
    }

    Mono并不像Flux那樣有一個流,但是因為它們在概念上是一個元素的流,所以我們使用的操作符通常有相同的名稱。在這個例子中,除了映射到應(yīng)用程序名稱的Flux之外,我們還將這些名稱收集到一個List中。在這種情況下,包含該列表的Mono可以被轉(zhuǎn)換為一個boolean值,表示其中是否包含某個名稱。這可能與直覺不符,但是如果你正在處理的項目在邏輯上是一個項目的集合,而不是它們的流,那么返回一個集合的Mono也很正常(例如Mono>)。

    與命令式API不同,void不是一個適當(dāng)?shù)捻憫?yīng)式返回類型。相反,每一個方法都必須返回一個Flux或者一個Mono。這可能看起來很奇怪(仍然有一些行為沒有任何返回呀!),但這是一個響應(yīng)流基本操作的結(jié)果。調(diào)用響應(yīng)式API的代碼執(zhí)行(例如.flatmap ().map()…)是構(gòu)建了一個數(shù)據(jù)到流的結(jié)構(gòu),但實際上并沒有轉(zhuǎn)換數(shù)據(jù)。只有在最后,當(dāng).subscribe()被調(diào)用時,數(shù)據(jù)才會開始向流轉(zhuǎn)換,并在隨之完成轉(zhuǎn)換。這種惰性執(zhí)行正是為什么基于lambdas構(gòu)建響應(yīng)式編程的原因,以及為什么總要有返回類型,因為必須得有一些東西去.subscribe()。

    void delete(String id) {
      this.restTemplate.delete(URI, id);
    }
    
    public void cleanup(String[] args) {
      delete("test-id");
    }

    上面這種的命令式阻塞示例可以返回void,因為它的網(wǎng)絡(luò)調(diào)用會立即開始執(zhí)行,直到接收到響應(yīng)時才返回。

    Mono<Void> delete(String id) {
      return this.httpClient.delete(URI, id);
    }
    
    public void cleanup(String[] args) {
      CountDownLatch latch = new CountDownLatch(1);
    
      delete("test-id")
        .subscribe(n -> {}, Throwable::printStackTrace, () -> latch::countDown);
    
      latch.await();
    }

    在這個響應(yīng)式示例中,網(wǎng)絡(luò)調(diào)用直到.subscribe()被調(diào)用后才開始,在delete()之后返回,因為它是用來生成調(diào)用的結(jié)構(gòu),而不是調(diào)用本身的結(jié)果。在本例中,我們使用返回0個條目的Mono,并在收到響應(yīng)后才發(fā)出onComplete()的信號,這就相當(dāng)于void返回類型了。

    方法的范圍

    一旦你決定了你的API需要返回什么,你就需要考慮你的每個方法(API和實現(xiàn))將會做什么了。在該Java客戶端上,我們發(fā)現(xiàn)把方法設(shè)計小且可復(fù)用會帶來收益。它使每一種方法更容易組成更大的操作。這還能讓它們更靈活地組合成并行或順序操作。此外,它還使?jié)撛诘膹?fù)雜流程更具可讀性。

    Mono<ListApplicationsResponse> getPage(int page) {
      return this.client.applicationsV2()
        .list(ListApplicationsRequest.builder()
          .page(page)
          .build());
    }
    
    void getResources() {
      getPage(1)
        .flatMapMany(response -> Flux.range(2, response.getTotalPages() - 1)
          .flatMap(page -> getPage(page))
          .startWith(response))
        .subscribe(System.out::println);
    }
    

    這個例子演示了我們?nèi)绾握{(diào)用一個分頁的API。第一個getPage()請求檢索結(jié)果的第一頁。在結(jié)果的第一頁中包括我們需要檢索的頁面總數(shù),以獲得完整的結(jié)果。因為getPage()方法是小的、可重用的,而且沒有其他額外作用,所以我們可以重用該方法,并可以通過totalPages并行為第2頁進(jìn)行調(diào)用!

    順序和并行協(xié)調(diào)

    現(xiàn)在,幾乎所有顯著的性能改進(jìn)都來自對并發(fā)性的提升。我們知道這一點,但許多系統(tǒng)的并發(fā)要么僅涉及傳入的連接,要么根本不并發(fā)。大部分這種情況都是源自這樣一個事實,那就是實現(xiàn)一個高度并發(fā)的系統(tǒng)又困難又容易出錯。響應(yīng)式編程的一個重要優(yōu)點是,你可以定義操作之間的順序和并行關(guān)系,并讓框架確定利用可用資源的最佳方式

    大云網(wǎng)官方微信售電那點事兒

    責(zé)任編輯:售電衡衡

    免責(zé)聲明:本文僅代表作者個人觀點,與本站無關(guān)。其原創(chuàng)性以及文中陳述文字和內(nèi)容未經(jīng)本站證實,對本文以及其中全部或者部分內(nèi)容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,并請自行核實相關(guān)內(nèi)容。
    我要收藏
    個贊
    ?
    美女被男人桶到爽免费网站| 91精品国产高清久久久久久| 大地资源影视中文在线观看| 色欲狠狠躁天天躁无码中文字幕| 久久精品国产AV一区二区电影| 免费AV在线| 国产精品无码专区在线观看| 西西人体337GoGo欧美人| 久久精品国产亚洲AV日韩| 欧美日韩一级片在线观看|