Последний пакет никогда не загружается в Solr при загрузке пакетов данных из потока файлов json - PullRequest
0 голосов
/ 18 октября 2018

Это может быть далеко, но я мог бы попробовать здесь.Существует блок кода на C #, который перестраивает ядро ​​Solr.Шаги следующие:

  1. Удалить все существующие документы
  2. Получить основные сущности
  3. Разделить сущности на партии по 1000
  4. Вращениепотоков для преобразования следующего набора процессов:
  5. Сериализация каждого пакета в json и запись json в файл на сервере, на котором размещено ядро ​​
  6. Отправка команды в ядро ​​для загрузки этого файлаиспользование System.Net.WebClient solrurl / corename / update / json? stream.file = myfile.json & stream.contentType = application / json; charset = utf-8
  7. Удалить файл.Я также попытался удалить файлы после того, как все пакеты сделаны, и вообще не удалять файлы
  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 Ответ

0 голосов
/ 18 октября 2018

Поскольку изменение размера набора данных и добавление точки останова «исправляет» его, это, безусловно, условие гонки.Поскольку вы еще не добавили код, который фактически индексирует контент, невозможно сказать, в чем проблема на самом деле , но я предполагаю, что последний коммит происходит до того, как все потоки завершены, и работает только тогда, когда все потоки завершены (если вы спите с потоками, проблема все равно останется, поскольку все потоки спят в одно и то же время).

Простое исправление - используйте взамен commitWithin и никогда не выполняйте явные коммиты.Параметр commitWithin гарантирует, что документы станут доступны в индексе в течение заданного периода времени (в виде миллисекунд).Чтобы убедиться, что отправленные вами документы станут доступны в течение десяти секунд, добавьте &commitWithin=10000 к своему URL.

Если документы, ожидающие принятия, уже есть, добавленные документы будут подтверждены до истечения десяти секунд, нодаже если в качестве последнего пакета будет представлен только один последний документ, никогда не пройдет более десяти секунд, прежде чем он станет видимым (.. и не будет никаких документов, навсегда оставленных в безусловном подвешенном состоянии).

Таким образом, вам не нужно будет синхронизировать ваши потоки или выполнить окончательную фиксацию, пока вы ждете, пока все потоки не завершат работу, прежде чем выйти из вашего приложения (если это приложение действительно завершается).

...