[英]JAVA GRPC Bi-directional Stream throws CANCELLED: io.grpc.Context was cancelled without error
I am trying to implement a bi-directional streaming service for all nodes in a cluster.我正在尝试为集群中的所有节点实现双向流服务。 Using this, these nodes are supposed to sync their states ie whenever any server would get any update using serveRequest
request from any client, it would pass that information to other nodes in the cluster using streaming service syncState
.使用这个,这些节点应该同步它们的状态,即每当任何服务器使用来自任何客户端的serveRequest
请求获得任何更新时,它都会使用流服务syncState
状态将该信息传递给集群中的其他节点。
For this, every node in the cluster has clients set up to connect to every other node.为此,集群中的每个节点都设置了客户端以连接到每个其他节点。 Clients initialization is one-time and a stream is set up (1 client has 1 stream per node) using which it is supposed to sync the latest state to other nodes.客户端初始化是一次性的,并且设置了 stream(1 个客户端每个节点有 1 个 stream),它应该使用它来将最新的 state 同步到其他节点。
Sample Proto样品原型
message MessageRequest {
string policyId = 1;
string txnId = 2;
string clientId = 3;
}
message Acknowledgement {
string serverId = 1;
string txnId = 2;
}
service SyncState{
rpc sync(stream MessageRequest) returns (stream Acknowledgement) {}
}
service ServeRequest{
rpc newRequest(MessageRequest) returns (Acknowledgement) {}
}
SyncService同步服务
public class SyncStateService extends SyncStateServiceGrpc.SyncStateServiceImplBase {
private static final Logger logger = LoggerFactory.getLogger(SyncStateService.class);
private SyncManager manager;
private Configuration config;
public SyncStateService(SyncManager manager, Configuration config) {
this.manager = manager;
this.config = config;
}
@Override
public StreamObserver<MessageRequest> sync(StreamObserver<Acknowledgement> responseObserver) {
logger.info("Server received connection request");
return new StreamObserver<MessageRequest>() {
@Override
public void onNext(MessageRequest request) {
Acknowledgement ack = Acknowledgement.newBuilder().setTxnId(request.getTxnId()).setServerId(config.getClientId()).build();
MessageRequest clone = MessageRequest.newBuilder().setClientId(config.getClientId()).setTxnId(request.getTxnId()).build();
CompletableFuture.runAsync(() -> manager.sendMessage(clone));
responseObserver.onNext(ack);
}
@Override
public void onError(Throwable t) {
logger.error("Error on server for client stream", t);
}
@Override
public void onCompleted() {
logger.info("client called on completed on stream, server closes response stream");
responseObserver.onCompleted();
}
};
}
}
Client Stream Manager客户 Stream 经理
public class SyncManager {
private Map<String, SyncClient> client = new HashMap<>();
private final Configuration config;
public SyncManager(Configuration config) {
this.config = config;
}
public void startStateSync(MessageRequest clone) {
//This method is called whenever
//ServeRequest APi is hit on any server
config.getNodes().forEach(e->{
SyncClient syncClient = client.get(e);
if (syncClient== null){
syncClient = new SyncClient(e);
}
MessageRequest gossipRequest = MessageRequest.newBuilder().setTxnId(clone.getTxnId())
.setPolicyId(clone.getPolicyId()).setClientId(config.getClientId()).build();
syncClient.syncMessage(e, gossipRequest);
});
}
public void sendMessage(MessageRequest clone) {
// Server which has received state sync request
//forwards the same info to other servers
config.getNodes().forEach(e->{
SyncClient syncClient = client.get(e);
if (syncClient== null){
syncClient = new SyncClient(e);
}
MessageRequest gossipRequest = MessageRequest.newBuilder().setTxnId(clone.getTxnId())
.setPolicyId(clone.getPolicyId()).setClientId(config.getClientId()).build();
syncClient.syncMessage(e, gossipRequest);
});
}
}
Client:客户:
public class SyncClient {
private static final Logger logger = LoggerFactory.getLogger(SyncClient.class);
private final ManagedChannel channel;
private final SyncStateServiceGrpc.SyncStateServiceStub stub;
private final StreamObserver<MessageRequest> stream;
public SyncClient(String node) {
channel = ManagedChannelBuilder.forTarget(node)
.usePlaintext()
.keepAliveTime(new Long(2), TimeUnit.DAYS)
.keepAliveTimeout(new Long(1), TimeUnit.DAYS)
.keepAliveWithoutCalls(true)
.build();
stub = SyncStateServiceGrpc.newStub(channel);
stream = getStreamObserver();
}
private StreamObserver<MessageRequest> getStreamObserver() {
final StreamObserver<MessageRequest> stream;
stream = stub.sync(new StreamObserver<>() {
@Override
public void onNext(Acknowledgement value) {
String txnId = value.getTxnId();
logger.info("Received message from server");
String serverId = value.getServerId();
}
@Override
public void onError(Throwable t) {
logger.error("Error occurred", t);
}
@Override
public void onCompleted() {
logger.info("Completed");
}
});
return stream;
}
public void syncMessage(String node, MessageRequest request) {
logger.info("Sending message to:: {}", node);
stream.onNext(request);
}
}
Issues:问题:
io.grpc.StatusRuntimeException: CANCELLED: io.grpc.Context was cancelled without error at io.grpc.Status.asRuntimeException(Status.java:535) ~[grpc-api-1.36.0.jar:1.36.0] at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478) ~[grpc-stub-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:464) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:428) ~[grpc-core-1.36.0.jar:1.36.0] at ZF98ED07A4D5F50F7D io.grpc.StatusRuntimeException: CANCELLED: io.grpc.Context was cancelled without error at io.grpc.Status.asRuntimeException(Status.java:535) ~[grpc-api-1.36.0.jar:1.36.0] at io .grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478) ~[grpc-stub-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java :464) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:428) ~[grpc-core-1.36.0.jar: 1.36.0] 在 ZF98ED07A4D5F50F7D E1410D905F1477FZ.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:461) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:553) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:68) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:739) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:718) ~[grpc E1410D905F1477FZ.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:461) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:553 ) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:68) ~[grpc-core-1.36.0.jar:1.36.0 ] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:739) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed .runInContext(ClientCallImpl.java:718) ~[grpc -core-1.36.0.jar:1.36.0] at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.36.0.jar:1.36.0] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na] -core-1.36.0.jar:1.36.0] at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc .internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.36.0.jar:1.36.0] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na] at java.base/java.lang.Thread.run(Thread. java:832) ~[na:na]
Is there something I am missing with bi-directional streaming with GRPC?使用 GRPC 进行双向流式传输有什么我缺少的吗?
I am trying to implement a bi-directional streaming service for all nodes in a cluster.我正在尝试为集群中的所有节点实现双向流服务。 Using this, these nodes are supposed to sync their states ie whenever any server would get any update using serveRequest
request from any client, it would pass that information to other nodes in the cluster using streaming service syncState
.使用这个,这些节点应该同步它们的状态,即每当任何服务器使用来自任何客户端的serveRequest
请求获得任何更新时,它都会使用流服务syncState
状态将该信息传递给集群中的其他节点。
For this, every node in the cluster has clients set up to connect to every other node.为此,集群中的每个节点都设置了客户端以连接到每个其他节点。 Clients initialization is one-time and a stream is set up (1 client has 1 stream per node) using which it is supposed to sync the latest state to other nodes.客户端初始化是一次性的,并且设置了 stream(1 个客户端每个节点有 1 个 stream),它应该使用它来将最新的 state 同步到其他节点。
Sample Proto样品原型
message MessageRequest {
string policyId = 1;
string txnId = 2;
string clientId = 3;
}
message Acknowledgement {
string serverId = 1;
string txnId = 2;
}
service SyncState{
rpc sync(stream MessageRequest) returns (stream Acknowledgement) {}
}
service ServeRequest{
rpc newRequest(MessageRequest) returns (Acknowledgement) {}
}
SyncService同步服务
public class SyncStateService extends SyncStateServiceGrpc.SyncStateServiceImplBase {
private static final Logger logger = LoggerFactory.getLogger(SyncStateService.class);
private SyncManager manager;
private Configuration config;
public SyncStateService(SyncManager manager, Configuration config) {
this.manager = manager;
this.config = config;
}
@Override
public StreamObserver<MessageRequest> sync(StreamObserver<Acknowledgement> responseObserver) {
logger.info("Server received connection request");
return new StreamObserver<MessageRequest>() {
@Override
public void onNext(MessageRequest request) {
Acknowledgement ack = Acknowledgement.newBuilder().setTxnId(request.getTxnId()).setServerId(config.getClientId()).build();
MessageRequest clone = MessageRequest.newBuilder().setClientId(config.getClientId()).setTxnId(request.getTxnId()).build();
CompletableFuture.runAsync(() -> manager.sendMessage(clone));
responseObserver.onNext(ack);
}
@Override
public void onError(Throwable t) {
logger.error("Error on server for client stream", t);
}
@Override
public void onCompleted() {
logger.info("client called on completed on stream, server closes response stream");
responseObserver.onCompleted();
}
};
}
}
Client Stream Manager客户 Stream 经理
public class SyncManager {
private Map<String, SyncClient> client = new HashMap<>();
private final Configuration config;
public SyncManager(Configuration config) {
this.config = config;
}
public void startStateSync(MessageRequest clone) {
//This method is called whenever
//ServeRequest APi is hit on any server
config.getNodes().forEach(e->{
SyncClient syncClient = client.get(e);
if (syncClient== null){
syncClient = new SyncClient(e);
}
MessageRequest gossipRequest = MessageRequest.newBuilder().setTxnId(clone.getTxnId())
.setPolicyId(clone.getPolicyId()).setClientId(config.getClientId()).build();
syncClient.syncMessage(e, gossipRequest);
});
}
public void sendMessage(MessageRequest clone) {
// Server which has received state sync request
//forwards the same info to other servers
config.getNodes().forEach(e->{
SyncClient syncClient = client.get(e);
if (syncClient== null){
syncClient = new SyncClient(e);
}
MessageRequest gossipRequest = MessageRequest.newBuilder().setTxnId(clone.getTxnId())
.setPolicyId(clone.getPolicyId()).setClientId(config.getClientId()).build();
syncClient.syncMessage(e, gossipRequest);
});
}
}
Client:客户:
public class SyncClient {
private static final Logger logger = LoggerFactory.getLogger(SyncClient.class);
private final ManagedChannel channel;
private final SyncStateServiceGrpc.SyncStateServiceStub stub;
private final StreamObserver<MessageRequest> stream;
public SyncClient(String node) {
channel = ManagedChannelBuilder.forTarget(node)
.usePlaintext()
.keepAliveTime(new Long(2), TimeUnit.DAYS)
.keepAliveTimeout(new Long(1), TimeUnit.DAYS)
.keepAliveWithoutCalls(true)
.build();
stub = SyncStateServiceGrpc.newStub(channel);
stream = getStreamObserver();
}
private StreamObserver<MessageRequest> getStreamObserver() {
final StreamObserver<MessageRequest> stream;
stream = stub.sync(new StreamObserver<>() {
@Override
public void onNext(Acknowledgement value) {
String txnId = value.getTxnId();
logger.info("Received message from server");
String serverId = value.getServerId();
}
@Override
public void onError(Throwable t) {
logger.error("Error occurred", t);
}
@Override
public void onCompleted() {
logger.info("Completed");
}
});
return stream;
}
public void syncMessage(String node, MessageRequest request) {
logger.info("Sending message to:: {}", node);
stream.onNext(request);
}
}
Issues:问题:
io.grpc.StatusRuntimeException: CANCELLED: io.grpc.Context was cancelled without error at io.grpc.Status.asRuntimeException(Status.java:535) ~[grpc-api-1.36.0.jar:1.36.0] at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478) ~[grpc-stub-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java:464) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:428) ~[grpc-core-1.36.0.jar:1.36.0] at ZF98ED07A4D5F50F7D io.grpc.StatusRuntimeException: CANCELLED: io.grpc.Context was cancelled without error at io.grpc.Status.asRuntimeException(Status.java:535) ~[grpc-api-1.36.0.jar:1.36.0] at io .grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478) ~[grpc-stub-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener$3.run(DelayedClientCall.java :464) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.DelayedClientCall$DelayedListener.delayOrExecute(DelayedClientCall.java:428) ~[grpc-core-1.36.0.jar: 1.36.0] 在 ZF98ED07A4D5F50F7D E1410D905F1477FZ.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:461) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:553) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:68) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:739) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:718) ~[grpc E1410D905F1477FZ.grpc.internal.DelayedClientCall$DelayedListener.onClose(DelayedClientCall.java:461) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:553 ) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:68) ~[grpc-core-1.36.0.jar:1.36.0 ] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:739) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed .runInContext(ClientCallImpl.java:718) ~[grpc -core-1.36.0.jar:1.36.0] at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.36.0.jar:1.36.0] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na] -core-1.36.0.jar:1.36.0] at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.36.0.jar:1.36.0] at io.grpc .internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.36.0.jar:1.36.0] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na] at java.base/java.lang.Thread.run(Thread. java:832) ~[na:na]
Is there something I am missing with bi-directional streaming with GRPC?使用 GRPC 进行双向流式传输有什么我缺少的吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.