Share via


Bereitstellen von Abhängigkeiten und Bibliotheken von Drittanbietern in Azure Functions

In diesem Artikel erfahren Sie, wie Sie Abhängigkeiten von Drittanbietern in Ihre Funktions-Apps übernehmen. Beispiele für Abhängigkeiten von Drittanbietern sind .json-Dateien, Binärdateien und Machine Learning-Modelle.

In diesem Artikel werden folgende Vorgehensweisen behandelt:

  • Einbringen von Abhängigkeiten über das Functions Code-Projekt
  • Einbinden von Abhängigkeiten durch Einbinden der Azure-Dateifreigabe

Einbringen von Abhängigkeiten aus dem Projektverzeichnis

Eine der einfachsten Möglichkeiten, Abhängigkeiten einzubringen, ist das Zusammenbringen der Dateien/Artefakte mit dem Funktions-App-Code in der Verzeichnisstruktur des Functions-Projekts. Hier sehen Sie ein Beispiel für die Verzeichnisbeispiele in einem Python-Funktionsprojekt:

<project_root>/
 | - my_first_function/
 | | - __init__.py
 | | - function.json
 | | - example.py
 | - dependencies/
 | | - dependency1
 | - .funcignore
 | - host.json
 | - local.settings.json

Indem die Abhängigkeiten in einem Ordner im Projektverzeichnis der Functions-App abgelegt werden, wird der Abhängigkeiten-Ordner zusammen mit dem Code bereitgestellt. Daher kann Ihr Funktionscode über die Dateisystem-API auf die Abhängigkeiten in der Cloud zugreifen.

Zugreifen auf die Abhängigkeiten in Ihrem Code

Im Folgenden finden Sie ein Beispiel für den Zugriff auf und die Ausführung von ffmpeg-Abhängigkeiten, die im <project_root>/ffmpeg_lib-Verzeichnis gespeichert werden.

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)

Hinweis

Möglicherweise müssen Sie chmod verwenden, um Execute-Rechte für die ffmpeg-Binärdatei in einer Linux-Umgebung zu bieten

Eine der einfachsten Möglichkeiten, Abhängigkeiten einzubringen, ist das Zusammenbringen der Dateien/Artefakte mit dem Funktions-App-Code in der Verzeichnisstruktur des Funktionsprojekts. Hier sehen Sie ein Beispiel für die Verzeichnisbeispiele in einem Java-Funktionsprojekt:

<project_root>/
 | - src/
 | | - main/java/com/function
 | | | - Function.java
 | | - test/java/com/function
 | - artifacts/
 | | - dependency1
 | - host.json
 | - local.settings.json
 | - pom.xml

Insbesondere für Java müssen Sie die Artefakte beim Kopieren von Ressourcen explizit in den Build-/Zielordner hinzufügen. Hier sehen Sie ein Beispiel für die Verwendung 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>
...

Indem die Abhängigkeiten in einem Ordner im Projektverzeichnis der Functions-App abgelegt werden, wird der Abhängigkeiten-Ordner zusammen mit dem Code bereitgestellt. Daher kann Ihr Funktionscode über die Dateisystem-API auf die Abhängigkeiten in der Cloud zugreifen.

Zugreifen auf die Abhängigkeiten in Ihrem Code

Im Folgenden finden Sie ein Beispiel für den Zugriff auf und die Ausführung von ffmpeg-Abhängigkeiten, die im <project_root>/ffmpeg_lib-Verzeichnis gespeichert werden.

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();

    }

Hinweis

Damit dieser Codeausschnitt in Azure funktioniert, müssen Sie die benutzerdefinierte Anwendungseinstellung „BASE_PATH“ mit dem Wert „/home/site/wwwroot“ angeben

Einbinden von Abhängigkeiten durch Einbinden einer Dateifreigabe

Wenn Sie Ihre Funktions-App unter Linux ausführen, gibt es eine andere Möglichkeit, Abhängigkeiten von Drittanbietern einzubringen. Mit Functions können Sie eine Dateifreigabe einbinden, die in Azure Files gehostet wird. Wählen Sie diesen Ansatz, wenn Sie Abhängigkeiten oder Artefakte von Ihrem Anwendungscode entkoppeln möchten.

Zunächst müssen Sie ein Azure-Speicherkonto erstellen. Im Konto müssen Sie auch eine Dateifreigabe in Azure Files erstellen. Befolgen Sie diese Anleitung, um diese Ressourcen zu erstellen

Nachdem Sie das Speicherkonto und die Dateifreigabe erstellt haben, verwenden Sie den Befehl az webapp config storage-account add, um die Dateifreigabe an Ihre Funktions-App anzufügen, wie im folgenden Beispiel gezeigt.

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 Wert
custom-id Eine beliebige eindeutige Zeichenfolge
storage-type Derzeit wird nur AzureFiles unterstützt
share-name Bereits vorhandene Freigabe
mount-path Pfad, unter dem innerhalb des Containers auf die Freigabe zugegriffen werden kann. Der Wert muss das Format /dir-name aufweisen und kann nicht mit /home beginnen

Weitere Befehle zum Ändern/Löschen der Dateifreigabekonfiguration finden Sie hier

Hochladen der Abhängigkeiten in Azure Files

Eine Möglichkeit zum Hochladen Ihrer Abhängigkeit in Azure Files ist über das Azure-Portal. Anweisungen zum Hochladen von Abhängigkeiten über das Portal finden Sie in diesem Leitfaden. Weitere Optionen zum Hochladen Ihrer Abhängigkeiten in Azure Files sind Azure CLI und PowerShell.

Zugreifen auf die Abhängigkeiten in Ihrem Code

Nachdem Ihre Abhängigkeiten in die Dateifreigabe hochgeladen wurden, können Sie über Ihren Code auf die Abhängigkeiten zugreifen. Die bereitgestellte Freigabe ist unter dem angegebenen Bereitstellungspfad verfügbar, z. B. /path/to/mount. Sie können mithilfe von Dateisystem-APIs auf das Zielverzeichnis zugreifen.

Das folgende Beispiel zeigt den HTTP-Triggercode, der auf die ffmpeg-Bibliothek zugreift, die in einer bereitgestellten Dateifreigabe gespeichert ist.

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)

Wenn Sie diesen Code für eine Funktions-App in Azure bereitstellen, müssen Sie eine App-Einstellung mit dem Schlüsselnamen FILE_SHARE_MOUNT_PATH und dem Wert des bereitgestellten Dateifreigabepfads erstellen, in diesem Beispiel /azure-files-share. Zum lokalen Debuggen müssen Sie FILE_SHARE_MOUNT_PATH mit dem Dateipfad auffüllen, in dem Ihre Abhängigkeiten auf Ihrem lokalen Computer gespeichert sind. Hier ist ein Beispiel, das mit local.settings.json auf FILE_SHARE_MOUNT_PATH festgelegt werden soll:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "FILE_SHARE_MOUNT_PATH" : "PATH_TO_LOCAL_FFMPEG_DIR"
  }
}

Nächste Schritte