如何使用 AKKA-HTTP、spray-json、oauth2 和 slick 优化 scala REST api?

Posted

技术标签:

【中文标题】如何使用 AKKA-HTTP、spray-json、oauth2 和 slick 优化 scala REST api?【英文标题】:How to optimize scala REST api using AKKA-HTTP, spray-json, oauth2 and slick? 【发布时间】:2017-01-31 11:11:31 【问题描述】:

我使用AKKA-HTTPspray-jsonSlick 在scala 中创建了一个REST api。对于路由授权,我使用了oauth2

DAO 检索数据(使用普通 SQL):

def getAllNotes: Future[Seq[UserEntity]] = 
    implicit val getUserResult = GetResult(r => UserEntity(r.<<, r.<<, r.<<, r.<<, r.<<, r.<<))
    query(s"select id, email, password,created_at, updated_at, deleted_at from users", getUserResult)

DAO 检索数据(Slick Table):

def getAll(): Future[Seq[A]] = 
    db.run(tableQ.result)

下面是路由部分:

val route: Route = pathPrefix("auth") 
    get 
        path("tests") 
            complete(userDao.getAll.map(u => u.toList))
         ~
        path("test") 
            complete(userDao.getAllNotes.map(u => u.toList))
         ~
        path("testUsers") 
            baseApi(userDao.getAllNotes)
         ~
        path("users") 
            baseApi(userDao.getAll())
        
    


implicit def baseApi(f: ToResponseMarshallable): Route = 
    authenticateOAuth2Async[AuthInfo[OauthAccount]]("realm", oauth2Authenticator)  auth =>
        pathEndOrSingleSlash 
            complete(f)
        
    

从功能上讲,所有路由都按预期工作,但是当使用 OAUTH2 和 Slick Tables 获取数据时,性能似乎有所下降。

以上路线的各自结果:

1. "users"     => 10 request per second: OAUTH2: YES, Slick Table: YES
2. "testUsers" => 17 request per second: OAUTH2: YES, Slick Table: NO
3. "tests"     => 500 request per second: OAUTH2: NO, Slick Table: YES
4. "test"      => 5593 request per second: OAUTH2: NO, Slick Table: NO

我的问题

如何使用 OAUTH2 和 Slick Table 优化 REST 请求?

如果我在所有情况下都使用 PLAIN SQL 而不是 Slick 表和联接,这会是一种好习惯吗?

【问题讨论】:

【参考方案1】:

似乎启用 Oauth2 的影响最大,但是与在 oauth2Authenticator 上完成的网络/服务调用相比,akka http 增加的开销可以忽略不计。即使以异步方式完成,您仍然需要正确配置执行上下文(好读 Explaining AKKA Thread Pool Execturor Config parameters)。

关于 Slick 部分,您似乎在每个请求上声明了隐式行映射器(可以是类 val 属性)。 查看Compiled Queries 并确保在您的db 连接池配置中分配了足够的jdbc 连接。

无论如何,这个测试的整个概念似乎都不是很有用,应该有最低要求(例如:最少 100 个请求/秒),然后在此基础上开始构建。

【讨论】:

每个请求上的隐式行映射器,你的意思是userDao.getAll.map(u =&gt; u.toList)。任何示例或代码 sn-p 都足以进行分析。 :) 我在getAllNotes 方法中引用了implicit val getUserResult,可以改为在类级别声明。 我替换了隐式,我收到的成就是5926 rps。我如何在getNotes() 中使用编译?我试过 db.run(Compiled(tableQ)) 但这会产生错误 getAllNotes 中,您使用了一个带有字符串和行映射器的query 函数,我假设您在其中使用db.run(sql(plainQuery)) 之类的东西,因为您的查询没有参数,您可以还在类级别将其声明为 val notesQuery=Compile(sql"select .. from users")) 然后在 getAllNotes 中使用 db.run(notesQuery)... 你对Scala中的OAuth2有什么其他的实现思路【参考方案2】:

关于Slick 的部分已被多次回答。最新答案在这里:Cache Slick DBIO Actions

这应该会显着缩短普通 Slick 版本的响应时间。

虽然OAUTH2 无法帮助您:/

【讨论】:

以上是关于如何使用 AKKA-HTTP、spray-json、oauth2 和 slick 优化 scala REST api?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spray-json 解析简单数组

使用 akka-http 模板的新 sbt 应用程序,如何确定解析器并添加 maven Central?

当 json 元素不存在时,如何设置 spray-json 以设置 null?

Spray-json反序列化嵌套对象

使用 Akka-Http 进行身份验证

scala spray-json 如何解析一个复杂的 数组JSON