Scala 休息(Squiryl/Akka/Spray)-吞吐量非常低

Scala 休息(Squiryl/Akka/Spray)-吞吐量非常低,scala,spray,squeryl,Scala,Spray,Squeryl,我目前正在基于RSS聚合器构建我的第一个RESTAPI。我使用两个特性中的一个实现了它,要么是MemoryBasedDB,要么是PostgresDB。在每次访问根url时,它都会对提要进行异步调用以获取最新文章,并将其作为XML字符串返回以进行解析。解析后,它将作为项目对象持久保存在数据库中 从功能上来说,这两种方式对我都很好。但是,当使用weighttp或gatling进行负载测试时,在1k请求/1k并发用户使用Postgres时,它将失败,原因如下: 在WERGETP中: error: re

我目前正在基于RSS聚合器构建我的第一个RESTAPI。我使用两个特性中的一个实现了它,要么是MemoryBasedDB,要么是PostgresDB。在每次访问根url时,它都会对提要进行异步调用以获取最新文章,并将其作为XML字符串返回以进行解析。解析后,它将作为项目对象持久保存在数据库中

从功能上来说,这两种方式对我都很好。但是,当使用weighttp或gatling进行负载测试时,在1k请求/1k并发用户使用Postgres时,它将失败,原因如下:

在WERGETP中:

error: read() failed: Connection reset by peer (104)
在我的服务器日志中:

final [WARN] [09/21/2014 14:45:27.224] [on-spray-can-akka.actor.default-dispatcher-36] [akka://on-spray-can/user/IO-HTTP/listener-0/523] Configured registration timeout of 1 second expired, stopping
我相信这与我提出问题的方式有关。它们正在阻塞,由于每个参与者都必须等待响应,因此它们后面的负载会越来越高,直至出现故障(超时)。然而,在我的研究中,我只能找到postgres的异步驱动程序,目前它与Squeryl不兼容(据我所知)

如何使数据库访问更快?目前,我使用Postgres实现~10-15req/s,使用内存持久化实现~400req/s

我的模型:

case class Article(id: Option[String], idint: Option[Int], title: String, author: String, published: String, updated: String, `abstract`: Option[String], content: Option[String], link: Option[String])
我的问题是:

trait PostgresDB extends Schema {

  val articles = table[Article]("articles")
  on(articles)(e => declare(e.idint is(unique)))

  def create(x: Article) = inTransaction {
      articles.insert(x)
  }

  def getAll: Set[Article] = inTransaction {
      from(articles)(article => select(article)).toSet
  }

  def getArticle(x: Int) = inTransaction {
      from(articles)(article => where(article.idint === Some(x)) select(article)).toList(0)
  }

  def printy = transaction {
      articles.schema.printDdl(println(_))
  }
}
到目前为止,我已经尝试:

  • 为连接池实现C3P0。没有真正的变化
  • 调整postgresql.conf以提高性能。微小的积极变化
  • 为spray/akka调整application.conf以提高性能。微小的积极变化
相关信息:

  • 内核:
    • Linux 3.13.0-33-generic#58 Ubuntu SMP周二7月29日16:45:05 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
  • 博士后9.3
  • Scala 2.10.4
  • 第1.3.1节
  • Akka 2.3.5

希望每个REST参与者没有阻塞自己的db请求。。。它们委托给具有持久连接的单独db参与者池

是的,我同意@experquiste,给db参与者自己的分派器,并将其线程池大小和参与者数量调整为db可以处理的并发请求数量。把路由器放在这个前面。您应该测量数据库服务器磁盘队列长度。这在持续的高负载下应该是稳定的,继续添加线程,直到队列开始增长

另一种方法是为db访问层使用线程池和未来。它似乎更易于配置,但缺少监督和错误恢复。 就我个人而言,我仍然使用演员来实现并发性


我从未使用过squeryl,inTransaction块是否创建db事务?您显示的数据库特性似乎不需要事务,您是否尝试过不使用事务

我不是这些问题的专家,但将性能测试分为不同的领域似乎不合理吗?例如,关于喷雾的性能和斯奎尔的性能

旁注。“~10-15req/s”的值非常非常低。不应该是那样的

另一张纸条。就我所记得的,C3P0应该会带来真正的不同。您确定设置正确吗


我还建议小心使用异步代码和线程池,如果它们不是必需的,就避免使用它们。它们使代码更加复杂,为bug开辟了一个全新的领域。(异步在某些用例中仍然很酷,但我希望我已经明确了我的观点。)

是的,如果当前没有事务执行,它将创建一个新事务。我以前看过那篇文章,但当时我还不能很好地解释未来。我现在在同一个程序中的其他地方使用它们,所以我将在这里尝试一下。使用Futures来管理这些调用非常有帮助--我现在使用基于磁盘的DB平均约300req/s。谢谢你的帮助!伟大的纯内存impl的3/4的数据库吞吐量非常好。不,数据库目前没有专用的参与者池。啊,记住了一些数字。据我记忆所及,一个简单的设置(使用C3P0)大约需要2-4ms来完成一个简单的请求,而在嵌入式模式下需要h2。大约6-10毫秒,h2没有嵌入。响应时间对总负载的影响不大,直到负载达到可能的最大值,而响应时间实际上确实造成了一些麻烦,开始变得非常大。无论如何,我并没有深入研究这个问题——只是做了一些基本的测试作为实验。