Dela via


Ta med beroenden eller bibliotek från tredje part till Azure Functions

I den här artikeln lär du dig att använda tredjepartsberoenden i dina funktionsappar. Exempel på tredjepartsberoenden är json-filer, binära filer och maskininlärningsmodeller.

I den här artikeln kan du se hur du:

  • Hämta beroenden via Functions Code-projekt
  • Hämta beroenden via montering av Azure Fileshare

Hämta beroenden från projektkatalogen

Ett av de enklaste sätten att ta in beroenden är att placera filerna/artefakten tillsammans med funktionsappkoden i Functions-projektkatalogstrukturen. Här är ett exempel på katalogexemplen i ett Python Functions-projekt:

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

Genom att placera beroendena i en mapp i funktionsappens projektkatalog distribueras mappen dependencies tillsammans med koden. Det innebär att funktionskoden kan komma åt beroendena i molnet via filsystem-API:et.

Komma åt beroendena i koden

Här är ett exempel för att komma åt och köra ffmpeg beroenden som placeras i <project_root>/ffmpeg_lib katalogen.

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)

Anteckning

Du kan behöva använda chmod för att ge Execute rättigheter till ffmpeg-binärfilen i en Linux-miljö

Ett av de enklaste sätten att ta in beroenden är att sätta ihop filerna/artefakten med funktionsappkoden i funktionsprojektkatalogstrukturen. Här är ett exempel på katalogexemplen i ett Java Functions-projekt:

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

För Java behöver du specifikt inkludera artefakterna i mappen build/target när du kopierar resurser. Här är ett exempel på hur du gör det i 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>
...

Genom att placera beroendena i en mapp i funktionsappens projektkatalog distribueras mappen dependencies tillsammans med koden. Det innebär att funktionskoden kan komma åt beroendena i molnet via filsystem-API:et.

Komma åt beroendena i koden

Här är ett exempel för att komma åt och köra ffmpeg beroenden som placeras i <project_root>/ffmpeg_lib katalogen.

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

    }

Anteckning

För att det här kodfragmentet ska fungera i Azure måste du ange en anpassad programinställning för "BASE_PATH" med värdet "/home/site/wwwroot"

Ta med beroenden genom att montera en filresurs

När du kör din funktionsapp i Linux finns det ett annat sätt att ta in beroenden från tredje part. Med Functions kan du montera en filresurs i Azure Files. Överväg den här metoden när du vill frikoppla beroenden eller artefakter från programkoden.

Först måste du skapa ett Azure Storage-konto. I kontot måste du också skapa en filresurs i Azure-filer. Följ den här guiden om du vill skapa dessa resurser

När du har skapat lagringskontot och filresursen använder du kommandot az webapp config storage-account add för att bifoga filresursen till funktionsappen, som du ser i följande exempel.

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>
Flagga Värde
anpassat ID Alla unika strängar
lagringstyp Endast AzureFiles stöds för närvarande
resursnamn Befintlig resurs
mount-path Sökväg där resursen ska vara tillgänglig i containern. Värdet måste ha formatet /dir-name och det kan inte börja med /home

Fler kommandon för att ändra/ta bort filresurskonfigurationen finns här

Ladda upp beroendena till Azure Files

Ett alternativ för att ladda upp ditt beroende till Azure Files är via Azure Portal. I den här guiden finns instruktioner för att ladda upp beroenden med hjälp av portalen. Andra alternativ för att ladda upp dina beroenden till Azure Files är via Azure CLI och PowerShell.

Komma åt beroendena i koden

När dina beroenden har laddats upp i filresursen kan du komma åt beroendena från koden. Den monterade resursen är tillgänglig på den angivna monteringssökvägen, till exempel /path/to/mount. Du kan komma åt målkatalogen med hjälp av filsystem-API:er.

I följande exempel visas HTTP-utlösarkod ffmpeg som har åtkomst till biblioteket, som lagras i en monterad filresurs.

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)

När du distribuerar den här koden till en funktionsapp i Azure måste du skapa en appinställning med nyckelnamnet FILE_SHARE_MOUNT_PATH och värdet för den monterade filresurssökvägen, som i det här exemplet är /azure-files-share. Om du vill utföra lokal felsökning måste du fylla FILE_SHARE_MOUNT_PATH i med filsökvägen där dina beroenden lagras på den lokala datorn. Här är ett exempel som du kan ange FILE_SHARE_MOUNT_PATH med hjälp av local.settings.json:

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

Nästa steg