Streaming¶
목차 | 이전: 인증·TLS·Proxy | 다음: Client와 요청의 생애
다른 언어로 보기 — C++ · C#/.NET · Java · Kotlin · Node/TypeScript
이 장을 읽고 나면
응답을 chunk로 처리하고 요청 body를 나누어 보낼 수 있다. 이 장의 코드는 각 언어의 HttpClient tutorial에서 가져왔다.
Streaming은 큰 body를 호출자 쪽 callback 또는 provider로 옮기는 경로다. JSON body와 달리 body 전체를 직렬화하거나 누적하지 않는다. status와 압축 규칙은 응답 처리 규칙에서 확인한다.
provider와 sink는 body가 이동하는 동안 한 번씩만 소비된다. 이 특성 때문에 streaming 경로에는 재전송과 투명 압축 해제가 적용되지 않는다.
1. Download sink로 응답을 받는다¶
download sink는 수신한 body chunk마다 호출되는 callback이다. raw 응답은 status와 header, JSON으로 읽기 전 body를 담는 응답이다. download가 돌려주는 최종 raw 응답은 status와 header를 보존하며, redirect 중간 응답 body는 sink로 전달하지 않는다.
AtomicInteger chunks = new AtomicInteger();
AtomicInteger bytes = new AtomicInteger();
client.get("/rooms/" + roomId + "/export")
.download(
chunk -> {
chunks.incrementAndGet();
bytes.addAndGet(chunk.length);
})
.toCompletableFuture()
.join();
System.out.println("download stream: chunks " + chunks.get() + " bytes " + bytes.get());
예제는 export body를 chunk마다 세어 전체 chunk 수와 byte 수를 누적한다.
2. Body stream provider로 요청을 보낸다¶
body stream provider는 전송할 다음 chunk를 반환하고, 언어의 빈 값으로 끝을 알린다. content type은 provider와 함께 지정한다.
byte[][] lines = {
"{\"playerId\":\"p2\",\"text\":\"import-1\"}\n".getBytes(StandardCharsets.UTF_8),
"{\"playerId\":\"p2\",\"text\":\"import-2\"}\n".getBytes(StandardCharsets.UTF_8),
"{\"playerId\":\"p2\",\"text\":\"import-3\"}\n".getBytes(StandardCharsets.UTF_8),
};
AtomicInteger nextLine = new AtomicInteger();
HttpResponse<Imported> imported =
client.post("/rooms/" + roomId + "/import")
.bodyStream(
() -> {
int index = nextLine.getAndIncrement();
return index < lines.length ? lines[index] : null;
},
"application/x-ndjson")
.submit(Imported.class)
.toCompletableFuture()
.join();
System.out.println("upload stream: imported " + imported.body().imported());
예제는 NDJSON 세 줄을 차례로 공급하고 서버가 세 항목을 가져온 결과를 확인한다.
3. 재시도와 압축을 기대하지 않는다¶
download sink와 body stream provider는 한 번 소비하면 같은 body를 다시 만들 수 없다. 따라서 streaming 요청은 retry 대상이 아니며 redirect 재전송에도 사용하지 않는다. download sink에는 압축 해제가 적용되지 않아 압축된 응답의 원시 바이트를 받는다.
4. 다음 장¶
client 재사용, close 시점, 응답 완료 방식과 timeout 경계는 Client와 요청의 생애에서 다룬다.