当客户端接收到对冲请求集合中的一个完成时,会取消其他的请求,被取消的请求最终会提交一个 CancelClientStreamCommand,发送一个 RST_STEAM 请求;当服务端接受到这个流后,如果监听器还没有关闭,会执行取消上下文的操作,最终将这个请求取消
客户端
当客户端成功接收到响应会,会在 io.grpc.internal.RetriableStream.Sublistener#close 中将成功的流进行提交
- io.grpc.internal.RetriableStream#commit$CommitTask#run
在提交时,会通过提交 CommitTask 将其他的流取消
class CommitTask implements Runnable {
@Override
public void run() {
// 遍历保存的枯竭的流,如果不是最后提交的流,则都取消
for (Substream substream : savedDrainedSubstreams) {
if (substream != winningSubstream) {
substream.stream.cancel(CANCELLED_BECAUSE_COMMITTED);
}
}
// 如果有重试中的,则取消
if (retryFuture != null) {
retryFuture.cancel(false);
}
// 如果有对冲中的,则取消
if (hedgingFuture != null) {
hedgingFuture.cancel(false);
}
// 将当前流从未提交的流中移除
postCommit();
}
}
- io.grpc.internal.AbstractClientStream#cancel
使用指定的原因取消流
public final void cancel(Status reason) {
Preconditions.checkArgument(!reason.isOk(), "Should not cancel with OK status");
cancelled = true;
abstractClientStreamSink().cancel(reason);
}
- io.grpc.netty.shaded.io.grpc.netty.NettyClientStream.Sink#cancel
提交取消流的指令
public void cancel(Status status) {
PerfMark.startTask("NettyClientStream$Sink.cancel");
try {
NettyClientStream.this.writeQueue.enqueue(new CancelClientStreamCommand(NettyClientStream.this.transportState(), status), true);
} finally {
PerfMark.stopTask("NettyClientStream$Sink.cancel");
}
}
- io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler#write
在执行写入消息时,写入取消指令
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (msg instanceof CreateStreamCommand) {
this.createStream((CreateStreamCommand)msg, promise);
} else if (msg instanceof SendGrpcFrameCommand) {
this.sendGrpcFrame(ctx, (SendGrpcFrameCommand)msg, promise);
} else if (msg instanceof CancelClientStreamCommand) {