关闭tcp连接后,响应流不会立即取消。
在1-2个空闲间隔后取消了keepAlive阶段响应流。
在闲置时间= 5秒内connectionRef
在5-10秒后收到终止消息。
public static void main(String[] args) {
ActorSystem actorSystem = ActorSystem.create();
ActorMaterializer mat = ActorMaterializer.create(actorSystem);
ConnectHttp connectHttp = ConnectHttp.toHost("0.0.0.0:8080");
ServerSettings serverSettings = ServerSettings.create(actorSystem);
Route route = Directives.complete(chunkedResponse(actorSystem, mat));
System.out.println("Starting server!");
Http.get(actorSystem)
.bindAndHandle(route.flow(actorSystem, mat), connectHttp, serverSettings, actorSystem.log(), mat);
}
private static ResponseEntity chunkedResponse(ActorSystem actorSystem, ActorMaterializer mat) {
Pair<ActorRef, Source<String, NotUsed>> p = Source
.actorRef(Int.MaxValue(), OverflowStrategy.fail())
.map(Object::toString)
.keepAlive(Duration.ofSeconds(5), () -> {
Instant now = Instant.now();
System.out.println(now + " send heartbeat");
return now + "\n";
})
.toMat(Sink.asPublisher(AsPublisher.WITHOUT_FANOUT), Keep.both()) // materialize as actorRef as publisher
.mapMaterializedValue(pair -> Pair.apply(pair.first(), Source.fromPublisher(pair.second())))
.run(mat);
ActorRef connectionRef = p.first();
Source<ByteString, NotUsed> streamSource = p.second()
.map(ByteString::fromString);
actorSystem.actorOf(ConnectionTerminationWatcher.props(connectionRef));
connectionRef.tell("open!\n", ActorRef.noSender());
return HttpEntities.create(ContentTypes.TEXT_CSV_UTF8, streamSource);
}
public static class ConnectionTerminationWatcher extends AbstractActor {
private final ActorRef connectionRef;
public ConnectionTerminationWatcher(ActorRef connectionRef) {
this.connectionRef = connectionRef;
}
public static Props props(ActorRef connectionRef) {
return Props.create(ConnectionTerminationWatcher.class, connectionRef);
}
@Override
public void preStart() throws Exception {
getContext().watchWith(connectionRef, "connection closed");
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals("connection closed", msg -> System.out.println(Instant.now() + " " + msg))
.build();
}
}
在此示例中,〜60秒后也没有取消keepAlive阶段响应流。
完整代码:https://gist.github.com/ortex/c86ee514c6e848285ee08889a114e716