springboot搭建http2服務器和h2c服務器 h2 的http/https 請求服務器


HTTP2.0特性
通俗易懂篇:https://www.cnblogs.com/yingsmirk/p/5248506.html
深入了解篇:https://www.jianshu.com/p/67c541a421f9
HTTP/2連接是建立在TCP連接之上的應用層協議,客戶端是TCP連接的發起者。

HTTP/2使用和HTTP/1.1一樣的 URI schemes:"http" 和 "https",並且還是共享同樣的默認端口:http的80,https的443。這意味着,對於"http" 和 "https"確定其是否支持HTTP/2協議的方式是不同的。

在官方文檔中,為HTTP/2協議定義了兩個版本:h2 和 h2c:

h2版本的協議是建立在TLS層之上的HTTP/2協議,這個標志被用在TLS應用層協議協商(TLS-ALPN)域和任何其它的TLS之上的HTTP/2協議。
h2c版本是建立在明文的TCP之上的HTTP/2協議,這個標志被用在HTTP/1.1的升級協議頭域和其它任何直接在TCP層之上的HTTP/2協議。
搭建帶有證書的h服務端:https://
要使用HTTP/2需要注意以下幾點

1.雖然HTTP/2沒有明確要求必須使用TLS,但當前幾乎所有瀏覽器均只支持 HTTP/2 Over TLS。所以在使用之前我們需要先制作一張證書。

2.如果您的項目中用的是tomcat或jetty,它們並不能直接支持HTTP/2,但是undertow可以。具體可以參考Spring Boot的文檔:https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#howto-configure-http2

3.我們制作的證書是不被瀏覽器認可的,所以會有安全提示,不能用於生產環境。

在本文的例子中使用的是undertow。

1.制作證書:

使用JDK自帶的keytool,證書類型為:PKCS12

打開cmd 輸入下面的命令:

keytool -genkey -alias undertow -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -dname "CN=localhost, OU=localhost, O=localhost, L=hangzhou, ST=zhejiang, C=CN"

輸入密鑰庫口令:

再次輸入新口令:

執行時會要求輸入證書口令,這里輸入的是123456。執行完命令后會在執行的文件夾生成一個keystore.p12的文件。

keytool

-genkey

-alias undertow (別名)

-storetype PKCS12 (證書類型)

-keyalg RSA (算法)

-keysize 2048 (秘鑰長度)

-keystore keystore.p12 (指定生成證書的位置和證書名稱)

-dname "

CN=localhost,(姓名姓氏)

 OU=localhost,(組織單位)

 O=localhost,(組織名稱)

 L=hangzhou,(所在城市或者區域名稱)

 ST=zhejiang,(所在的省/市/自治區名稱)

 C=CN"(該單位的雙字母國家/地區代碼)

keytool的詳細用法:

https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html

常見的證書格式及其說明參考:

http://www.cnblogs.com/xq1314/archive/2017/12/05/7987216.html

配置Web容器
spring boot默認使用的是tomcat,我們需要先將tomcat移除,然后換成undertow。

在搭建好的springboot項目中引入  注意springboot在2.0版本才開始支持http2,springboot2.0 支持的jdk最低版本為java8

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

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-undertow</artifactId>

</dependency>

 

如果不移除tomcat依賴會一直以Tomcat作為容器啟動。

然后將剛才生成的keystore.p12拷貝到src/main/resources下。

然后在application.properties中配置服務器信息。

#端口號
server.port=8443
#ip地址
server.address=0.0.0.0

#啟用HTTP響應壓縮
server.compression.enabled=true
# 啟用http2
server.http2.enabled=true
# 啟用ssl
server.ssl.enabled=true
#證書位置
server.ssl.key-store=classpath:keystore.p12
# 證書密碼
server.ssl.key-store-password=123456
# 證書類型
server.ssl.key-store-type= PKCS12
# 協議類型
server.ssl.protocol=TLSv1.2
server.ssl.key-alias=undertow
這時如果啟動服務器,是只支持https的。


@SpringBootApplication
public class DemoApplication implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>{

   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }

   @Override
   public void customize(UndertowServletWebServerFactory undertowServletWebServerFactory) {
      undertowServletWebServerFactory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
         @Override
         public void customize(Undertow.Builder builder) {
            builder.addHttpListener(8080, "0.0.0.0");
         }

      });
   }
}
這里增加8080端口的監聽,配置參考:

https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#howto-configure-webserver

https://docs.spring.io/spring-boot/docs/2.0.5.RELEASE/reference/htmlsingle/#howto-enable-multiple-listeners-in-undertow

啟動后可以看到控制台打印出如下信息:

 

測試
增加一個測試控制器

 

瀏覽器訪問:https://192.168.110.117:8443/someData

 

 

觀察兩次請求的size,一次是92一次是70,這是因為HTTP/2的頭部壓縮技術。

 

瀏覽器訪問:http://localhost:8080/someData   HTTP/1.1協議 而且數據包要比HTTP/2的數據包大,並且無論刷新多少次,大小是不變的。

 

 

搭建h2c服務端:http://


 

從Spring boot 2.0的官方文檔上看,明確寫明了“Spring boot 不支持h2c —— HTTP/2協議的明文版本”,於是就想其它辦法來支持h2c。

首先,想的是通過外置的tomcat配置來支持h2c,因為tomcat8.5中的server.xml配置中,有HTTP/2協議相關的配置:

 

這里顯示要添加證書,明顯支持的是基於TLS層之上的h2版本的HTTP/2協議,但是從配置上可以禁用SSL,於是就嘗試了一下,果然成功了。配置成如下示例,就支持h2c了:

<Connector port="5080" protocol="HTTP/1.1" connectionTimeout="20000">

    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /></Connector>

tomcat容器自身是支持多個connector的配置的,查看springboot2.0是否支持同時配置多個Connector

 

 

文檔中示例是通過 java configure 的方式配置一個https的connector,在application.properties中不支持配置多個connector。

因此模仿這外置tomcat配置h2c的方式,在Spring boot 2.0 的內置tomcat中通過java configure的方式配置h2c協議,具體代碼如下:

新建一個springboot項目,加入以下配置即可

/

**
 * h2c協議
 * @return
 */
@Bean
public ServletWebServerFactory servletContainer() {
   TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
   tomcat.addAdditionalTomcatConnectors(createH2cConnector());
   return tomcat;
}

private Connector createH2cConnector() {
   Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
   Http2Protocol upgradeProtocol = new Http2Protocol();
   connector.addUpgradeProtocol(upgradeProtocol);
   //connector.setScheme("http");
   connector.setPort(5080);

   return connector;
}
這時啟動我們的Spring boot應用,會發現最后的啟動日志有兩個端口

 

 

因為瀏覽器只支持h2 所以使用curl 驗證h2c的服務端 或者用wireshark抓包查看

檢查你的curl是否支持http2

 

從上面的 Features 信息發現,我的curl工具是支持HTTP/2協議的。

下面開始驗證我Spring boot 的服務在5080端口是否是h2c,具體如下:

輸入curl -v  --http2 "http://192.168.110.117:5080/someData"

 

從結果看 已經驗證通過。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM