Trazer dependências ou biblioteca de terceiros para o Azure Functions
Neste artigo, você aprenderá a trazer dependências de terceiros para os aplicativos de funções. Exemplos de dependências de terceiros são arquivos json, arquivos binários e modelos de machine learning.
Neste artigo, você aprenderá como:
- Trazer dependências por meio do projeto de código do Functions
- Trazer dependências por meio da montagem do Azure Fileshare
Trazer dependências do diretório do projeto
Uma das maneiras mais simples de trazer dependências é colocar os arquivos/artefatos junto com o código do aplicativo de funções na estrutura de diretório do projeto do Functions. Este é um exemplo das amostras de diretório em um projeto de funções do Python:
<project_root>/
| - my_first_function/
| | - __init__.py
| | - function.json
| | - example.py
| - dependencies/
| | - dependency1
| - .funcignore
| - host.json
| - local.settings.json
Ao colocar as dependências em uma pasta dentro do diretório do projeto do aplicativo de funções, a pasta de dependências será implantada junto com o código. Como resultado, o código da função pode acessar as dependências na nuvem por meio da API do sistema de arquivos.
Acessar as dependências no código
Aqui está um exemplo de como acessar e executar a dependência ffmpeg
que é colocada no diretório <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)
Observação
Talvez seja necessário usar chmod
para fornecer direitos de Execute
ao binário ffmpeg em um ambiente do Linux
Uma das maneiras mais simples de trazer dependências é colocar os arquivos/artefatos junto com o código do aplicativo de funções na estrutura de diretório do projeto de funções. Este é um exemplo das amostras de diretório em um projeto de funções do Java:
<project_root>/
| - src/
| | - main/java/com/function
| | | - Function.java
| | - test/java/com/function
| - artifacts/
| | - dependency1
| - host.json
| - local.settings.json
| - pom.xml
Especificamente para Java, você precisa incluir os artefatos na pasta compilação/destino ao copiar os recursos. Veja um exemplo de como fazer isso no 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>
...
Ao colocar as dependências em uma pasta dentro do diretório do projeto do aplicativo de funções, a pasta de dependências será implantada junto com o código. Como resultado, o código da função pode acessar as dependências na nuvem por meio da API do sistema de arquivos.
Acessar as dependências no código
Aqui está um exemplo de como acessar e executar a dependência ffmpeg
que é colocada no diretório <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();
}
Observação
Para que esse trecho de código funcione no Azure, você precisa especificar uma configuração de aplicativo personalizada de "BASE_PATH" com o valor de "/home/site/wwwroot"
Trazer dependências montando um compartilhamento de arquivos
Ao executar seu aplicativo de funções no Linux, há outra maneira de trazer dependências de terceiros. O Functions permite montar um compartilhamento de arquivos hospedado no Arquivos do Azure. Considere essa abordagem quando quiser desassociar dependências ou artefatos do código do aplicativo.
Primeiro, você precisa criar uma conta de Armazenamento do Azure. Na conta, você também precisa criar o compartilhamento de arquivos nos arquivos do Azure. Para criar esses recursos, siga este guia
Depois de criar a conta de armazenamento e o compartilhamento de arquivos, use o comando az webapp config storage-account add para anexar o compartilhamento de arquivos ao aplicativo de funções, conforme mostrado no exemplo a seguir.
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>
Sinalizador | Valor |
---|---|
custom-id | Qualquer cadeia de caracteres exclusiva |
storage-type | Somente AzureFiles tem suporte no momento |
share-name | Compartilhamento preexistente |
mount-path | Caminho no qual o compartilhamento estará acessível dentro do contêiner. O valor deve estar no formato /dir-name e não pode começar com /home |
Mais comandos para modificar/excluir a configuração de compartilhamento de arquivos podem ser encontrados aqui
Carregar as dependências no Arquivos do Azure
Uma opção para carregar sua dependência no Arquivos do Azure é por meio do portal do Azure. Consulte este guia para ver instruções de como carregar dependências usando o portal. Outras opções para carregar suas dependências no Arquivos do Azure são por meio da CLI do Azure e do PowerShell.
Acessar as dependências no código
Depois que suas dependências são carregadas no compartilhamento de arquivos, você pode acessar as dependências do código. O compartilhamento montado está disponível no mount-path especificado, como /path/to/mount
. Você pode acessar o diretório de destino usando APIs do sistema de arquivos.
O exemplo a seguir mostra o código de gatilho HTTP que acessa a biblioteca ffmpeg
, que é armazenada em um compartilhamento de arquivos montado.
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)
Ao implantar esse código em um aplicativo de funções no Azure, você precisa criar uma configuração de aplicativo com um nome de chave de FILE_SHARE_MOUNT_PATH
e o valor do caminho do compartilhamento de arquivos montado, que neste exemplo é /azure-files-share
. Para fazer a depuração local, você precisa preencher o FILE_SHARE_MOUNT_PATH
com o caminho do arquivo em que suas dependências são armazenadas no computador local. Este é um exemplo para definir FILE_SHARE_MOUNT_PATH
usando local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "python",
"FILE_SHARE_MOUNT_PATH" : "PATH_TO_LOCAL_FFMPEG_DIR"
}
}