我的HttpServer响应带有某些内容的http get请求。该内容相对较小,但可能需要一段时间才能获得。据我了解反应式堆栈,我应该给HttpServerResponse提供Mono或Flux,并且我的服务应该在Netty worker线程以外的其他线程中使用后台阻塞IO。例如:
class SomeService {
private static final ExecutorService EXECUTOR = ...
public Mono<String> load() {
CompletableFuture<String> future = new CompletableFuture<>();
EXECUTOR.submit(() -> loadContent(future));
Mono<String> ret = Mono.fromFuture(future).onErrorResume(Mono::error);
return ret;
}
private void loadContent(CompletableFuture<String> cf) {
String s = doBlockingLoadFromSomewhere();
cf.complete(s);
}
}
class Server {
private SomeService loader;
void activate() {
InetSocketAddress address = getAddressSomehow();
server = HttpServer.create()
.host(address.getHostString())
.port(address.getPort())
.route(routes -> routes.get("/path", this::handlePath))
.bindNow();
}
private Publisher<Void> handlePath(HttpServerRequest request, HttpServerResponse response)
{
Mono<String> contentMono = loader.load();
return response.status(OK).sendString(contentMono);
}
}
除了一个例外,它工作得很好。我必须发送一个CONTENT_LENGTH标头,但是Reactor-netty不会自动设置它,所以我必须自己做。 我有一个明显的方法来阻止和计算内容长度(如果可用),但是它将阻止Netty线程。 我试图将整个NettyOutbound组成一个Mono,但是这完全丢失了内容,可能是我做错了。
private Publisher<Void> handlePath(HttpServerRequest request, HttpServerResponse response)
{
Mono<String> contentMono = loader.load();
Mono<NettyOutbound> handling = contentMono.flatMap(str -> {
NettyOutbound r = response.status(OK)
.header(CONTENT_LENGTH, Long.valueOf(str.length()).toString())
.sendString(Mono.just(str), UTF_8);
return Mono.just(r);
});
return handling.then();
}
请告诉我,有没有一种标准的发送CONTENT_LENGTH的方法(并且通常在内容Mono准备就绪时编写响应标头)而不阻塞Netty worker线程? 换一种说法。所有文档样本都立即构成响应头,并在准备就绪时构成内容。内容准备就绪时,如何构成响应标题和响应内容?
PS 我正在使用io.projectreactor:reactor-core:3.2.5.RELEASE和io.projectreactor.netty:reactor-netty:0.8.4.RELEASE