在Scala中使用curl时的性能问题

时间:2018-04-11 12:26:29

标签: scala apache-spark curl hive

我正在尝试从Hive中获取一个列,并根据该列的值,我需要执行curl命令。

这就是我生成列列表的方式

val list = hiveContext.sql("select application_number from t").collect()

for(l1 <- list) {
    val z = a.toString().replace("[", "").replace("]", "")
    val cmd = Seq("curl", "-X", "POST", "--insecure", "--header",
                  "Content-Type: application/json", "--header", 
                  "Accept: application/json", "-d", 
                  "{\"searchText\":\"+'z'+\",\"qf\":\"applId\"}", "https://link")
    val r = cmd.!!
}

现在,我已经以完美的方式将数据存储在r变量中。

但我的名单有1000万条记录。因此迭代它需要花费大量时间。

有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

您可以让Spark使用.map或UDF迭代每条记录,并从工作节点执行curl请求。 好处是你永远不必收集主服务器上的所有记录,然后运行10M卷曲请求。 Ť 他的缺点是所有curl请求都是异步的,因此无法保证顺序,如果你的集群足够大,你实际上可以降低curl请求的接收端。 另一个缺点是,这会带来重大的副作用。 如果Spark Job失败,那么已经发布了5M的请求。

除了使用从系统触发的curl请求之外,我还将使用本机JVM HTTP import scalaj.http.Http

像这样的东西

import org.apache.spark.sql.SparkSession
import scala.util.Try
import scalaj.http.Http


val spark = SparkSession.builder()
  .master("local[2]")
  .appName("test")
  .getOrCreate()

import spark.implicits._

// val list = (0 to 100).toDF("application_number").as[Int]
val list = hiveContext.sql("select application_number from t").as[Int]

val r = list.map(application_number => {
  Try(Http("https://link").postData(s"""{"searchText": "$application_number","qf":"applId"}""")
    .header("Content-Type", "application/json")
    .asString.body).toOption
}).collect()

println(r.toList)

scalaj-http是阻塞的,但线程安全,因此为了获得更高的性能(和风险),您可以将其包含在执行框架(Futures)中,并且超时等等