zoukankan      html  css  js  c++  java
  • [http] http版本的选择/http2的启动

    前言

    http2可以承载在TCP上或者TLS上,分别简称h2和h2c

    当访问一个服务的时候,到底用http1.1还是http2,client和server是可以协商的。

    [https://www.cnblogs.com/hugetong/p/13410276.html]

    TLS承载HTTP2

    RFC规定,TLS承载HTTP2时,TLS必须实现ALPN功能。

    implementations that support HTTP/2 over TLS MUST use protocol
       negotiation in TLS 

    nginx里可以这样配置:这样配置之后,5000端口可以同时为http2与http1.1提供服务。

            server {
                    listen 0.0.0.0:5000 http2 ssl;
                    ssl_certificate /data/sni/sni_test3.cer;
                    ssl_certificate_key /data/sni/sni_test3.key;
                    location / {
                            proxy_pass http://httpt7/;
                    }
            }

    使用curl测试如下:

    http2

    ╰─>$ curl -v -k  https://t9:5000/
    *   Trying 192.168.7.9:5000...
    * Connected to t9 (192.168.7.9) port 5000 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: /etc/ssl/certs/ca-certificates.crt
      CApath: none
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (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, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * 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=CN; ST=BeiJing; L=BeiJing; O=tong.com; OU=tong; CN=caotong_test3; emailAddress=tong@local
    *  start date: Sep 24 10:00:10 2019 GMT
    *  expire date: Sep 21 10:00:10 2029 GMT
    *  issuer: C=CN; ST=BeiJing; L=BeiJing; O=Tartaglia; CN=TTTrust; emailAddress=ca@tartaglia.org
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x5635fa55b8b0)
    > GET / HTTP/2
    > Host: t9:5000
    > user-agent: curl/7.70.0
    > accept: */*
    > 
    * Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
    < HTTP/2 200 
    < server: tong.localhost
    < date: Fri, 31 Jul 2020 07:41:11 GMT
    < content-type: text/html
    < content-length: 660
    < last-modified: Thu, 02 Apr 2020 08:45:48 GMT
    < etag: "5e85a63c-294"
    < accept-ranges: bytes
    < 
    <!DOCTYPE html>
    <html>
    xxx
    </html>
    * Connection #0 to host t9 left intact

    http1

    ╰─>$ curl -v -k --http1.1 https://t9:5000/
    *   Trying 192.168.7.9:5000...
    * Connected to t9 (192.168.7.9) port 5000 (#0)
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: /etc/ssl/certs/ca-certificates.crt
      CApath: none
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (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, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    *  subject: C=CN; ST=BeiJing; L=BeiJing; O=tong.com; OU=tong; CN=caotong_test3; emailAddress=tong@local
    *  start date: Sep 24 10:00:10 2019 GMT
    *  expire date: Sep 21 10:00:10 2029 GMT
    *  issuer: C=CN; ST=BeiJing; L=BeiJing; O=Tartaglia; CN=TTTrust; emailAddress=ca@tartaglia.org
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    > GET / HTTP/1.1
    > Host: t9:5000
    > User-Agent: curl/7.70.0
    > Accept: */*
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Server: TONG
    < Date: Fri, 31 Jul 2020 07:45:34 GMT
    < Content-Type: text/html
    < Content-Length: 660
    < Connection: keep-alive
    < Last-Modified: Thu, 02 Apr 2020 08:45:48 GMT
    < ETag: "5e85a63c-294"
    < Accept-Ranges: bytes
    < 
    <!DOCTYPE html>
    <html>
    xxx
    </html>
    * Connection #0 to host t9 left intact

    TCP承载HTTP2

    nginx配置:

            server {
                    listen 0.0.0.0:5000 http2;
                    location / {
                            proxy_pass http://httpt7/;
                    }
            }

    curl访问,必须采用显示约定的方式进行访问。显示约定是指client事先知道了对方是http2,curl的话,要参数 http2-prior-knowledge指定

    ╰─>$ curl -v -k --http2-prior-knowledge http://t9:5000/
    *   Trying 192.168.7.9:5000...
    * Connected to t9 (192.168.7.9) port 5000 (#0)
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x55f343ece8b0)
    > GET / HTTP/2
    > Host: t9:5000
    > user-agent: curl/7.70.0
    > accept: */*
    > 
    * Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
    < HTTP/2 200 
    < server: TONG
    < date: Fri, 31 Jul 2020 07:48:36 GMT
    < content-type: text/html
    < content-length: 660
    < last-modified: Thu, 02 Apr 2020 08:45:48 GMT
    < etag: "5e85a63c-294"
    < accept-ranges: bytes
    < 
    <!DOCTYPE html>
    <html>
    xxx
    </html>
    * Connection #0 to host t9 left intact

    一般来说,server应该有能力与client协商版本。但是很遗憾目前nginx还不支持。这个feature已经被提出,还没有被开发。见:https://trac.nginx.org/nginx/ticket/816

     

    h2c的时候怎么协商?

    首先client发一个http1.1的请求过去,并携带着header 希望upgrade到http2,如果server愿意,将回一个101的response

    如下例子: (这个例子是nignx不支持,拒绝的情况)

    ╰─>$ curl -v -k --http2 http://t9:5000/
    *   Trying 192.168.7.9:5000...
    * Connected to t9 (192.168.7.9) port 5000 (#0)
    > GET / HTTP/1.1
    > Host: t9:5000
    > User-Agent: curl/7.70.0
    > Accept: */*
    > Connection: Upgrade, HTTP2-Settings
    > Upgrade: h2c
    > HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA
    > 
    * Received HTTP/0.9 when not allowed
    
    * Closing connection 0
    curl: (1) Received HTTP/0.9 when not allowed

     (假如不拒绝,将回复如下:)

         HTTP/1.1 101 Switching Protocols
         Connection: Upgrade
         Upgrade: h2c
    
         [ HTTP/2 connection ...

    当server只支持http1时,试图升到http2的client会回落至http1正常工作,如下:

    ╰─>$ curl -v -k --http2 http://t9:5000/
    *   Trying 192.168.7.9:5000...
    * Connected to t9 (192.168.7.9) port 5000 (#0)
    > GET / HTTP/1.1
    > Host: t9:5000
    > User-Agent: curl/7.70.0
    > Accept: */*
    > Connection: Upgrade, HTTP2-Settings
    > Upgrade: h2c
    > HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA
    > 
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Server: TONG
    < Date: Fri, 31 Jul 2020 08:01:12 GMT
    < Content-Type: text/html
    < Content-Length: 660
    < Connection: keep-alive
    < Last-Modified: Thu, 02 Apr 2020 08:45:48 GMT
    < ETag: "5e85a63c-294"
    < Accept-Ranges: bytes
    < 
    <!DOCTYPE html>
    <html>
    xxx
    </html>
    * Connection #0 to host t9 left intact

    总结一下

    client访问http2 server的时候,分两种情况,一种是自适应版本的协商方式。一种是显式指定版本为http2的方式。

    自适应的方式分两种情况tls承载与tcp承载。

    tls承载时,使用ALPN。tcp承载时,client使用Upgrade header尝试http2,serveri接受便回复101开始http2,server不接受就正常用http1答复。

    参考:https://tools.ietf.org/html/rfc7540#section-3

  • 相关阅读:
    openstack 之Queen版本安装完成创建实例状态报错为ERROR
    重启nova-scheduler服务,报错Login was refused using authentication mechanism AMQPLAIN
    Failed to contact the endpoint at http://controller:35357/ for discovery. Fallback to using that endpoint as the base url.
    在centos系统的/etc/hosts添加了 当前主机的 ‘ NAT分配的IP controller’,RabbitMQ添加用户报错。
    一对简单的IPV6 SOCKET代码
    字节转换函数
    libevent笔记6:ssl bufferevent
    libevent笔记5:水位watermarks
    libevent笔记4:Filter_bufferevent过滤器
    libevent笔记3:evbuffer
  • 原文地址:https://www.cnblogs.com/hugetong/p/13410276.html
Copyright © 2011-2022 走看看