我正在尝试从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万条记录。因此迭代它需要花费大量时间。
有更好的方法吗?
答案 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)中,并且超时等等