Вы должны быть предельно осторожны перед использованием BlobTriggers. Изначально этот пост был написан до того, как была обнаружена серьезная проблема, лежащая в основе триггеров больших двоичных объектов в целом. Суть этой проблемы в том, что если в вашей учетной записи хранилища более 10 000 больших двоичных объектов, ваши триггеры будут периодически пропускаться (т. Е. Нет гарантии доставки). Подробнее об этой проблеме вы можете прочитать здесь.

tl; dr: Если то, что вы делаете, не является игрушечным приложением, вам следует использовать триггеры сетки событий.

Тем не менее, если вы все еще собираетесь использовать BlobTrigger, не стесняйтесь продолжать читать, поскольку есть другие уловки, которые нужно запомнить.

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

Если вы когда-либо работали с функциями Azure, этот код покажется вам очень знакомым. Одним из многих триггеров, которые могут запускать лазурную функцию, является BlobTrigger.

Атрибут [BlobTrigger()] требует blobPath, что является ложью. Если вы похожи на меня, вы могли предположить, что это означает полностью определенный путь; но это не так. Этот путь на самом деле является суффиксом в форме {containername}/{suffix}. Это означает, что указанная выше функция будет выполняться даже для большого двоичного объекта my-container/DIRNOTGIVEN/myfile.json, независимо от того, что каталог DIRNOTGIVEN не указан в blobPath.

Совет №1. Если путь триггера вашего большого двоичного объекта совпадает с концом любого пути большого двоичного объекта в вашем контейнере, он будет запущен для этого большого двоичного объекта. Пути BLOB-объектов - это суффиксы.

Если не справиться с этим правильно, это заблуждение может начать выглядеть немного пугающим, если учесть, что как часть пути к BLOB-объекту вы можете указывать строки шаблона.

Вышеупомянутая функция будет выполняться для абсолютно любого файла с расширением json (опять же независимо от структуры каталогов). Удалите расширение, и оно будет запускаться для каждого файла в контейнере. Например, он подберет и my-container/abc.json, и my-container/directory/def.json

Имея это в виду, вам может быть интересно, что происходит со ссылками на Blob?

Атрибут [Blob()] также требует blobPathпараметра, и это тоже ложь. Этот путь относительно исходного триггера. В результате, если были загружены два файла - my-container/abc.json и my-container/directory/def.json - у вас теперь было бы два отдельных файла test.csv; один будет находиться в корне my-container, а другой - в my-container / directory.

Совет № 2: если у вас есть ссылка на большой двоичный объект, вызванная из функции, запускаемой большим двоичным объектом, которая была выполнена из частичного совпадения суффикса, ваша ссылка будет относиться к пути триггера!

Я расскажу вам о примере, когда мое первоначальное непонимание того, как это работает, почти вызвало проблемы в реальном мире. У нас есть набор файлов csv, которые читаются триггером большого двоичного объекта:

container-name/{thingid}/{partid}.csv

Функция, которая читает эти части, объединяет все CSV в один новый файл. Этот новый файл также имеет отдельный триггер большого двоичного объекта:

container-name/{thingid}.csv

Если бы вы не знали, что blobPath на самом деле является суффиксом (а я не знал), вы могли подумать, что вторая функция будет работать только с CSV в корне контейнера. Однако вместо этого вторая функция также выполнялась на части CSV. В нашем случае это нарушило работу функции, потому что идентификаторы partid и thingid относятся к разным типам и в результате довольно быстро были подхвачены в dev. Однако есть такая вселенная, где это могла быть долговременная вредоносная ошибка, потому что оба CSV имели одинаковую схему.

Обнаружив эту проблему, мы начали изменять способ структурирования больших двоичных объектов для триггеров. Например: container-name/{thingid}/{partid}.csv теперь стало container-name/things/{thingid}/parts/{partid}.csv

Подобное структурирование наших файлов устраняет указанную выше проблему, поскольку триггер blob container-name/things/{thingid} больше не соответствует файлам деталей (из-за /parts/sub-каталога. Однако это не серебряная пуля, но это хорошее место для начала. Он также имеет добавленную преимущество того, что кому-то будет легче понять, что такое различные идентификаторы, без необходимости запускать связанный триггер большого двоичного объекта.

Совет № 3. Всегда ставьте перед строкой шаблона значимый каталог.

Альтернатива, которую я еще не использовал, но которая, я считаю, была бы уловкой, - это хранить абсолютно все в корневом каталоге по вашему выбору. Например, если вы сохранили все в каталоге $root и никогда больше нигде не использовали это ключевое слово. Тогда указанный выше путь к BLOB-объекту может быть $root/{thingid}/{partid}.csv без проблем.

В заключение, я думаю, что все в порядке, если вы знаете, как работают триггеры и ссылки blob. Я просто хочу, чтобы в лазурном sdk было немного более понятно, как это работает. Либо переименование параметра blobPath в blobSuffix, либо добавление поддержки подстановочных знаков для N родительских каталогов (например, что-то вроде my-container/*/abc.json) может сделать это немного более понятным.