【发布时间】:2014-09-21 19:56:55
【问题描述】:
我目前正在构建我的第一个 REST API,它基于一个 RSS 聚合器。我使用 MemoryBasedDB 或 PostgresDB 这两个特征之一来实现它。在每次访问根 url 时,它都会对提要进行异步调用以获取最新文章,并将其作为 XML 字符串返回以进行解析。解析后作为 Article 对象保存在数据库中。
从功能上讲,这对我来说都很好。但是,当使用 weighttp 或 gatling 进行负载测试时,它将在 1k 请求/1k 并发用户下使用 Postgres 失败:
在 weighttp 中:
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
我认为这与我的查询布局方式有关。它们处于阻塞状态,并且由于每个参与者都必须等待响应,它们背后的负载越来越高,直至故障点(超时)。但是,在我的研究中,我只能找到 this 用于 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 以提高性能。小的积极变化。
- 调整 application.conf 以用于 spray/akka 以提高性能。小的积极变化。
相关信息:
- 内核:
- Linux 3.13.0-33-generic #58-Ubuntu SMP 2014 年 7 月 29 日星期二 16:45:05 UTC x86_64 x86_64 x86_64 GNU/Linux
- Postgres 9.3
- Scala 2.10.4
- 喷雾 1.3.1
- Akka 2.3.5
【问题讨论】: