前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java9+springboot2+undertow2启用http2及server push

java9+springboot2+undertow2启用http2及server push

作者头像
code4it
发布2018-09-17 16:02:20
1.7K0
发布2018-09-17 16:02:20
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究下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生成实例

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实例

controller

@RestController
public class IndexController {

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

运行

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参数忽略校验https,否则报错

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实例

maven改动

    <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());
    }

运行

  • 不启用server push

没有用server push,在在Initiator那栏,看到的是/demo这个触发的。点开waterfall,会看到Content Download的耗时。

  • 启用server push

可以看到如果是用server push的,在Initiator那栏,有个Push标识,点开waterfall,会看到reading push的耗时。

小结

随着java9支持HTTP2,servlet4引入PushBuilder支持server push,使用java作为服务端开发语言的开发者可以更方便地将HTTP2实践起来。

截止到写这篇文章之时,几大servlet容器的servlet4支持情况:

  • jetty尚且没有看到支持servlet4的实现版本发布;
  • tomcat有9.x版本支持servlet4,但是在springboot2上替换依赖报错,整体实践起来稍稍麻烦;
  • undertow2.0.1.Final版本支持servlet4,在springboot2上替换依赖,非常简单,没有报错,这也是本文选择undertow的原因。

doc

  • HTTP/2 服务器推送(Server Push)教程
  • HTTP/2 PUSH(推送)与HTTP Preload(预加载)大比拼| Dexecure
  • tomcat-9.0-doc
  • Undertow provides support for Servlet 4.0, including support for embedded servlet
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • maven
  • 配置
    • application.yml
      • ENABLE_HTTP2及ENABLE_PUSH
      • HTTP2实例
        • controller
          • 运行
          • server push实例
            • maven改动
              • controller
                • 运行
                • 小结
                • doc
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档