Portare le dipendenze o la libreria di terze parti in Funzioni di Azure
Questo articolo illustra come inserire dipendenze di terze parti nelle app per le funzioni. Esempi di dipendenze di terze parti sono file JSON, file binari e modelli di Machine Learning.
In questo articolo vengono illustrate le operazioni seguenti:
- Inserire dipendenze tramite il progetto codice di Funzioni
- Inserire le dipendenze tramite il montaggio della condivisione file di Azure
Inserire dipendenze dalla directory del progetto
Uno dei modi più semplici per inserire le dipendenze consiste nell'inserire i file/artefatti insieme al codice dell'app per le funzioni nella struttura di directory del progetto Funzioni. Di seguito è riportato un esempio di esempi di directory in un progetto di funzioni Python:
<project_root>/
| - my_first_function/
| | - __init__.py
| | - function.json
| | - example.py
| - dependencies/
| | - dependency1
| - .funcignore
| - host.json
| - local.settings.json
Inserendo le dipendenze in una cartella all'interno della directory del progetto dell'app per le funzioni, la cartella dependencies verrà distribuita insieme al codice. Di conseguenza, il codice della funzione può accedere alle dipendenze nel cloud tramite l'API del file system.
Accesso alle dipendenze nel codice
Ecco un esempio per accedere ed eseguire ffmpeg
le dipendenze inserite nella <project_root>/ffmpeg_lib
directory.
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
Potrebbe essere necessario usare chmod
per fornire Execute
diritti al file binario ffmpeg in un ambiente Linux
Uno dei modi più semplici per inserire le dipendenze consiste nell'inserire i file/artefatti insieme al codice dell'app per le funzioni nella struttura di directory del progetto di funzioni. Ecco un esempio di esempi di directory in un progetto di funzioni Java:
<project_root>/
| - src/
| | - main/java/com/function
| | | - Function.java
| | - test/java/com/function
| - artifacts/
| | - dependency1
| - host.json
| - local.settings.json
| - pom.xml
Per Java in particolare, è necessario includere in modo specifico gli artefatti nella cartella di compilazione/destinazione durante la copia delle risorse. Ecco un esempio su come eseguire questa operazione in 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>
...
Inserendo le dipendenze in una cartella all'interno della directory del progetto dell'app per le funzioni, la cartella dependencies verrà distribuita insieme al codice. Di conseguenza, il codice della funzione può accedere alle dipendenze nel cloud tramite l'API del file system.
Accesso alle dipendenze nel codice
Ecco un esempio per accedere ed eseguire ffmpeg
le dipendenze inserite nella <project_root>/ffmpeg_lib
directory.
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
Per ottenere il funzionamento di questo frammento di codice in Azure, è necessario specificare un'impostazione dell'applicazione personalizzata "BASE_PATH" con il valore "/home/site/wwwroot"
Portare le dipendenze montando una condivisione file
Quando si esegue l'app per le funzioni in Linux, esiste un altro modo per introdurre dipendenze di terze parti. Funzioni consente di montare una condivisione file ospitata in File di Azure. Prendere in considerazione questo approccio quando si vogliono separare le dipendenze o gli artefatti dal codice dell'applicazione.
Prima di tutto, è necessario creare un account di archiviazione di Azure. Nell'account è anche necessario creare una condivisione file in file di Azure. Per creare queste risorse, seguire questa guida
Dopo aver creato l'account di archiviazione e la condivisione file, usare il comando az webapp config storage-account add per collegare la condivisione file all'app per le funzioni, come illustrato nell'esempio seguente.
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>
Flag | valore |
---|---|
custom-id | Qualsiasi stringa univoca |
tipo di archiviazione | Attualmente è supportato solo AzureFiles |
share-name | Condivisione preesistente |
mount-path | Percorso in cui la condivisione sarà accessibile all'interno del contenitore. Il valore deve essere del formato /dir-name e non può iniziare con /home |
Altri comandi per modificare/eliminare la configurazione della condivisione file sono disponibili qui
Caricamento delle dipendenze in File di Azure
Un'opzione per caricare la dipendenza in File di Azure è tramite portale di Azure. Per istruzioni sul caricamento delle dipendenze tramite il portale, vedere questa guida . Altre opzioni per caricare le dipendenze in File di Azure sono tramite l'interfaccia della riga di comando di Azure e PowerShell.
Accesso alle dipendenze nel codice
Dopo aver caricato le dipendenze nella condivisione file, è possibile accedere alle dipendenze dal codice. La condivisione montata è disponibile nel percorso di montaggio specificato, ad esempio /path/to/mount
. È possibile accedere alla directory di destinazione usando le API del file system.
Nell'esempio seguente viene illustrato il codice trigger HTTP che accede alla ffmpeg
libreria, archiviata in una condivisione file montata.
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 si distribuisce questo codice in un'app per le funzioni in Azure, è necessario creare un'impostazione dell'app con un nome di chiave e FILE_SHARE_MOUNT_PATH
il valore del percorso della condivisione file montata, che per questo esempio è /azure-files-share
. Per eseguire il debug locale, è necessario popolare con il FILE_SHARE_MOUNT_PATH
percorso del file in cui sono archiviate le dipendenze nel computer locale. Ecco un esempio da impostare 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"
}
}