现象
- 日志发生以下异常
- INTERNAL: Connection closed after GOAWAY. HTTP/2 error code: INTERNAL_ERROR, debug data: Stream 5 sent too many headers EOS: false - INTERNAL: Invalid protobuf byte sequence While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length. iii. Protocol message contained an invalid tag (zero).
异常原因及解决方案:
原因
多线程同时向stream的observer句柄写数据,造成数据异常。
解决方案
observer加一个包装类,推送消息时使用包装类的推送方法,推送方法内加锁,使数据流能够顺序发送。类似于:
public static class ObserverWrapper {
@Getter
private final String account;
@Getter
private final StreamObserver<Response> observer;
private static final ReentrantLock LOCK = new ReentrantLock();
public ObserverWrapper (String account, StreamObserver<Response> observer) {
this.account = account;
this.observer = observer;
((ServerCallStreamObserver) observer).setOnCancelHandler(() -> {
LOG.error("通道关闭: {}", observer);
});
}
public void sendMsg(List<Msg> list) {
if (list== null || list.isEmpty()) {
LOG.warn("推送信息为空......");
return;
}
LOCK.lock();
try {
Response response = Response.newBuilder()
.addMsgs(list).build();
this.observer.onNext(response);
LOG.debug("向客户端: {} 信息成功: {}", account, list);
} catch (Exception e) {
LOG.error("发送消息异常", e);
} finally {
LOCK.unlock();
}
}
}