java - OKhttp h2c协议(protocol)比HTTP1.1协议(protocol)慢

标签 java http okhttp http2

我正在研究是否升级 http 2 以实现微服务之间的通信。所以我使用okhhtp测试了h2c协议(protocol)的性能。 但结果很奇怪。 H2c 的性能甚至不如http1.1。我的测试方法或场景有问题吗?

当并发线程较多时,H2c 的性能较差。

# 20 thread

http1.1
Benchmark        Mode  Cnt   Score   Error  Units
JMHTest.request  avgt   10  30.997 ± 0.185  ms/op

h2c
Benchmark        Mode  Cnt   Score   Error  Units
JMHTest.request  avgt   10  32.816 ± 1.022  ms/op

# 50 thread

http1.1
Benchmark        Mode  Cnt   Score   Error  Units
JMHTest.request  avgt   10  31.286 ± 0.555  ms/op

h2c
Benchmark        Mode  Cnt   Score   Error  Units
JMHTest.request  avgt   10  72.564 ± 0.678  ms/op

我使用JMH进行测试,我的服务器是启用了HTTP2协议(protocol)的spring-web服务器。 我期望将 okhttp 与 h2c 协议(protocol)结合使用时获得更高的性能。

这是我的测试代码。

环境

  • Jdk:openjdk 版本“17.0.6”2023-01-17 LTS
  • okhttp3:5.0.0-alpha.12

客户端

@State(Scope.Benchmark)
public class JMHTest {
    private static final OkHttpClient CLIENT = HttpClientFactory.buildH2PriorClient();
    private static final String URL = "http://localhost:8080/hello";
    private static final Request REQUEST = new Request.Builder()
            .url(URL)
            .post(RequestBody.create(MediaType.get("text/plain"), BodyConstant.BODY_100B))
            .build();

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JMHTest.class.getSimpleName())
                .build();

        new Runner(opt).run();
    }

    @BenchmarkMode({Mode.AverageTime})
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    @Fork(value = 2, warmups = 1)
    @Warmup(iterations = 2)
    @Measurement(iterations = 5)
    @Threads(20)
    @Benchmark
    public void request() {
        post();
    }

    @SneakyThrows
    private void post() {
        Call call = CLIENT.newCall(REQUEST);
        try (Response response = call.execute()) {
            try (ResponseBody body = response.body()) {
                if (!response.isSuccessful()) {
                    throw new RuntimeException();
                }
            }
        }
    }
}
public class HttpClientFactory {

    public static OkHttpClient buildClient() {
        return getClientBuilder().build();
    }

    public static OkHttpClient buildH2PriorClient() {
        OkHttpClient.Builder builder = getClientBuilder();
        builder.setProtocols$okhttp(List.of(Protocol.H2_PRIOR_KNOWLEDGE));
        return builder.build();
    }

    @SneakyThrows
    private static OkHttpClient.Builder getClientBuilder() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.setReadTimeout$okhttp(3000);
        builder.setConnectTimeout$okhttp(3000);
        builder.setReadTimeout$okhttp(3000);
        builder.setWriteTimeout$okhttp(3000);
        return builder;
    }
}

最佳答案

HTTP/2 会牺牲少量额外的 CPU 工作量(通常不是 HTTP 调用的瓶颈),以减少创建的 TCP 和 TLS 连接的数量,并减少传输的数据包数量。例如,它使用HPACK来压缩 header 。

如果您的客户端和服务器在连接上有额外的延迟,并且您限制了客户端同时使用的 TCP 连接数,我怀疑您的基准测试会显示 HTTP/2 是更好的选择。

🎄

关于java - OKhttp h2c协议(protocol)比HTTP1.1协议(protocol)慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77713082/

相关文章:

http - 将 angularjs http-auth 与 $resource 一起使用

android - OkHttp 客户端的最佳/不易出错的缓存大小是多少(与 exoplayer 一起使用)

java - 对 previous 的第一次调用如何返回与最后一次调用 next 相同的元素?

java - 删除 Java 中的 HTTP 响应 header

java - 使用 javax.mail 删除服务器上的电子邮件

angularjs - Http进度功能?

php - 您采取了哪些步骤来解决 PHP cURL 问题?

android - Retrofit2 + RxJava 错误处理

android - OKHTTP 无法解析主机 没有与主机名关联的地址

java - 如何使用 lwuit 使用可停止的 http 连接?