A服务通过grpc调用B服务去查询数据时,一开始写成(伪代码):
@Override
public void getBData(BRequest request StreamObserver<B> responseObserver) {
BReply.Builder builder = BReply.newBuilder();
try {
...
if (bData == null) {
return;
}
BeanUtils.copyProperties(bData, builder);
} catch (Exception e) {
log.error("异常", e);
}
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
}
可以看到,我这里如果没有查到数据,就直接return了,并没有执行下面的这段代码
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
导致调用方一致没有接收到结果,一直在等待,直到请求超时
正确写法:
@Override
public void getBData(BRequest request StreamObserver<B> responseObserver) {
BReply.Builder builder = BReply.newBuilder();
try {
...
if (bData == null) {
return;
}
BeanUtils.copyProperties(bData, builder);
} catch (Exception e) {
log.error("异常", e);
}finally{
responseObserver.onNext(builder.build());
responseObserver.onCompleted();
}
}
这个问题排查了很久,因为根本没有相关日志报错信息,而且由于调用方还用了事务,加了分布式锁,导致锁无法释放,最终导致死锁,系统宕机
本文记录了一次由于在GRPC服务中错误处理导致的调用问题。原本的代码在BData为空时直接返回,未通知调用方,造成调用方长时间等待并引发事务死锁。正确的做法是在finally块中确保使用responseObserver发送结果和完成信号,避免类似问题。排查过程中缺乏相关日志信息增加了诊断难度。
806

被折叠的 条评论
为什么被折叠?



