Скрипт Python для записи (+ блокировки)/чтения файла в Azure

Я новичок в программировании на Python и Azure.

Мне нужно написать скрипт, который будет выполняться двумя процессами.

Два процесса будут запускать один и тот же скрипт Python. Я знаю, что у Azure есть storageAccounts для размещения в нем некоторых файлов, я нашел это: https://docs.microsoft.com/en-us/python/api/azure-storage-file/azure.storage.file.fileservice.fileservice?view=azure-python

и: https://github.com/Azure/azure-storage-python

Вот некоторый псевдокод, чтобы проиллюстрировать, чего мне нужно достичь:

function useStorageFile
   if(fileFromStorage == null)
      createFileInStorage lockFileInStorage;
      executeDockerCommand;
      writeResultOFCommandInStorageFile;
   else
      if(fileFromStorage != null)
        X:if(fileFromStorage.status !== 'locked')
           readResultFromFile
        else
           wait 1s;
           continue X;

Можно ли заблокировать/разблокировать файл в Azure? Как я могу добиться этого, например, в python? благодарю вас.

EDIT Мне удалось записать файл в хранилище BLOB-объектов с помощью скрипта Python. Теперь возникает вопрос: как я могу заблокировать файл, записывая в него результат команды первым процессом, и сделать его прочитанным вторым процессом, как только блокировка хранилища BLOB-объектов (если существует опция...) освобождается первый процесс? вот скрипт python, который я использую:

import os, uuid, sys
from azure.storage.blob import BlockBlobService, PublicAccess

def run_sample():
    try:
        # Create the BlockBlockService that is used to call the Blob service for the storage account
        block_blob_service = BlockBlobService(account_name='xxxxxx', account_key='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

        # Create a container called 'quickstartblobs'.
        container_name ='quickstartblobs'
        block_blob_service.create_container(container_name)

        # Set the permission so the blobs are public.
        block_blob_service.set_container_acl(container_name, public_access=PublicAccess.Container)

        # Create a file in Documents to test the upload and download.
        local_path=os.path.abspath(os.path.curdir)
        local_file_name ='youss.txt'
        full_path_to_file =os.path.join(local_path, local_file_name)

        # Write text to the file.
        file = open(full_path_to_file,  'w')
        file.write("Hello, World!")
        file.close()

        print("Temp file = " + full_path_to_file)
        print("\nUploading to Blob storage as blob" + local_file_name)

        # Upload the created file, use local_file_name for the blob name
        block_blob_service.create_blob_from_path(container_name, local_file_name, full_path_to_file)

        # List the blobs in the container
        print("\nList blobs in the container")
        generator = block_blob_service.list_blobs(container_name)
        for blob in generator:
            print("\t Blob name: " + blob.name)

        # Download the blob(s).
        # Add '_DOWNLOADED' as prefix to '.txt' so you can see both files in Documents.
        full_path_to_file2 = os.path.join(local_path, str.replace(local_file_name ,'.txt', '_DOWNLOADED.txt'))
        print("\nDownloading blob to " + full_path_to_file2)
        block_blob_service.get_blob_to_path(container_name, local_file_name, full_path_to_file2)

        sys.stdout.write("Sample finished running. When you hit <any key>, the sample will be deleted and the sample "
                         "application will exit.")
        sys.stdout.flush()
        input()

        # Clean up resources. This includes the container and the temp files
        block_blob_service.delete_container(container_name)
        os.remove(full_path_to_file)
        os.remove(full_path_to_file2)
    except Exception as e:
        print(e)


# Main method.
if __name__ == '__main__':
    run_sample()

person Youssef Harkati    schedule 18.05.2019    source источник
comment
Обязательно ли использовать хранилище файлов Azure? Можно ли вместо этого использовать хранилище BLOB-объектов Azure?   -  person Gaurav Mantri    schedule 19.05.2019
comment
@GauravMantri нет, я сказал Хранилище файлов Azure, потому что я новичок в Azure, и это было первое, что я нашел. Хранилище BLOB-объектов лучше? Можно ли решить мою проблему? спасибо   -  person Youssef Harkati    schedule 19.05.2019
comment
Спасибо! Еще один вопрос: вы хотите заблокировать файл для записи или чтения?   -  person Gaurav Mantri    schedule 19.05.2019
comment
@GauravMantri Я использовал хранилище BLOB-объектов и смог написать скрипт на Python для создания файла. На самом деле моя проблема заключается в том, чтобы убедиться, что только один из двух процессов (фактически 2 виртуальные машины) будет писать в него, а второй читать этот файл, как только блокировка будет снята. я отредактирую свой вопрос, чтобы написать код, который я сделал для создания файла в хранилище BLOB-объектов.   -  person Youssef Harkati    schedule 19.05.2019
comment
Я не думаю, что вы можете заблокировать сам файл. Как насчет эмуляции блокировки путем создания второго файла блокировки в той же папке с другим именем? Процесс перед открытием фактического файла проверит, есть ли файл блокировки в папке, и если нет, нажмите файл блокировки, а затем откройте фактический файл для чтения, удалив файл блокировки после завершения работы. Очевидно, что возможен случай состояния гонки, который теоретически можно решить, используя системы с гораздо меньшими задержками, такие как очереди RabbitMQ/Kafka или что-то, основанное на технике семафоров.   -  person dimon222    schedule 19.05.2019
comment
@ dimon222 dimon222 тот же код будет выполняться на двух разных виртуальных машинах (то есть на двух разных процессах) в одной подсети (azure). И я думаю, что есть способ добиться этого с помощью хранилища больших двоичных объектов, потому что я нашел это: docs.microsoft.com/en-us/azure/storage/common/. Осталось найти как :)   -  person Youssef Harkati    schedule 20.05.2019
comment
Я имею в виду файл блокировки, которым нужно управлять в хранилище файлов Azure (поскольку это хранилище, которое, как я предполагаю, вы разделяете через монтирование между двумя виртуальными машинами). Честно говоря, большинство этих механизмов хранения используют согласованность в конечном итоге, поэтому для небольшой задержки вы, вероятно, захотите управлять параллелизмом вне его через очереди. В качестве альтернативы, если вместо этого вы используете хранилище BLOB-объектов Azure, файл будет зафиксирован в корзине только после его полной загрузки (то есть при фиксации). Вы можете интегрировать событие загрузки/фиксации файла в Функции Azure   -  person dimon222    schedule 20.05.2019


Ответы (1)


Как я могу заблокировать файл во время записи в него результата команды первым процессом и сделать его прочитанным вторым процессом, как только блокировка хранилища BLOB-объектов (если опция существует...) будет освобождена первым процессом?

В хранилище BLOB-объектов Azure есть функция под названием Lease, которую вы может воспользоваться. По сути, процесс Leasing получает эксклюзивную блокировку ресурса (большой двоичный объект в вашем случае), и только один процесс может арендовать большой двоичный объект. После получения аренды большого двоичного объекта любой другой процесс не может изменить или удалить большой двоичный объект.

Итак, что вам нужно сделать, это попытаться получить аренду блоба перед записью. Если большой двоичный объект уже арендован, вы получите сообщение об ошибке (код состояния HTTP 412, ошибка PreConditionFailed). Предполагая, что вы не получили сообщение об ошибке, вы можете продолжить обновление файла. После обновления файла вы можете либо вручную снять блокировку (либо разорвать аренду, либо освободить аренду), либо разрешить автоматическое истечение срока аренды. Предполагая, что вы получили сообщение об ошибке, вы должны подождать и периодически получать статус аренды большого двоичного объекта (скажем, каждые 5 секунд). Как только вы обнаружите, что большой двоичный объект больше не арендован, вы можете прочитать его содержимое.

person Gaurav Mantri    schedule 21.05.2019
comment
спасибо, чувак, это действительно похоже на то, что мне нужно, я собираюсь попробовать твое решение, так как оно звучит как ОДНО :), как ты думаешь, это возможно в python? большое спасибо - person Youssef Harkati; 21.05.2019
comment
Большой двоичный объект аренды должен быть доступен в Storage SDK для python. Попробуйте найти функцию lease_blob или что-то подобное в blob_service. - person Gaurav Mantri; 21.05.2019
comment
я нашел это для реализации Python github.com/Azure-Samples/storage-blob-python-getting-started/ Как вы рекомендуете периодически выполнять выборку аренды BLOB-объекта? я думаю, возможно, с циклом while (извините, я новичок в программировании на python) - person Youssef Harkati; 21.05.2019
comment
How do you recommend to implement the fetch of the blob's lease periodically ?. Я бы периодически получал свойства большого двоичного объекта и проверял статус аренды. Я также не очень хорошо разбираюсь в python, но да, вам нужно будет выполнить цикл while. - person Gaurav Mantri; 21.05.2019
comment
Кроме того, убедитесь, что вы не установили аренду infinite для большого двоичного объекта. Установите более короткую продолжительность (от 15 до 60 секунд), чтобы в случае возникновения проблемы с записью процесса в большой двоичный объект аренда автоматически очищалась по истечении этого времени. - person Gaurav Mantri; 21.05.2019