HTTP/2 与 OkHttp3 和 Retrofit2

Posted

技术标签:

【中文标题】HTTP/2 与 OkHttp3 和 Retrofit2【英文标题】:HTTP/2 with OkHttp3 and Retrofit2 【发布时间】:2017-06-05 11:00:56 【问题描述】:

我花了很多时间在 OkHttp3 上实现 HTTP/2 支持,但我没有想法。

如何检查它是否有效:

在 access.log 中检查哪个协议使用连接到服务器的客户端: 浏览器:"GET /favicon.ico HTTP/2.0" 200 382 https://server.com "" Mozilla / 5.0 (X11; Linux x86_64)" 安卓客户端:'GET /api/v2/ ... HTTP/1.1 "200 3717" - "" android ..."

我用什么:

带有nginx/1.10.2https 的服务器 JAVA_VERSION="1.8.0_76" 安卓版本="6.0.1"

build.gradle

compile 'com.facebook.stetho:stetho-okhttp3:1.4.2'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
...

我如何使用:

 client = configureClient(new OkHttpClient().newBuilder())
          .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
          .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
          .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
          .protocols(Arrays.asList(Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1))
          .addInterceptor(new Interceptor() 
              @Override
              public Response intercept(Chain chain) throws IOException 
                ...
              
          )
          .addNetworkInterceptor(new StethoInterceptor())
          .build();

我尝试了什么

我发现我需要将 Jetty ALPN jar 添加到我的引导类路径中。 所以我刚刚在 build.gradle(Project) 中添加了以下几行:

allprojects 
  ...
    gradle.projectsEvaluated 
        tasks.withType(JavaCompile) 
          options.compilerArgs.add('-Xbootclasspath/p:/home/USER_NAME/Android/alpn-boot/alpn-boot-8.1.2.v20141202.jar')
        

我尝试了来自 https://mvnrepository.com/artifact/org.mortbay.jetty.alpn/alpn-boot 的所有 alpn-boot 版本,但没有,甚至是错误消息。

我也尝试在 build.gradle 中添加 compile("org.mortbay.jetty.alpn:alpn-boot:VERSION_NUMBER"),但使用版本 7* 仍然没有错误并且不起作用。 在版本 8* 中,我在构建应用程序时遇到以下错误:

Error:Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been compiled using Java 8 or above.
If you are using the 'java' gradle plugin in a library submodule add 
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
to that submodule's build.gradle file.

添加 targetCompatibility = '1.7' 和 sourceCompatibility = '1.7' 仍然没有。

提前感谢您的帮助

【问题讨论】:

【参考方案1】:

alpn-boot 仅用于标准(桌面/服务器)JVM。它不适用于 Android 设备。

在这种情况下,对 bootclasspath 的更改也是一个运行时选项,而不是编译器参数。

AFAIK 它应该在 Android 上自动为 https 请求工作。

n.b.我也看到了同样的情况,使用基于 okhttp 的测试客户端,为您的网站获取 http/1.1,但为 twitter 获取 http/2。

$ oksocial --debug -i https://api.twitter.com/robots.txt 2>&1  | grep protocol
11:30:28.849    protocol: h2

$ oksocial --debug -i https://debug.api.heyyka.com/api/v1/dev/err 2>&1 | grep protocol
11:30:45.381    protocol: http/1.1

我认为在您的情况下,您依赖 NPN 而不是 ALPN,而 okhttp 不支持。

$ nghttp -v https://debug.api.heyyka.com/api/v1/dev/err
[  0.189] Connected
[  0.362][NPN] server offers:
          * h2
          * http/1.1
The negotiated protocol: h2

【讨论】:

我知道我应该在服务器端寻找原因,对吧? 我认为这是最相关的链接nginx.com/blog/supporting-http2-google-chrome-users 我一直在重新编译支持 openssl-1.0.2+ 的 nginx,它现在可以工作了。 android代码没有任何变化。非常感谢@YuriSchimke!

以上是关于HTTP/2 与 OkHttp3 和 Retrofit2的主要内容,如果未能解决你的问题,请参考以下文章

Okhttp3、http2多路复用POST请求高峰负载时响应时间长

Okhttp3基本使用

关于Okhttp3介绍

HTTP/2 与 OkHttp

Okhttp3 网络请求框架与 Gson

深入浅出安卓热门网络框架 OKHttp3 和 Retrofit 原理