Phantom vs Quill for Playframework(Scala)和Cassandra

时间:2016-06-21 00:35:10

标签: cassandra playframework-2.5 phantom-dsl

我目前正在使用Cassandra作为PlayFramework项目中的数据库。我正在寻找一个反应性的驱动程序,似乎我的选择仅限于Phantom和Quill。 我对nosql数据库的经验仅限于MongoDB,之前我没有使用任何Quill或Phantom。

查看comparison here,似乎最终可能会在Phantom中编写更多代码。此外,使用DSL来描述模型似乎是违反直觉的(来自繁重的休眠/ JPA背景) - 但这可能只是我。

我想知道是否有人可以提供实用的建议/用例,其中一个人会优于另一个人以及每个人需要注意的事项?

2 个答案:

答案 0 :(得分:8)

作为幻影作者的一个略微偏见的观点,我非常了解幻影中的设计目标。 Quill图书馆网站上现有的Quill和Phantom之间存在比较,自然偏向另一个方向。

Phantom旨在成为应用程序级别层的完美选择,其中Quill旨在成为最高级的字符串生成器,当您在Cassandra上构建大型应用程序时,这不是一个非常有用的比较。

使用幻像的优点

  • 关于类型安全以及DSL对Cassandra功能的改进程度,确实没有竞争对手。 DSL非常“亲密”。了解您的数据结构并为Cassandra功能提供全面支持。它在编译时知道对Cassandra有什么可能,以及什么不是。

  • Quill devs认为幻影有更多的依赖关系,但这并不完全准确,因为大多数都是可选的,包括播放迭代和流支持等。你不想要的就是那么简单。

  • Quill比较简单地指出:"您可以通过扩展DSL来扩展Phantom以添加新功能,尽管它可能不是一个简单的过程。",这有点不准确。作为游戏中的新玩家,Quill在Cassandra功能支持方面是一个玩具,你经常会发现自己需要添加功能。幻影毫无疑问有其缺口,但它是一个更为成熟的替代品,而且需要延期的次数非常少。

  • 我们已经针对更复杂的功能在几天或几周内解决了大多数错误,但通常您可能需要的一切都已经存在,目前Quill中找不到许多功能,甚至需要几个小时写下来。

  • 我不是来自强大的JPA背景,但Cassandra和幻像之间的映射是一个非常强大的层,因为它允许您直接从映射自动生成表的整个模式DSL。它还允许DSL在编译时完全模仿Cassandra的行为,它将知道哪些查询对于您选择的主键是可能的等等,quill根本没有这样的支持。

  • Phantom拥有非常强大的应用程序级抽象层,例如连接器,数据库,数据库的自动生成,以及帮助您将应用程序运行到生产中的东西。

  • Quill背后的代码要复杂得多,虽然我是第一个对其背后的工程能力给予强烈信任的人,但当我认为用户友好时,这个故事并没有得到很好的支持。

  • Quill尝试一次性做更多事情。它是一代产品的迷你引擎,在他们决定完全专注于SQL dbs并放弃对其他任何东西的支持之前,scalaquery试图在几年前做了一些事情。它是现代Slick的前身,并使用了类似的QDSL引用方法。

  • Quill是一个泄漏的抽象。由于他们的目标是支持更广泛的数据库,因此他们对数据库特性的特殊性的支持非常低劣。下面是一个例子:

从比较中的基本示例中可以看出:

val getAllByCountry = quote {
  (country: String) => query[WeatherStation]
     .filter(_.country == country)
  }
}

到目前为止,如果我们包含必要的映射代码,那么大概都比幻影等价物更简洁。

select.where(_.country eqs country).fetch()

但让我们进一步探索。如果你试图像这样取一个国家怎么办?或者如果您尝试获取PagingState信息该怎么办?或者输入现有的PagingState以在UI上显示内容。

至少在比较中,Quill无法向用户提供他们的体验最终结果的真实预览。很自然地假设,无论何时进入工具页面,它都会将自己描述为同类产品中的最佳工具,因为我们肯定会在幻影背后做到这一点,但这绝不是完整的故事。

更简洁,更酷的事情:

select.where(_.country eqs country).fetchRecord()
select.where(_.country eqs country).one()

部分选择怎么样?

select(_.country, _.city).where(_.country eqs country)

Phantom在语义上区分使用Cassandra在运行时可能发生的所有事情,它首先尝试使用编译时技巧和域知识来防止运行时错误。你怎么能拥有Quill等价物呢?

此外,Quill完全能够直接从case class生成查询。

  case class WeatherStation(
    country: String,
    city: String,
    stationId: String,
    entry: Int,
    value: Int
  )

  object WeatherStation {

    val getAllByCountry = quote {
      (country: String) =>
        query[WeatherStation].filter(_.country == country)
    }

    val getAllByCountryAndCity = quote {
      (country: String, city: String) =>
        getAllByCountry(country).filter(_.city == city)
    }

    val getAllByCountryCityAndId = quote {
      (country: String, city: String, stationId: String) =>
        getAllByCountryAndCity(country, city).filter(_.stationId == stationId)
    }
  }

但是它缺乏关于你的架构的任何知识。如果国家不是小学的一部分怎么办?该查询无效,幻影不会让你编译它,这只是最基本的例子。

Phantom可以直接从表中自动生成您的CQL,它可以动态生成整个数据库,专业版甚至可以自动迁移表并帮助您处理模式不一致,并为您提供非常高级的UI和监控接口,您可以动态升级和降级模式。

<强>缺点

  • Phantom确实使得TypeCodec之类的内容略微冗长,但是从幻像2.9.0开始,我们引入了一个非常强大的宏机制来编码Cassandra中没有的类型完全依赖TypeCodec

  • Phantom需要最少的样板来定义表DSL,并且本质上并不能很好地与共享表列一起使用。它可以做到,但它不是最漂亮的代码,也不是最糟糕的代码。

<强>总体

  • Quill是一个非常好的软件,由非常有才华的人编写,对此有0个疑问。
  • 在查询生成中,它比幻像更好,可以通过QDSL减少无法通过EDSL减少的样板,如果我们正在为谁是最卑鄙的最糟糕的字符串生成器而战奎尔获胜。
    • 它在应用层面上是一个非常低劣的工具,对大多数人来说它更加不自然。 Slick在某种程度上推广了这些概念,但是您在应用程序生命周期中想要的一些最基本的功能并不像QDSL那样容易解决,或者至少它还没有发生。
    • Phantom更成熟,更广泛采用,拥有更多资源和创始团队的意见,长期的路线图以及与Datastax的重要合作伙伴关系,帮助我们掌握所有功能。

答案 1 :(得分:0)

我们从Quill开始,然后由于Phantom的功能和易于改变而去了Phantom。但是,我们遇到了严重的负载测试问题,发现它没有释放CPU线程和网络连接。我们在本地mac机器和AWS EC2-Cluster AMI Linux服务器上进行了测试。基本上资源没有被释放,并且随之而来的是内存不足的异常。如果这个问题得到解决,Phantom会很棒。目前我不建议将Phantom用于任何需要高性能生产系统的人。

在制作的最后一分钟,我们不得不改变所有代码并切换回Quill,这对我来说很痛苦。

我已经与Phantom打开了一个问题,希望他们可以尽快解决这个问题。附上一个项目,通过并行运行一个简单的JSON / REST scala项目来测试Quill和Phantom之间的负载。

https://github.com/yleun/cassandra-loadtest

如果Phantom可以解决这个内存不足的问题,它可能会成为Quill的优秀数据库客户端,但是现在它还没有生产就绪,我希望其他人在遇到问题后不要再遇到问题。花大量时间用幻影建造。