我们现在正在开发一个使用Netty的客户端 - 服务器系统。 我们有时会发现通信错误。 如果我们错误地使用Netty,你能给我一些建议。
我们在以下sendResponse中按此顺序调用writeHeadersFrame和writeDataFrame。
但我们有时会发现Headers框架和数据框之间的意外切换。
private def sendResponse(
streamId: Int,
name: String,
status: ResponseStatus,
options: Map[String, String],
data: Option[PackableData],
isLast: Boolean): Unit =
requestTable.get(streamId) match {
case None =>
log.error(s"sendResponse: streamId not found: $streamId")
case Some(requestInfo) if requestInfo.ctx.channel.isActive =>
writeResponseAccessLog(requestInfo.connectionTime, requestInfo.path, requestInfo.remoteAddress, status)
writeHeadersFrame(requestInfo, streamId, status, isHeadersFrameEndStream(data, isLast))
writeDataFrame(requestInfo, streamId, data, isLast)
flush(requestInfo)
removeStreamIdIfLast(streamId, isLast)
case _ => detectedDisconnectionAndStop
}
private def writeHeadersFrame(requestInfo: RequestInfo, streamId: Int, status: ResponseStatus, isLast: Boolean): Unit = {
log.debug(s"writeHeadersFrame($streamId, $status, $isLast)")
val headers = new DefaultHttp2Headers().status(status.code.toString)
headers.set(new AsciiString("content-type"), new AsciiString("application/x-msgpack"))
val promise = requestInfo.ctx.newPromise()
promise.addListener(new NettyChannelFutureListener(self))
encoder.writeHeaders(requestInfo.ctx, streamId, headers, 0, isLast, promise)
}
private def writeBytesArray(ctx: ChannelHandlerContext, streamId: Int, bytes: Array[Byte], isLast: Boolean): Unit = {
val byteBuffer = Unpooled.copiedBuffer(bytes)
val promise: ChannelPromise = ctx.newPromise()
promise.addListener(new NettyChannelFutureListener(self))
log.debug(s"writeDataFrame: DATA Frame ${bytes.length} bytes, Readable bytes=${byteBuffer.readableBytes()}")
encoder.writeData(ctx, streamId, byteBuffer, 0, isLast, promise)
}
private def writeDataFrame(requestInfo: RequestInfo, streamId: Int, data: Option[PackableData], isLast: Boolean): Unit = {
log.debug(s"writeDataFrame: $streamId, $data, $isLast)")
data match {
case None =>
log.info("writeDataFrame: No Data")
case Some(packable) =>
MessagePackUtil.serialize(packable) match {
case Failure(e) =>
log.error(s"writeDataFrame: serialize error: ${e.getMessage}")
case Success(bytes: Array[Byte]) =>
writeBytesArray(requestInfo.ctx, streamId, bytes, isLast)
}
}
}