jdk9开始支持IO多路复用,jdk11开始在java.net包中实现http2
springboot下配置undertow
application.yaml
# 应用端口
server:
port: 8080
http2:
enabled: true
use-forward-headers: true
package server.config;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.undertow.UndertowOptions;
@Configuration
public class Http2Config {
@Bean
UndertowServletWebServerFactory undertowServletWebServerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(
builder -> {
builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)
.setServerOption(UndertowOptions.HTTP2_SETTINGS_ENABLE_PUSH,true);
});
return factory;
}
}
客户端实现
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandler;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.concurrent.CountDownLatch;
public class TestResttemplate {
public static void main(String args[]) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/hello?id=1")).build();
BodyHandler
HttpResponse
try {
response = client.send(request, responseBodyHandler);
String body = response.body();
System.out.println(body);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.sleep(5000);
CountDownLatch latch = new CountDownLatch(1);
for(int i= 0;i<10;i++) {
connect(client,i,latch);
}
latch.countDown();
Thread.sleep(10000);
}
public static void connect(HttpClient client,int i,CountDownLatch latch) throws IOException, InterruptedException {
Thread thread = new Thread(()->{
HttpRequest request = HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/hello?id="+i)).version(Version.HTTP_2).build();
BodyHandler
HttpResponse
try {
latch.await();
response = client.send(request, responseBodyHandler);
String body = response.body();
System.out.println(body);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}) ;
thread.start();
}
}
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(int id) {
try {
Thread.sleep(id*100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello:"+id;
}
}
jdk11的httpclient首次建立TCP后(高并发的时候应该考虑使用连接池,初始链接数,不然并发下依然会创建多个TCP连接),其他共用一个TCP连接,根据id的大小进行sleep,可以看出IO多路复用是非阻塞,一次性可以确认多个数据包,seq=350