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方式调用
Http2服务调用排坑记的更多相关文章
- element UI排坑记(一):判断tabs组件是否切换
之所以将这个问题列在排坑记之中,是因为官方组件的一个属性颇有些隐蔽,这个问题曾经折腾了本人较多时间,始终思维固着,且使用搜索引擎也不容易搜索到答案,故记之.然而实际解决却是相当简单的. 一.问题描述 ...
- Spring Cloud ZooKeeper集成Feign的坑2,服务调用了一次后第二次调用就变成了500,错误:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.n
错误如下: 2017-09-19 15:05:24.659 INFO 9986 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refre ...
- Spark踩坑记——从RDD看集群调度
[TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...
- 【转】Vue 脱坑记 - 查漏补缺(汇总下群里高频询问的xxx及给出不靠谱的解决方案)
前言 文章内容覆盖范围,芝麻绿豆的破问题都有,不止于vue; 给出的是方案,但不是手把手一字一句的给你说十万个为什么! 有三类人不适合此篇文章: “喜欢站在道德制高点的圣母婊” – 适合去教堂 “无理 ...
- Vue + TypeScript + Element 搭建简洁时尚的博客网站及踩坑记
前言 本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 . TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript ...
- Spring Cloud Gateway入坑记
Spring Cloud Gateway入坑记 前提 最近在做老系统的重构,重构完成后新系统中需要引入一个网关服务,作为新系统和老系统接口的适配和代理.之前,很多网关应用使用的是Spring-Clou ...
- IdentityServer 部署踩坑记
IdentityServer 部署踩坑记 Intro 周末终于部署了 IdentityServer 以及 IdentityServerAdmin 项目,踩了几个坑,在此记录分享一下. 部署架构 项目是 ...
- <<Python编程:从入门到实践>>踩坑记 Django
<<Python编程:从入门到实践>>踩坑记 Django Django Python 19.1.1.5 模板new_topic 做完书上的步骤后,对主题添加页面经行测试,但是 ...
- 【踩坑记】从HybridApp到ReactNative
前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...
- Spark踩坑记——共享变量
[TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...
随机推荐
- Java日期时间API系列36-----Jdk8中java.time包中的新的日期时间API类应用,使用LocalTime计算十二时辰。
十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰.二十四小时和十二时辰对照表: 时辰 时间 24时制 子时 深夜 11:00 - 凌晨 01:00 23:00 - 01 : ...
- Teradata退出中国,您可以相信中国数据库!
继Adobe.Tableau.Salesforce之后,2023年2月15日,数仓软件巨头Teradata宣布将逐步结束在中国的直接运营.数仓界的"黄埔军校"仓皇撤出中国市场给出的 ...
- 墨天轮沙龙 | 北京大学李文杰:面向知识图谱应用的图数据库系统gStore
在6月8日举办的[墨天轮数据库沙龙第七期-开源生态专场]中,北京大学重庆大数据研究院图数据库与知识图谱实验室副主任.北京大学王选计算机研究所全职博士后 李文杰老师分享了<面向知识图谱应用的图数据 ...
- 66.有没有碰到过数组响应丢失(问的是ref和reactive的用法,什么情况下用)
由于vue3使用proxy,对于对象和数组都不能直接整个赋值. 直接赋值丢失了响应性 只有push或者根据索引遍历赋值才可以保留reactive数组的响应性 : 可以使用 toRefs 解决这个问 ...
- 现代化 React UI 库:Material-UI 详解!
随着 React 在前端开发中的流行,越来越多的 UI 框架和库开始涌现,以帮助开发者更高效地构建现代化.响应式的用户界面.其中,Material-UI 是基于 Google Material Des ...
- 云原生爱好者周刊:Crossplane 成为 CNCF 孵化项目
云原生一周动态要闻: Crossplane 成为 CNCF 孵化项目 VMware Tanzu Kubernetes Grid 1.4 发布 Sqlcommenter 与 OpenTelemetry ...
- LiveData
ViewModel 添加依赖 implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' activity_main.xml < ...
- python操作pptx设置title字体大小插入全屏图片A4尺寸实例一枚
pip install python-pptx 安装好pptx,设置标题最大的作用是ppt里面的摘要视图显示摘要文字 参考:https://python-pptx.readthedocs.io/en/ ...
- 强化学习:gym下atari游戏环境的官方文档地址
2024年10月16日 共建议查看两个历史上的官方地址: https://ale.farama.org/ https://www.gymlibrary.dev/ 最新官方地址: https://ale ...
- UE4纯C++实现游戏快捷栏之物品读取
我们在上一步骤中创建了快捷栏的UI界面,在这一部分我们将从Json文件中读取物品的相关信息(种类以及属性),来填充到游戏数据中进行存储以便快捷栏使用,具体分以下几部分完成. 1.Types.h: 添加 ...