从 json 文件流上传批量数据时,最后一批永远不会上传到 Solr

Posted

技术标签:

【中文标题】从 json 文件流上传批量数据时,最后一批永远不会上传到 Solr【英文标题】:Last batch never uploads to Solr when uploading batches of data from json file stream 【发布时间】:2018-10-17 23:03:31 【问题描述】:

这可能是一个长镜头,但我不妨在这里尝试。有一段 c# 代码正在重建 solr 核心。步骤如下:

    删除所有现有文档 获取核心实体 将实体分成 1000 个批次 执行下一组进程的线程自旋: 将每个批次序列化为 json 并将 json 写入服务器上的文件 托管核心 向核心发送命令以使用 System.Net.WebClient solrurl/corename/update/json?stream.file=myfile.json&stream.contentType=application/json;charset=utf-8 上传该文件 删除文件。我也试过在所有批次完成后删除文件,以及根本不删除文件 所有批次完成后,它会提交。我也尝试过提交 每批完成后。

我的问题是如果最后一批远小于批量大小,则不会上传。它像调用命令一样流过,但没有任何反应。它不会引发异常,并且我在 solr 日志中看不到任何错误。我的问题是为什么?以及如何确保最后一批总是被上传?我们认为这是一个时间问题,但我们在代码的许多部分添加了 Thread.Sleep(30000) 来测试该理论,但它仍然会发生。

唯一没有发生的情况是:

如果批次已满或几乎已满 我们不运行多个线程 我们在最后一批的 File.Delete 行设置断点,等待 30 秒左右,然后继续

这是编写文件和调用更新命令的代码。每个批次都会调用它。

    private const string
        FileUpdateCommand = "1/update/json?stream.file=0&stream.contentType=application/json;charset=utf-8",
        SolrFilesDir = @"\\MYSERVER\SolrFiles",
        SolrFileNameFormat = SolrFilesDir + @"\0-1.json",
        _solrUrl = "http://MYSERVER:8983/solr/",
        CoreName = "MyCore";

    public void UpdateCoreByFile(List<CoreModel> items)
    
        if (items.Count == 0)
            return;
        var settings = new JsonSerializerSettings  DateTimeZoneHandling = DateTimeZoneHandling.Utc ;
        var dir = new DirectoryInfo(SolrFilesDir);
        if (!dir.Exists)
            dir.Create();
        var filename = string.Format(SolrFileNameFormat, Guid.NewGuid(), CoreName);
        using (var sw = new StreamWriter(filename))
        
            sw.Write(JsonConvert.SerializeObject(items, settings));
        

        var file = HttpUtility.UrlEncode(filename);
        var command = string.Format(FileUpdateCommand, file, CoreName);

        using (var client = _clientFactory.GetClient())//System.Net.WebClient
        
            client.DownloadData(new Uri(_solrUrl + command));
        
        //Thread.Sleep(30000);//doesn't work if I add this
        File.Delete(filename);//works here if add breakpoint and wait 30 sec or so
    

我只是想弄清楚为什么会发生这种情况以及如何解决它。我希望这是有道理的,并且我已经提供了足够的信息和代码。感谢您的帮助。

【问题讨论】:

【参考方案1】:

由于更改数据集的大小并添加断点“修复”它,这肯定是一种竞争条件。由于您尚未添加实际索引内容的代码,因此无法说出问题 真正 是什么,但我的猜测是最后一次提交发生在所有线程完成之前,并且仅有效当 all 线程完成时(如果你让线程休眠,问题仍然存在,因为所有线程都在同一时间休眠)。

简单的解决方法 - 改用 commitWithin,并且永远不要发出显式提交。 commitWithin 参数确保文档在给定时间范围内(以毫秒为单位)在索引中可用。为确保您提交的文档在十秒内可用,请将&amp;commitWithin=10000 附加到您的网址。

如果已经有文档等待提交,则添加的文档将在十秒之前提交,但即使最后一个文档作为最后一批提交,也不会超过十秒变得可见(.. 不会有任何文档永远处于未提交的边缘)。

这样您就不必保持线程同步或发出最终提交,只要您等到所有线程完成后再退出您的应用程序(如果它是实际终止的应用程序)。

【讨论】:

其中的提交很有趣,可能会帮助遇到类似问题的其他人;但是,这不是解决方案。我们发现了问题,它不在我粘贴的代码范围内。感谢您的意见! 出了什么问题?它可能对以后偶然发现该帖子的其他人有所帮助。 我们必须在提交之前调用 task.Wait()!

以上是关于从 json 文件流上传批量数据时,最后一批永远不会上传到 Solr的主要内容,如果未能解决你的问题,请参考以下文章

Python 3:如何在不保存在磁盘上的情况下将 pandas 数据帧作为 csv 流上传?

html 读取本地文件后使用文件二进制流上传文件

在播放框架 2.0 中将文件作为流上传

前端批量上传图片后端怎么接收?

批量插入不插入

json代码驾照考题批量加入MySQL数据库 ps.executeUpdate()永远只能悲催的加一条数据 去掉id主键自增 for 与 foreach