如何修复Spray中SSL连接已关闭但仍出现“Dropping Close”错误

34
我正在调用一个API,但大部分时间都会出现错误:“Dropping Close since the SSL connection is already closing”和“Premature connection close (the server doesn't appear to support request pipelining)。” 我90%的时间都会遇到这个错误,意味着:很少情况下查询会返回它应该返回的数据。

为了确保这不是API服务器的问题,我使用Node.js(Express和Request libs)复制相同的查询,每次都能成功。这让我几乎确定是spray bug。

以下是代码示例::

case class MyClass(user: String, pass: String)

class MyActor extends Actor {
  import spray.client.pipelining._
  import spray.http.BasicHttpCredentials
  import spray.http.{HttpRequest,HttpResponse}
  import scala.concurrent.Future

  import context.dispatcher

  def receive = {
    case myClass: MyClass => {
      val credentials: BasicHttpCredentials = BasicHttpCredentials(myClass.user, myClass.pass)
      val url: String = "https://myApi?params=values"
      val request: HttpRequest = Get(url) ~> addCredentials(credentials)
      val pipeline = sendReceive
      val response: Future[HttpResponse] = pipeline(request)
      val finalRes: Future[String] = response.map{ r =>
        println(r)
        r.entity.asString
      }
      finalRes pipeTo sender
    }
  } // end receive
} //end Actor

错误详情:

04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-8] a.i.TcpOutgoingConnection - Attempting connection to ...
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-6] a.i.TcpOutgoingConnection - Connection established to ...
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-6] s.c.c.HttpClientConnection - Connected to ...
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-9] s.c.c.HttpHostConnectionSlot - Connection to ... established, dispatching 1 pending requests
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpClientConnection - now monitoring Actor[akka://on-spray-can/system/IO-TCP/selectors/$a/5]
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-6] s.c.c.HttpHostConnectionSlot - Dispatching GET request to /api?params=values across connection Actor[akka://on-spray-can/user/IO-HTTP/group-0/4]
04/01 10:19:05 DEBUG[on-spray-can-akka.actor.default-dispatcher-6] s.c.c.HttpHostConnectionSlot - now monitoring Actor[akka://on-spray-can/user/IO-HTTP/group-0/4]
04/01 10:19:06 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpClientConnection - Dropping Close since the SSL connection is already closing
04/01 10:19:06 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpClientConnection - Connection was PeerClosed, awaiting TcpConnection termination...
04/01 10:19:06 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] a.i.TcpOutgoingConnection - stopped
04/01 10:19:06 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpClientConnection - TcpConnection terminated, stopping
04/01 10:19:06 WARN [on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpHostConnectionSlot - Premature connection close (the server doesn't appear to support request pipelining) in response to GET request to /myApi?params=values with 1 retries left, retrying...
04/01 10:19:06 DEBUG[on-spray-can-akka.actor.default-dispatcher-3] s.c.c.HttpClientConnection - stopped

我能在所有这些版本中重现错误:

spray 1.0.1; akka 2.0.5; scala 2.9.3
spray 1.2.1; akka 2.2.4; scala 2.10.1
spray 1.3.1; akka 2.3.0; scala 2.10.3
spray 1.3.2; akka 2.3.6; scala 2.11.4
spray 1.3.3; akka 2.3.9; scala 2.11.6

我看到了类似的行为。在我的情况下,Spray Can 正试图向我的应用程序 actor 发送一条消息,但 PeerClosed 消息似乎比它更优先,导致该消息被丢弃。 - Sarge
我也在spray.io的谷歌讨论组中发布了这个问题:https://groups.google.com/forum/#!topic/spray-user/w0oeFC7eJ_s - maya.js
1
我认为这与您使用的JVM或对面的SSL有关。您是否尝试过使用一些API客户端并发出请求?至少写下您使用的JVM版本。 - bkowalikpl
你尝试连接的服务器是基于akka-http或spray的吗?如果是,请检查akka-http配置。 - Shankar Shastri
1个回答

1

如你所说,

为了确保这不是API服务器问题,我使用Node.js(Express和Request库)复制了相同的查询,并且每次都能正常工作。这让我几乎确定是Spray的错误。

您在Scala中的代码使用HTTP管线功能发送请求,在使用nodejs进行测试时是否也使用HTTP管线功能发送请求?

对于错误消息:

服务器似乎不支持请求管线

您应该确保:

  1. 请确保服务器支持管线功能,并启用管线功能。
  2. 如果在客户端和服务器之间存在代理(包括反向代理),请确保代理支持管线功能,并启用管线功能。

如果无法确保管线功能可以正常支持,则不应使用它。

以下资源可能有帮助:

HTTP流水线技术需要客户端和服务器都支持。符合HTTP/1.1标准的服务器必须支持流水线技术。这并不意味着服务器必须使用流水线技术响应请求,但是如果客户端选择使用流水线技术发送请求,服务器不得失败。[7]

https://en.wikipedia.org/wiki/HTTP_pipelining

HTTP管线化在现代浏览器中默认未激活:
存在常见的错误代理,这导致Web开发人员无法轻松预见和诊断奇怪和不稳定的行为。正确实现管线化是复杂的:正在传输的资源大小、将要使用的有效RTT以及有效带宽直接影响管线提供的改进。不知道这些信息,重要的消息可能会被延迟到不重要的消息之后。甚至在页面布局期间,“重要”的概念也会发生变化!因此,在大多数情况下,HTTP管线化只带来了微小的改进。管线化受到HOL问题的影响。出于这些原因,管线化已被更好的算法——多路复用取代,该算法由HTTP/2使用。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Connection_management_in_HTTP_1.x$revision/1330814


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接