zoukankan      html  css  js  c++  java
  • Http2服务调用排坑记

    原文作者:陈友行
    原文链接:https://www.nginx.org.cn/article/detail/89
    转载来源:NGINX开源社区
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

       1.   了解HTTP2

    时代在发展,使用http协议的人越来越多。http1.1的弊端慢慢都被显现出来。

    1)   浏览器方式一些网站频繁发送请求,造成一家独大其他网站无法使用。或者所有网站都频发发送请求造成用户体验差等等问题。限制每个url同时并发数量。

    2)   提高请求的响应速度。只有一个连接,只有一次tcp三次握手或者tls的7次握手。一个http1.1请求所用的时间,http2.0可以处理三到四个请求。

    3)   提高服务端与客服端的性能(尤其是大型互联网公司流量很大,如果使用http2.0,可以减少一半的http服务器)。

    http客服端不知道http服务端是否支持http2.0。反过来 http服务端也不知道http客服端是否支持http2.0。为什么出现这种现象,让所有的http服务端与http客服端直接从http1.1过度到http2.0是不可能的事情。甚至在大点的公司内部直接从http1.1直接过度到http2.0也是一件不现实的事情,那么出现一件麻烦的事情有http1客服端,也有http2客服端。有http2服务端,也有http1服务端。这种两个维度,四种情况的共存现象。

    有人会问,只支持http1.1不好吗? 已经支持http2,.0的client肯定不会放弃http2.0优秀的性能与特性,能使用使用http2.0,就要使用。

    那么http2.0的设计者为了解决这种麻烦的东西。推出了解决方案:协商。

    https1.1与https2.0的协商是基于ALPN机制。ALPNS是基于TLS实现。在建立TLS链接的时候,客服端会 在TLS协议里面加入自己支持的协议,服务端在客服端支持的协议里面选中一个自己最合适的。然后把选中的协议通知给客服端。如果客户端没有发送支持的http协议,服务端会默认使用http1.1。

    http没有TLS协议,无法基于TLS传递协议。协议制定者使用了Upgrade机制。客户端发送一个空请求,请求里面包含该Upgrade,Connection,HTTP2-Settings请求头。服务端从Upgrade取出支持的协议然后响应请求,在响应的请求头里面包含Upgrade,Connection。这样协商就成功。

    下面是http1.1与http2.0的协商流程,请求头示例:

    GET / HTTP/1.1 Host: example.com Connection: Upgrade, HTTP2-Settings Upgrade: h2c HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

    如果服务端不支持 HTTP/2,它会忽略 Upgrade 字段,直接返回 HTTP/1.1 响应,例如:

    HTTP/1.1 200 OK Content-Length: 243 Content-Type: text/html

    如果服务端支持 HTTP/2,那就可以回应 101 状态码及对应头部:

    HTTP/1.1 100 Switching Protocols Connection: Upgrade Upgrade: h2c

    小结:

    1)https 1.1 与https.2.0的协商 与 http1.1与http2.0的协商是两套设计方案。https 1.1 与https.2.0 TLS自动实现。http1.1与http2.0的协商需要自己实现。

    2)现在的趋势,客服端与服务端都需要同时支持http1.1,http2.0,https1.1,https2.0,技术实现比较复杂。

    2.   问题初现

    1、项目的问题出在于通过JAVA端去调用华为提供的H2服务时,一直返回PROTOCOL_ERROR错误;但是同样的写法调用,自己写的H2服务是可以的,调用baidu,taobao,small都可以;也就是说明程序是可以用的,但为什么华为就是返回错误呢? 以下是华为侧回复的内容:

    意思是说客户端调用时使用的协议不对,服务端解析不了,要求我们在报文头加上协调参数。客户端按要求修改,但问题依旧;发现服务端并不支持协商的方式去调用,抓如下:

    2、其它工具验证:

    1)     浏览器调用不成功。

    2)     POSTMAN调用不成功。

    3)     CURL调用不成功。

    3、Jdk版本支持H2说明:

    原文链接:https://blog.csdn.net/taiyangdao/article/details/80883189

    1)     Java 8

    初始即支持TLS 1.2,并且客户端默认即使用TLS 1.2。

    但是为了支持HTTP2,还要借助于Jetty的ALPN模块alpn-boot。

    下载alpn-boot的jar,并且在启动JVM时加参数java -Xbootclasspath/p:<path_to_alpn_boot_jar> ...

    2)     Java 9

    初始即支持TLS 1.2,并且客户端默认即使用TLS 1.2。

    通过JEP 244, TLS ALPN Extension支持ALPN,完整支持了HTTP2。

    3)      Java 10

    同Java 9。

    4)     Java 11

    同Java 9,并进而支持TLS 1.3。

    3.   排查过程
    到此时发现,根据第二部分所讲,JAVA端调用HTTP2的以下两种方式都走不通:

    1)       调https方式,因为5G核心网为了提高效率,而且都是内部使用,规范中并不提供加密调用的方式,走不通。

    2)       走http1.1协商的方式,需要服务端根据协调参数,自动选择;但现在也不支持。

    3.1.  换jar包
    在此过程上反复的尝试了多种方法:

    1)升级到jdk11,通过原生的httpClient去调用,问题依旧:

    HttpClient client = HttpClient.newBuilder()       

    .version(HttpClient.Version.HTTP_2)       

    .priority(0)       

    .sslContext(SSLContext.getInstance("TLSv1.2"))       

    .build();

    2)  通过okHttpClient3.2去调用,问题依旧:

    3)  通过netty去调用,问题依旧。

         4)   协调了客户侧的网络专家帮忙分析,通过curl --http2调用,问题依旧。

    3.2. 分析C++成功案例:
    后台C++开发客户端是可以正常调用的,通过了解,C++指定了强制使用H2协议去调用,将包抓出来比对,发现在客户端发送请求时,确实存在差异:

    问题定位:

    java端是否有也类型的参数,可以指定强制使用H2方式去调用呢;

    3.3. 尝试curl命令
    首先通过curl进行反复的尝试:

    Curl 只设置了--http2 参数时调用不成功 。

    在https://curl.haxx.se/docs/http2.html 找到了参数--http2-prior-knowledge说明:

    Curl 通过 --http2-prior-knowledge 强制使用H2协议去调用,验证成功。

    3.4. 查找类prior-knowledge参数,解决问题
    在https://www.jianshu.com/p/9530d58250c7 中找到解决办法:

    动手尝试验证:

    第一步,升级okHttpClient包到4.1.0:

    第二步,编写测试程序:

    第三步,抓包验证,成功:

    4.   总结:java调用H2的方法
    4.1.  加密调用
    https1.1与https2.0的协商是基于ALPN机制。ALPNS是基于TLS实现。在建立TLS链接的时候,客服端会 在TLS协议里面加入自己支持的协议,服务端在客服端支持的协议里面选中一个自己最合适的。然后把选中的协议通知给客服端。如果客户端没有发送支持的http协议,服务端会默认使用http1.1

    4.2. 协商调用
      开源地址:https://http2.github.io/http2-spec/#discover-http:

    4.3. 强制指定H2方式调用



  • 相关阅读:
    服务器状态码
    QuerySet中添加Extra进行SQL查询
    django配置一个网站建设
    MySQL数据库查询中的特殊命令
    125. Valid Palindrome
    121. Best Time to Buy and Sell Stock
    117. Populating Next Right Pointers in Each Node II
    98. Validate Binary Search Tree
    91. Decode Ways
    90. Subsets II
  • 原文地址:https://www.cnblogs.com/exmyth/p/14856989.html
Copyright © 2011-2022 走看看