我正在研究是否升级http 2以实现微服务之间的通信。所以我使用okhhtp测试了h2c协议的性能。 但结果很奇怪。 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协议的spring-web服务器。 我期望在使用 okhttp 和 h2c 协议时获得更高的性能。
这是我的测试代码。
openjdk version "17.0.6" 2023-01-17 LTS
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 来压缩标头。
我怀疑,如果您的客户端和服务器在连接上有额外的延迟,并且您限制了客户端同时使用的 TCP 连接数,那么您的基准测试会显示 HTTP/2 是更好的选择。
🎄