在我们的系统中,我们通常有两个组件:clouderahadoop集群(cdh)和openshift“后端”系统。在hdfs中,我们有一些巨大的.parquet文件。
我们现在有一个业务需求,即“按用户给定的筛选条件导出数据”以“实时”方式作为可下载文件发送给用户。因此流程是:例如,用户输入一个类似sql的过滤器字符串 user='Theo' and command='execution'
. 然后他发了一个get /export
以筛选器字符串作为参数请求我们的后端服务。用户现在应该从他的网络浏览器中获得一个“下载文件”,并立即开始以csv的形式下载该文件(即使其大小为多个terrabytes甚至petabytes,如果用户想尝试并等待那么长时间,这是用户的选择)。事实上,集群应该同步响应,而不是在发送结果之前将整个响应缓存在单个节点上,而只是以用户的“网速”接收数据并直接流式传输给用户(缓冲区为10或100 mb)。
我现在面临的问题是如何最好地满足这一要求。我的考虑:
我想用spark来做这个。spark将读取parquet文件,轻松地应用过滤器,然后将过滤结果“合并”到驱动程序,驱动程序将数据流回到请求的后端/客户端。在此任务期间,如果将数据发送回后端/用户的速度太慢,驱动程序当然不应该耗尽内存,而应该让执行者以与“消耗”数据相同的速度交付数据。
然而,我在这里面临一些问题:
标准用例是用户有细粒度过滤器,这样他导出的文件只包含1000行。如果我能通过 spark-submit
对于每个请求,由于初始化和查询计划的创建,我已经进入了几秒钟的延迟(即使它和读取和过滤数据一样简单)。我想避免这样。
集群和后端是严格隔离的。理想情况下,操作人员根本不希望我们从后端访问集群,但是集群应该只调用后端。我们可以“打开”一个端口,但我们可能无法讨论“我们的后端将运行spark驱动程序,但作为执行后端连接到集群”之类的问题。
如果我们运行一个“服务器spark作业”,也就是说,我们向集群主服务器提交一个模式为“client”的应用程序,集群主服务器也会为http请求打开一个端口,并且只对请求运行spark管道,但是spark上下文一直保持打开状态(并且可以通过固定的url从后端访问)?我知道有“spark job server”项目可以做到这一点,但由于spark和jobs的性质,它仍然感觉有点奇怪,“自然”一个作业是下载一个文件,而不是一个24小时运行的服务器不时地等待执行一些管道步骤。
我不知道如何限制sparks结果获取,以便执行器以一定的速度发送,这样,如果用户请求PB,驱动程序就不会耗尽内存。。有什么建议吗?
spark到底是这个任务的一个好选择还是你对更好的工具有什么建议(在cdh 5.14环境中最好是这样,因为我们没有让操作团队安装任何附加工具)。
暂无答案!
目前还没有任何答案,快来回答吧!