java9+springboot2+undertow2啟用http2及server push

本文主要研究下java9+springboot2+undertow2啟用http2及server push

maven

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>9</java.version>
    </properties>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

注意這里使用undertow端壳,移除掉了starter-web中的tomcat依賴

配置

application.yml

server:
  port: 8443
  ssl:
    key-store: classpath:keystore.jks
    key-store-password: xxx
    key-password: xxx
    protocol: TLSv1.2
  http2:
    enabled: true
  use-forward-headers: true

keystore生成實(shí)例

keytool -genkey -keyalg RSA -alias selfsigned -keystore src/main/resources/keystore.jks -storepass xxx -validity 360 -keysize 2048

ENABLE_HTTP2及ENABLE_PUSH

@Configuration
public class Http2Config {

    @Bean
    UndertowServletWebServerFactory undertowServletWebServerFactory() {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        factory.addBuilderCustomizers(
                builder -> {
                    builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
                            .setServerOption(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH,true);
                });

        return factory;
    }
}

這里開啟了HTTP2以及server push功能

HTTP2實(shí)例

controller

@RestController
public class IndexController {

    /**
     * curl -Ik --http2 https://localhost:8443/hello
     * @return
     */
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }
}    

運(yùn)行

curl -Ivk --http2 https://localhost:8443/hello
*   Trying ::1...
* Connected to localhost (::1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /usr/local/etc/openssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*    subject: C=ZH; ST=guangdong; L=shenzhen; O=spring; OU=springboot; CN=localhost
*    start date: Mar  9 14:10:54 2018 GMT
*    expire date: Mar  4 14:10:54 2019 GMT
*    issuer: C=ZH; ST=guangdong; L=shenzhen; O=spring; OU=springboot; CN=localhost
*    SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* TCP_NODELAY set
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f8a5280ea00)
> HEAD /hello HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/2.0 200
HTTP/2.0 200
< content-type:text/plain;charset=UTF-8
content-type:text/plain;charset=UTF-8
< content-length:5
content-length:5
< date:Fri, 09 Mar 2018 15:18:36 GMT
date:Fri, 09 Mar 2018 15:18:36 GMT

<
* Connection #0 to host localhost left intact

注意宴卖,這里curl命令使用-k參數(shù)忽略校驗(yàn)https羊赵,否則報(bào)錯(cuò)

curl -I --http2 https://localhost:8443/hello
curl: (60) SSL certificate problem: self signed certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

server push實(shí)例

maven改動(dòng)

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>9</java.version>
        <servlet-api.version>4.0.0</servlet-api.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.undertow</groupId>
            <artifactId>undertow-core</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>io.undertow</groupId>
            <artifactId>undertow-servlet</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>io.undertow</groupId>
            <artifactId>undertow-websockets-jsr</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.undertow</groupId>
                    <artifactId>undertow-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.undertow</groupId>
                    <artifactId>undertow-servlet</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.undertow</groupId>
                    <artifactId>undertow-websockets-jsr</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

由于server push需要servlet4版本再菊,目前springboot2依賴的undertow還是1.4版本的還只是servlet3吱雏,因此這里需要額外exclude掉再引入undertow2版本以支持servelt4

controller

    @GetMapping("/demo")
    public void http2ServerPush(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PushBuilder pushBuilder = request.newPushBuilder();
        pushBuilder
                .path("/demo.png")
                .addHeader("content-type", "image/png")
                .push();
        try(PrintWriter respWriter = response.getWriter()){
            respWriter.write("<html>" +
                            "<img src='/demo.png'>" +
                    "</html>");
        }
    }
   
    @GetMapping(value = "/demo.png")
    public void download(HttpServletResponse response) throws IOException {
        InputStream data = getClass().getClassLoader().getResourceAsStream("demo.png");
        response.setHeader("content-type", "image/png");
        FileCopyUtils.copy(data,response.getOutputStream());
    }    

運(yùn)行

  • 不啟用server push


    屏幕快照 2018-03-10 下午3.19.49.png

沒(méi)有用server push碧信,在在Initiator那欄垫挨,看到的是/demo這個(gè)觸發(fā)的。點(diǎn)開waterfall,會(huì)看到Content Download的耗時(shí)祸轮。

  • 啟用server push


    屏幕快照 2018-03-10 下午3.18.45.png

可以看到如果是用server push的兽埃,在Initiator那欄,有個(gè)Push標(biāo)識(shí)适袜,點(diǎn)開waterfall柄错,會(huì)看到reading push的耗時(shí)。

小結(jié)

隨著java9支持HTTP2苦酱,servlet4引入PushBuilder支持server push鄙陡,使用java作為服務(wù)端開發(fā)語(yǔ)言的開發(fā)者可以更方便地將HTTP2實(shí)踐起來(lái)。

截止到寫這篇文章之時(shí)躏啰,幾大servlet容器的servlet4支持情況:

  • jetty尚且沒(méi)有看到支持servlet4的實(shí)現(xiàn)版本發(fā)布趁矾;
  • tomcat有9.x版本支持servlet4,但是在springboot2上替換依賴報(bào)錯(cuò)给僵,整體實(shí)踐起來(lái)稍稍麻煩毫捣;
  • undertow2.0.1.Final版本支持servlet4,在springboot2上替換依賴帝际,非常簡(jiǎn)單蔓同,沒(méi)有報(bào)錯(cuò),這也是本文選擇undertow的原因蹲诀。

doc

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斑粱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脯爪,更是在濱河造成了極大的恐慌则北,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痕慢,死亡現(xiàn)場(chǎng)離奇詭異尚揣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)掖举,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門快骗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人塔次,你說(shuō)我怎么就攤上這事方篮。” “怎么了励负?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵藕溅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我熄守,道長(zhǎng)蜈垮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任裕照,我火速辦了婚禮攒发,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晋南。我一直安慰自己惠猿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布负间。 她就那樣靜靜地躺著偶妖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪政溃。 梳的紋絲不亂的頭發(fā)上趾访,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音董虱,去河邊找鬼扼鞋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愤诱,可吹牛的內(nèi)容都是我干的云头。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼淫半,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼溃槐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起科吭,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤昏滴,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后对人,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體影涉,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年规伐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蟹倾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猖闪,死狀恐怖鲜棠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情培慌,我是刑警寧澤豁陆,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站吵护,受9級(jí)特大地震影響盒音,放射性物質(zhì)發(fā)生泄漏表鳍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一祥诽、第九天 我趴在偏房一處隱蔽的房頂上張望譬圣。 院中可真熱鬧,春花似錦雄坪、人聲如沸厘熟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绳姨。三九已至,卻和暖如春阔挠,著一層夾襖步出監(jiān)牢的瞬間飘庄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工购撼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竭宰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓份招,卻偏偏與公主長(zhǎng)得像切揭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锁摔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,778評(píng)論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理廓旬,服務(wù)發(fā)現(xiàn),斷路器谐腰,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 從三月份找實(shí)習(xí)到現(xiàn)在孕豹,面了一些公司,掛了不少十气,但最終還是拿到小米励背、百度、阿里砸西、京東叶眉、新浪、CVTE芹枷、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,218評(píng)論 11 349
  • 轉(zhuǎn)自陳明乾的博客衅疙,可能有一定更新。 轉(zhuǎn)原文聲明:原創(chuàng)作品鸳慈,允許轉(zhuǎn)載饱溢,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章 原始出處 、...
    C86guli閱讀 4,675評(píng)論 6 72
  • 竹 一棵書 連續(xù)的章節(jié) 都是虛空 窗口 睜開眼睛走芋,呼吸著 張大嘴 聽見了嗎绩郎?發(fā)出聲吧 雪 在冰冷的旋律里 捕捉和收...
    明天朔閱讀 363評(píng)論 0 3