Перенос зависимостей или сторонней библиотеки в функции Azure
Из этой статьи вы узнаете, как перенести сторонние зависимости в приложения-функции. Примерами сторонних зависимостей являются JSON-файлы, двоичные файлы и модели машинного обучения.
Вы узнаете, как выполнять следующие задачи:
- Перенести зависимости через проект кода для функций
- Перенести зависимости через подключение общей папки Azure
Перенести зависимости из каталога проекта
Одним из самых простых способов переноса зависимостей является размещение файлов и артефактов вместе с кодом приложений-функций в структуре каталогов проекта функций. Ниже приведен пример образцов каталогов в проекте функций Python:
<project_root>/
| - my_first_function/
| | - __init__.py
| | - function.json
| | - example.py
| - dependencies/
| | - dependency1
| - .funcignore
| - host.json
| - local.settings.json
Если поместить зависимости в папку в каталоге проекта приложений-функций, папка зависимостей будет развернута вместе с кодом. В результате ваш код функции сможет получить доступ к зависимостям в облаке с через API файловой системы.
Доступ к зависимостям в коде
Ниже приведен пример получения доступа и выполнения зависимости ffmpeg
, помещаемой в каталог <project_root>/ffmpeg_lib
.
import logging
import azure.functions as func
import subprocess
FFMPEG_RELATIVE_PATH = "../ffmpeg_lib/ffmpeg"
def main(req: func.HttpRequest,
context: func.Context) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
command = req.params.get('command')
# If no command specified, set the command to help
if not command:
command = "-h"
# context.function_directory returns the current directory in which functions is executed
ffmpeg_path = "/".join([str(context.function_directory), FFMPEG_RELATIVE_PATH])
try:
byte_output = subprocess.check_output([ffmpeg_path, command])
return func.HttpResponse(byte_output.decode('UTF-8').rstrip(),status_code=200)
except Exception as e:
return func.HttpResponse("Unexpected exception happened when executing ffmpeg. Error message:" + str(e),status_code=200)
Примечание
Может потребоваться использовать chmod
для предоставления прав Execute
двоичному файлу FFmpeg в среде Linux.
Одним из самых простых способов переноса зависимостей является размещение файлов и артефактов вместе с кодом приложений-функций в структуре каталогов проекта функций. Ниже приведен пример образцов каталогов в проекте функций Java:
<project_root>/
| - src/
| | - main/java/com/function
| | | - Function.java
| | - test/java/com/function
| - artifacts/
| | - dependency1
| - host.json
| - local.settings.json
| - pom.xml
В частности, для Java необходимо явно включить артефакты в папку сборки или целевого объекта при копировании ресурсов. Ниже приведен пример того, как это сделать в Maven.
...
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${stagingDirectory}</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}</directory>
<includes>
<include>host.json</include>
<include>local.settings.json</include>
<include>artifacts/**</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
...
Если поместить зависимости в папку в каталоге проекта приложений-функций, папка зависимостей будет развернута вместе с кодом. В результате ваш код функции сможет получить доступ к зависимостям в облаке с через API файловой системы.
Доступ к зависимостям в коде
Ниже приведен пример получения доступа и выполнения зависимости ffmpeg
, помещаемой в каталог <project_root>/ffmpeg_lib
.
public class Function {
final static String BASE_PATH = "BASE_PATH";
final static String FFMPEG_PATH = "/artifacts/ffmpeg/ffmpeg.exe";
final static String HELP_FLAG = "-h";
final static String COMMAND_QUERY = "command";
@FunctionName("HttpExample")
public HttpResponseMessage run(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) throws IOException{
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String flags = request.getQueryParameters().get(COMMAND_QUERY);
if (flags == null || flags.isBlank()) {
flags = HELP_FLAG;
}
Runtime rt = Runtime.getRuntime();
String[] commands = { System.getenv(BASE_PATH) + FFMPEG_PATH, flags};
Process proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
String out = stdInput.lines().collect(Collectors.joining("\n"));
if(out.isEmpty()) {
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
out = stdError.lines().collect(Collectors.joining("\n"));
}
return request.createResponseBuilder(HttpStatus.OK).body(out).build();
}
Примечание
Чтобы получить этот фрагмент кода для работы в Azure, необходимо указать пользовательский параметр приложения "BASE_PATH" со значением "/home/site/wwwroot".
Перемещение зависимостей путем подключения общей папки
При запуске приложения-функции в Linux существует другой способ подключения сторонних зависимостей. Функции позволяют подключать общую папку, размещенную в службе файлов Azure. Этот подход следует использовать, если требуется разделить зависимости или артефакты из вашего кода приложения.
Сначала нужно создать учетную запись хранения в Azure. В учетной записи также необходимо создать общую папку в службе файлов Azure. Чтобы создать эти ресурсы, следуйте этому руководству.
После создания учетной записи хранения и общей папки используйте команду az webapp config storage-account add, чтобы подключить общую папку к приложению-функции, как показано далее в примере.
az webapp config storage-account add \
--name < Function-App-Name > \
--resource-group < Resource-Group > \
--subscription < Subscription-Id > \
--custom-id < Unique-Custom-Id > \
--storage-type AzureFiles \
--account-name < Storage-Account-Name > \
--share-name < File-Share-Name > \
--access-key < Storage-Account-AccessKey > \
--mount-path </path/to/mount>
Флаг | Значение |
---|---|
Пользовательский идентификатор | Любая уникальная строка |
Тип хранилища | На данный момент поддерживаются только AzureFiles |
имя общего ресурса | Уже имеющаяся общая папка |
путь подключения | Путь, по которому общая папка будет доступна внутри контейнера. Значение должно иметь формат /dir-name и не может начинаться с /home |
Дополнительные команды для изменения или удаления конфигурации общей папки можно найти здесь.
Отправка зависимостей в службу файлов Azure
Один из вариантов отправки зависимости в службу файлов Azure — с помощью портала Azure. Инструкции по отправке зависимостей с помощью портала см. в этом руководстве. Кроме того, отправить зависимости в службу файлов Azure можно через Azure CLI и PowerShell.
Доступ к зависимостям в коде
После отправки зависимостей в общую папку можно получить доступ к зависимостям из кода. Подключенная общая папка доступна по указанному пути подключения, например /path/to/mount
. Доступ к целевому каталогу можно получить с помощью программных интерфейсов файловой системы.
В следующем примере показан код триггера HTTP, обращающийся к библиотеке ffmpeg
, которая хранится в подключенной общей папке.
import logging
import azure.functions as func
import subprocess
FILE_SHARE_MOUNT_PATH = os.environ['FILE_SHARE_MOUNT_PATH']
FFMPEG = "ffmpeg"
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
command = req.params.get('command')
# If no command specified, set the command to help
if not command:
command = "-h"
try:
byte_output = subprocess.check_output(["/".join(FILE_SHARE_MOUNT_PATH, FFMPEG), command])
return func.HttpResponse(byte_output.decode('UTF-8').rstrip(),status_code=200)
except Exception as e:
return func.HttpResponse("Unexpected exception happened when executing ffmpeg. Error message:" + str(e),status_code=200)
При развертывании этого кода в приложении-функции в Azure необходимо создать параметр приложения с именем ключа FILE_SHARE_MOUNT_PATH
и значением пути к подключенной общей папке (в данном примере это /azure-files-share
). Чтобы выполнить локальную отладку, необходимо указать для свойства FILE_SHARE_MOUNT_PATH
значение пути к файлу, в котором хранятся зависимости на локальном компьютере. Ниже приведен пример для установки FILE_SHARE_MOUNT_PATH
с помощью local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "python",
"FILE_SHARE_MOUNT_PATH" : "PATH_TO_LOCAL_FFMPEG_DIR"
}
}
Дальнейшие действия
- Azure Functions Python Developer Guide (Справочник по Функциям Azure для разработчика Python)
- Руководство разработчика Java по Функциям Azure
- Справочник разработчика по функциям Azure