Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Akka流TCP+;Akka Stream Kafka制作人未停止未发布消息且未出错退出_Scala_Akka_Akka Stream_Akka Kafka - Fatal编程技术网

Scala Akka流TCP+;Akka Stream Kafka制作人未停止未发布消息且未出错退出

Scala Akka流TCP+;Akka Stream Kafka制作人未停止未发布消息且未出错退出,scala,akka,akka-stream,akka-kafka,Scala,Akka,Akka Stream,Akka Kafka,我有以下信息流: Source(IndexedSeq(ByteString.empty)) .via( Tcp().outgoingConnection(bsAddress, bsPort) .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true)) .map(_.utf8String) ) .map(m => new ProducerRecord[Array[Byte], String]

我有以下信息流:

Source(IndexedSeq(ByteString.empty))
.via(
  Tcp().outgoingConnection(bsAddress, bsPort)
    .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
    .map(_.utf8String)
)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
  Producer.plainSink(
    ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
      .withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
  )
).onComplete {
    case Success(Done) => printAndByeBye("Stream ends successfully")
    case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
  }
它可以正常工作一段时间,我可以使用卡夫卡主题中填充的消息。但是,很明显,每隔一段时间,就不会有更多的消息发布,并且该代码不会记录任何错误(printAndByeBye将打印传递的消息并终止actor系统)。重新启动应用程序后,消息继续流动

你知道怎么知道这里发生了什么吗

编辑:我将Kamon放在上面,可以看到以下行为:


看起来好像有什么东西在没有通知流应该停止的情况下停止了,但我不知道如何使其显式并停止流。

我建议创建具有监视属性的流,以处理TCP连接中可能出现的异常,如下所示:

val flow = 
    Tcp().outgoingConnection("", 12)
          .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
          .map(_.utf8String).withAttributes(ActorAttributes.supervisionStrategy {
      case ex: Throwable =>
        println("Error ocurred: " + ex)
        Supervision.Resume
     }


如果流有任何错误,则流停止。使用此配置,您将看到流是否引发了任何异常。

我建议创建具有监督属性的流,以处理TCP连接中可能出现的异常,如下所示:

val flow = 
    Tcp().outgoingConnection("", 12)
          .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
          .map(_.utf8String).withAttributes(ActorAttributes.supervisionStrategy {
      case ex: Throwable =>
        println("Error ocurred: " + ex)
        Supervision.Resume
     }


如果流有任何错误,则流停止。通过这种配置,您将看到流是否抛出了任何异常。

如果一切都停止,则可能是由于某个地方施加了背压。 尝试并有选择地用非背压感知阶段替换背压感知阶段,并检查问题是否仍然存在。 在您的情况下,有两种可能的背压源:

1) TCP连接

您可以尝试通过TestRing将无限源的
附加到卡夫卡,按照以下方式操作:

Source.cycle(() => List(???).iterator)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
  Producer.plainSink(
    ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
      .withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
  )
).onComplete {
    case Success(Done) => printAndByeBye("Stream ends successfully")
    case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
  }
2) 卡夫卡水槽

替换为一些日志记录

Source(IndexedSeq(ByteString.empty))
.via(
  Tcp().outgoingConnection(bsAddress, bsPort)
    .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
    .map(_.utf8String)
)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runForeach(println)
.onComplete {
    case Success(Done) => printAndByeBye("Stream ends successfully")
    case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
  }

你能在这两种情况中只看到一种吗?两者都有?无?

如果一切都停止,可能是因为某个地方施加了背压。 尝试并有选择地用非背压感知阶段替换背压感知阶段,并检查问题是否仍然存在。 在您的情况下,有两种可能的背压源:

1) TCP连接

您可以尝试通过TestRing将无限源的
附加到卡夫卡,按照以下方式操作:

Source.cycle(() => List(???).iterator)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runWith(
  Producer.plainSink(
    ProducerSettings(system, new ByteArraySerializer, new StringSerializer)
      .withBootstrapServers(s"${kafkaAddress}:${kafkaPort}")
  )
).onComplete {
    case Success(Done) => printAndByeBye("Stream ends successfully")
    case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
  }
2) 卡夫卡水槽

替换为一些日志记录

Source(IndexedSeq(ByteString.empty))
.via(
  Tcp().outgoingConnection(bsAddress, bsPort)
    .via(Framing.delimiter(ByteString("\n"), 256, allowTruncation = true))
    .map(_.utf8String)
)
.map(m => new ProducerRecord[Array[Byte], String](kafkaTopic, m))
.runForeach(println)
.onComplete {
    case Success(Done) => printAndByeBye("Stream ends successfully")
    case Failure(ex) => printAndByeBye("Stream ends with an error: " + ex.toString)
  }

你能在这两种情况中只看到一种吗?两者都有?在none?

中,流没有失败,但TCP流变为空闲,因为发布数据的设备在一段时间后停止发送数据,而没有断开连接。 而不是使用更简单的:

TCP().outgoingConnection(bsAddress, bsPort)
我最终使用:

def outgoingConnection(
remoteAddress:  InetSocketAddress,
localAddress:   Option[InetSocketAddress]           = None,
options:        immutable.Traversable[SocketOption] = Nil,
halfClose:      Boolean                             = true,
connectTimeout: Duration                            = Duration.Inf,
idleTimeout:    Duration                            = Duration.Inf): Flow[ByteString, ByteString, Future[OutgoingConnection]] = ???
所以

变成

val connectTimeout: Duration = 1 second
val idleTimeout: Duration = 2 second
Tcp().outgoingConnection(
    remoteAddress = InetSocketAddress.createUnresolved(bsAddress, bsPort),
    connectTimeout = connectTimeout,
    idleTimeout = idleTimeout
  )

通过通知idleTimeout,后续启动失败,可以重新启动另一个流。

流没有失败,但TCP流变为空闲,因为发布数据的设备在一段时间后停止发送数据,而不会断开连接。 而不是使用更简单的:

TCP().outgoingConnection(bsAddress, bsPort)
我最终使用:

def outgoingConnection(
remoteAddress:  InetSocketAddress,
localAddress:   Option[InetSocketAddress]           = None,
options:        immutable.Traversable[SocketOption] = Nil,
halfClose:      Boolean                             = true,
connectTimeout: Duration                            = Duration.Inf,
idleTimeout:    Duration                            = Duration.Inf): Flow[ByteString, ByteString, Future[OutgoingConnection]] = ???
所以

变成

val connectTimeout: Duration = 1 second
val idleTimeout: Duration = 2 second
Tcp().outgoingConnection(
    remoteAddress = InetSocketAddress.createUnresolved(bsAddress, bsPort),
    connectTimeout = connectTimeout,
    idleTimeout = idleTimeout
  )

通过通知idleTimeout,后续启动失败,另一个流可能会重新启动。

是否有方法监视这种情况?或者当背压停止流时超时?有一个阶段可以捕获使用Tcp流获取数据时发生的背压超时。是否有方法监视这种情况?或者当背压停止流时超时?有一个阶段可以捕获使用Tcp流获取数据时发生的背压超时。