Trazer dependências ou biblioteca de terceiros para Funções do Azure
Neste artigo, vai aprender a incluir dependências de terceiros nas suas aplicações de funções. Exemplos de dependências de terceiros são ficheiros json, ficheiros binários e modelos de machine learning.
Neste artigo, vai aprender a:
- Trazer dependências através do projeto Código das Funções
- Trazer dependências através da montagem do Azure Fileshare
Trazer dependências do diretório do projeto
Uma das formas mais simples de introduzir dependências é colocar os ficheiros/artefactos em conjunto com o código da aplicação de funções na estrutura de diretório do projeto de Funções. Eis um exemplo dos exemplos de diretórios num 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 numa pasta dentro do diretório do projeto de aplicação de funções, a pasta de dependências será implementada juntamente com o código. Como resultado, o código de função pode aceder às dependências na cloud através da API do sistema de ficheiros.
Aceder às dependências no código
Eis um exemplo para aceder e executar ffmpeg
a dependência que é colocada no <project_root>/ffmpeg_lib
diretório.
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)
Nota
Poderá ter de utilizar chmod
para fornecer Execute
direitos ao binário ffmpeg num ambiente linux
Uma das formas mais simples de introduzir dependências é colocar os ficheiros/artefactos em conjunto com o código da aplicação de funções na estrutura de diretório do projeto de funções. Eis um exemplo dos exemplos de diretórios num projeto de funções 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, tem de incluir especificamente os artefactos na pasta build/target ao copiar recursos. Eis um exemplo sobre como fazê-lo 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 numa pasta dentro do diretório do projeto de aplicação de funções, a pasta de dependências será implementada juntamente com o código. Como resultado, o código de função pode aceder às dependências na cloud através da API do sistema de ficheiros.
Aceder às dependências no código
Eis um exemplo para aceder e executar ffmpeg
a dependência que é colocada no <project_root>/ffmpeg_lib
diretório.
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();
}
Nota
Para que este fragmento de código funcione no Azure, tem de especificar uma definição de aplicação personalizada de "BASE_PATH" com o valor "/home/site/wwwroot"
Traga dependências ao montar uma partilha de ficheiros
Ao executar a aplicação de funções no Linux, existe outra forma de introduzir dependências de terceiros. As funções permitem-lhe montar uma partilha de ficheiros alojada no Ficheiros do Azure. Considere esta abordagem quando quiser desassociar dependências ou artefactos do código da aplicação.
Primeiro, tem de criar uma Conta de Armazenamento do Azure. Na conta, também tem de criar uma partilha de ficheiros nos ficheiros do Azure. Para criar estes recursos, siga este guia
Depois de criar a conta de armazenamento e a partilha de ficheiros, utilize o comando az webapp config storage-account add para anexar a partilha de ficheiros à sua aplicação de funções, conforme mostrado no exemplo seguinte.
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 exclusiva |
tipo de armazenamento | Atualmente, apenas o AzureFiles é suportado |
share-name | Partilha pré-existente |
mount-path | Caminho no qual a partilha estará acessível dentro do contentor. O valor tem de ser do formato /dir-name e não pode começar com /home |
Pode encontrar mais comandos para modificar/eliminar a configuração da partilha de ficheiros aqui
Carregar as dependências para Ficheiros do Azure
Uma opção para carregar a dependência para Ficheiros do Azure é através de portal do Azure. Veja este guia para obter instruções para carregar dependências com o portal. Outras opções para carregar as suas dependências para Ficheiros do Azure são através da CLI do Azure e do PowerShell.
Aceder às dependências no código
Depois de as dependências serem carregadas na partilha de ficheiros, pode aceder às dependências a partir do seu código. A partilha montada está disponível no caminho de montagem especificado, como /path/to/mount
. Pode aceder ao diretório de destino através de APIs do sistema de ficheiros.
O exemplo seguinte mostra o código do acionador HTTP que acede à ffmpeg
biblioteca, que é armazenada numa partilha de ficheiros montada.
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)
Quando implementa este código numa aplicação de funções no Azure, tem de criar uma definição de aplicação com um nome de FILE_SHARE_MOUNT_PATH
chave e valor do caminho de partilha de ficheiros montado, que, para este exemplo, é /azure-files-share
. Para efetuar a depuração local, tem de preencher o com o FILE_SHARE_MOUNT_PATH
caminho do ficheiro onde as dependências estão armazenadas no seu computador local. Eis um exemplo a definir FILE_SHARE_MOUNT_PATH
com local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "python",
"FILE_SHARE_MOUNT_PATH" : "PATH_TO_LOCAL_FFMPEG_DIR"
}
}