Отслеживание 1400+ клиентских кодов, многопоточность кошмар

Я ищу немного помощи. Мне нужно циклически перебрать код 1400 клиентов на моем сервере, я должен проверить, на какой версии программного обеспечения они работают, и проверить настройки кода, поэтому, когда мы применяем обновления, они не теряются. Я попытался сделать его сериализованным, как вы могли догадаться, это заняло вечность. Затем я попытался запустить его параллельно, как вы могли ожидать, я получаю «Ошибка Os, слишком много открытых файлов». Я попытался решить это, добавив «sleep (random ())», который работает, но это кажется запутанным и замедляется значительно замедлил процесс, и, возможно, мой код был полным мусором, любое понимание было бы замечательно.

Я использую git в CLI, чтобы получить версию, это кажется тяжелым? Есть ли лучший способ тянуть теги?

Здесь я получаю список клиентов, я немного редактирую, чтобы получить путь

def full_check(client_list, cur_vers):
    for c in client_list:
        if sc.venue_check(c):
            url = sc.surl(c[0])
            if url is not None:
                path = f'/home/ubuntu/site-files/{url}'
                # Maximizing output, this cut run time by 90%
                # Hard to log though...

                nschools.append({
                    'path': path,
                    'cur_vers': cur_vers,
                    'client': c[0],
                    'schema_version': c[2]
                })
# Here, I am then looping through the paths I get, I put a sleep to stop it from bugging out
# about OS File open Limits
    for s in nschools:
        print(s['path'])
        sleep(random())
        t = threading.Thread(target=vers_check, args=(s['path'], s['cur_vers'], s['client'], s['schema_version']))
        t.start()

Здесь я проверяю версию

def vers_check(path, cur_vers, client, schema_version):
    """
    This Checks the Schools Release.
    TODO Add logging and Return Functionality.
    :param client:
    :param schema_version:
    :param path:
    :param school:
    :param cur_vers:
    :return:
    """
    os.chdir(path)
    try:
        vers = subprocess.check_output(["git", "describe", "--tags"]).strip().decode('utf-8')

        raw = str(vers).strip('-')
        rawsplit = raw.split('-')
        st = rawsplit[0]

        if str(st) != cur_vers:
            cschools.append({
                'client': client,
                'schema_version': schema_version,
                'sw_version': st,
                'path': path,
                'is_update': False
            })
            log.log('warn', 'Version Check', f'The School {client} is on Software Version {st} and Schema Version {schema_version} Which is Out Of Date. Current Version is {cur_vers}')
        else:
            cschools.append({
                'client': client,
                'schema_version': schema_version,
                'sw_version': st,
                'path': path,
                'is_update': True
            })
            log.log('info', 'Version Check', f'The School is on Software Version {st} and Schema Version {schema_version} Which is Up To Date. Current Version is {cur_vers}')
    except subprocess.CalledProcessError as e:
        log.log('err', 'Failed Version Check', f'We were unable to get the version for {client}', e)
```

1 ответ
1

Во-первых, я почти уверен, что это невозможно для

os.chdir(path)

осмысленно применять разные рабочие каталоги для каждого потока; и даже если бы это было возможно, это была бы плохая идея. подпроцесс поддерживает cwd параметр непосредственно то, что вам следует использовать.

Если бы вы открывали файлы самостоятельно, вам бы хотелось семафор где блокировка применяется только к той части кода, в которой открывается файл. Однако вы не открываете файлы — вероятно, это ваш вызов git который открывает больше всего файлов.

Я думаю, что единственный практический способ обойти это — просто ограничить количество параллельных потоков. Вы можете либо оценить это заранее, либо продолжать раскручивать потоки, пока не достигнете первого OSError и не запускайте новые потоки, выполняя их по одному, пока ваш рабочий пул не будет завершен.

Если вы глубоко заботитесь о производительности, подпроцессинг git следует заменить вычислением в процессе; либо вызов библиотеки, либо ручная обработка записей в .git (Я тоже не исследовал).

  • 1

    Звучит примерно правильно. Итак, если я правильно понимаю, вместо git describe —tags откройте .git / refs / tags и проверьте наличие там файла последней версии.

    — парень с цифрами

  • Ага; если это возможно, это в основном гарантированно будет быстрее

    — Райндериен

  • 2

    Holy Shitballs batman … код прогона от 1-3 минут до ~ 3-5 секунд

    — парень с цифрами

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *