摘要:是一個倡議,它提倡提供一種帶有非阻塞背壓的異步流處理的標(biāo)準(zhǔn)。是標(biāo)準(zhǔn)的實現(xiàn)之一。的實現(xiàn)細(xì)節(jié)請求響應(yīng)的與請求響應(yīng)的暴露為是請求的的消費者是響應(yīng)的的生產(chǎn)者內(nèi)部的內(nèi)部
北京時間 9 月 26 日,Oracle 官方宣布 Java 11 正式發(fā)布 一、JDK HTTP Client介紹 JDK11中的17個新特性 JDK11中引入HTTP Client的動機
既有的HttpURLConnection存在許多問題
其基類URLConnection當(dāng)初是設(shè)計為支持多協(xié)議,但其中大多已經(jīng)成為非主流(ftp, gopher…)
API的設(shè)計早于HTTP/1.1,過度抽象
難以使用,存在許多沒有文檔化的行為
它只支持阻塞模式(每個請求/響應(yīng)占用一個線程)
HTTP Client發(fā)展史 在JDK11 HTTP Client出現(xiàn)之前在此之前,可以使用以下工具作為Http客戶端
JDK HttpURLConnection
Apache HttpClient
Okhttp
Spring Rest Template
Spring Cloud Feign
將Jetty用作客戶端
使用Netty庫。還
初探JDK HTTP Client我們來看一段HTTP Client的常規(guī)用法的樣例 ——
執(zhí)行GET請求,然后輸出響應(yīng)體(Response Body)。
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://openjdk.java.net/")) .build(); client.sendAsync(request, asString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println) .join();第一步:創(chuàng)建HttpClient
一般使用JDK 11中的HttpClient的第一步是創(chuàng)建HttpClient對象并進(jìn)行配置。
指定協(xié)議(http/1.1或者h(yuǎn)ttp/2)
轉(zhuǎn)發(fā)(redirect)
代理(proxy)
認(rèn)證(authenticator)
HttpClient client = HttpClient.newBuilder() .version(Version.HTTP_2) .followRedirects(Redirect.SAME_PROTOCOL) .proxy(ProxySelector.of(new InetSocketAddress("www-proxy.com", 8080))) .authenticator(Authenticator.getDefault()) .build();第二步:創(chuàng)建HttpRequest
從HttpRequest的builder組建request
請求URI
請求method(GET, PUT, POST)
請求體(request body)
Timeout
請求頭(request header)
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://openjdk.java.net/")) .timeout(Duration.ofMinutes(1)) .header("Content-Type", "application/json") .POST(BodyPublisher.fromFile(Paths.get("file.json"))) .build()第三步:send
http client可以用來發(fā)送多個http request
請求可以被以同步或異步方式發(fā)送
1. 同步發(fā)送同步發(fā)送API阻塞直到HttpResponse返回
HttpResponse2. 異步發(fā)送response = client.send(request, BodyHandler.asString()); System.out.println(response.statusCode()); System.out.println(response.body());
異步發(fā)送API立即返回一個CompletableFuture
當(dāng)它完成的時候會獲得一個HttpResponse
client.sendAsync(request, BodyHandler.asString()) .thenApply(response -> { System.out.println(response.statusCode()); return response; } ) .thenApply(HttpResponse::body) .thenAccept(System.out::println);
※CompletableFuture是在java8中加入的,支持組合式異步編程
二、從提升單機并發(fā)處理能力的技術(shù)來看HttpClient的實現(xiàn)細(xì)節(jié) 提升單機并發(fā)處理能力的技術(shù)多CPU/多核
多線程
非阻塞(non-blocking)
Java NIOJava NIO為Java帶來了非阻塞模型。
Lambda表達(dá)式可以方便地利用多CPU。
Lambda表達(dá)式讓代碼更加具有可讀性
回調(diào)假設(shè)以下代碼是一個聊天應(yīng)用服務(wù)器的一部分,該應(yīng)用以Vert.x框架實現(xiàn)。
(Eclipse Vert.x is a tool-kit for building reactive applications on the JVM.)
向connectHandler方法輸入一個Lambda表達(dá)式,每當(dāng)有用戶連接到聊天應(yīng)用時,都會調(diào)用該Lambda表達(dá)式。這就是一個回調(diào)。
這種方式的好處是,應(yīng)用不必控制線程模型——Vert.x框架為我們管理線程,打理好一切相關(guān)復(fù)雜性,程序員只考慮和回調(diào)就夠了。
vertx.createServer() .connectHandler(socket -> { socket.dataHandler(new User(socket, this)); }).listen(10_000);
注意,這種設(shè)計里,不共享任何狀態(tài)。對象之間通過向事件總線發(fā)送消息通信,根本不需要在代碼中添加鎖或使用synchronized關(guān)鍵字。并發(fā)編程變得更加簡單。
Future大量的回調(diào)會怎樣?請看以下偽代碼
(1)->{ (2)->{ (3)->{ (4)->{} } } }
大量回調(diào)會形成“末日金字塔”。
如何破解? 使用Future
Future1=(1)->{} Future2=(Future1.get())->{} Future3=(Future2.get())->{} Future4=(Future3.get())->{}
但這會造成原本期望的并行處理,變成了串行處理,帶來了性能問題。
我們真正需要的是將Future和回調(diào)聯(lián)合起來使用。下面將要講的CompletableFuture就是結(jié)合了Future和回調(diào),其要點是組合不同實例而無需擔(dān)心末日金字塔問題。
(new CompletableFuture()).thenCompose((1)->{}) .thenCompose((2)->{}) .thenCompose((3)->{}) .thenCompose((4)->{}) .join()Reactive Streams
Reactive Streams是一個倡議,它提倡提供一種帶有非阻塞背壓的異步流處理的標(biāo)準(zhǔn)(Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure)。
JDK 9中的java.util.concurrent.Flow中的概念,與Reactive Streams是一對一對等的。java.util.concurrent.Flow是Reactive Streams標(biāo)準(zhǔn)的實現(xiàn)之一。
多CPU的并行機制讓處理海量數(shù)據(jù)的速度更快,消息傳遞和響應(yīng)式編程讓有限的并行運行的線程執(zhí)行更多的I/O操作。 HttpClient的實現(xiàn)細(xì)節(jié) 請求響應(yīng)的body與reactive streams請求響應(yīng)的body暴露為reactive streams
http client是請求的body的消費者
http client是響應(yīng)的body的生產(chǎn)者
HttpRequest內(nèi)部public abstract class HttpRequest { ... public interface BodyPublisher extends Flow.PublisherHttpResponse的內(nèi)部{ ... } }
public abstract class HttpResponse{ ... public interface BodyHandler { BodySubscriber apply(int statusCode, HttpHeaders responseHeaders); } public interface BodySubscriber extends Flow.Subscriber > { ... } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/71991.html
摘要:在中也可以直接使用返回的是,然后通過來獲取結(jié)果阻塞線程,從中獲取結(jié)果四一點嘮叨非常的年輕,網(wǎng)絡(luò)資料不多,且代碼非常精細(xì)和復(fù)雜,目前來看底層應(yīng)該是使用了線程池搭配進(jìn)行異步通訊。 零 前期準(zhǔn)備 0 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 1 HttpClient 簡介 java.net.http.HttpClient 是 jdk11 中正式...
摘要:主要是為了實現(xiàn)系統(tǒng)之間的雙向解耦而實現(xiàn)的。問題及優(yōu)化隊列過長問題使用上述方案的異步非阻塞可能會依賴于的任務(wù)隊列長度,若隊列中的任務(wù)過多,則可能導(dǎo)致長時間等待,降低效率。 Tornado和Celery介紹 1.Tornado Tornado是一個用python編寫的一個強大的、可擴(kuò)展的異步HTTP服務(wù)器,同時也是一個web開發(fā)框架。tornado是一個非阻塞式web服務(wù)器,其速度相當(dāng)快。...
序 本文主要研究一下Java11的HttpClient的基本使用。 變化 從java9的jdk.incubator.httpclient模塊遷移到j(luò)ava.net.http模塊,包名由jdk.incubator.http改為java.net.http 原來的諸如HttpResponse.BodyHandler.asString()方法變更為HttpResponse.BodyHandlers.of...
摘要:從版本開始,不再單獨發(fā)布或者版本了,有需要的可以自己通過去定制官方解讀官方細(xì)項解讀穩(wěn)步推進(jìn)系列六的小試牛刀一文讀懂的為何如此高效棄用引擎 Java語言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13的新特性 序 本文主要講述一下Java11的新...
摘要:展示如下場景再現(xiàn)經(jīng)過分析,最后我們定位到是使用產(chǎn)生的內(nèi)存泄露問題。下面通過一個,來簡單講下具體內(nèi)存泄露的原因。這一次的內(nèi)存泄露問題算是解決了??偨Y(jié)關(guān)于內(nèi)存泄露問題在第一次排查時,往往是有點不知所措的。 記一次 JAVA 的內(nèi)存泄露分析 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blog 當(dāng)前環(huán)境 jdk == 1.8 ...
閱讀 707·2023-04-25 22:50
閱讀 1541·2021-10-08 10:05
閱讀 990·2021-09-30 09:47
閱讀 1926·2021-09-28 09:35
閱讀 830·2021-09-26 09:55
閱讀 3424·2021-09-10 10:51
閱讀 3436·2021-09-02 15:15
閱讀 3304·2021-08-05 09:57