Przenoszenie zależności lub biblioteki innych firm do Azure Functions

W tym artykule nauczysz się wprowadzać zależności innych firm do aplikacji funkcji. Przykłady zależności innych firm to pliki json, pliki binarne i modele uczenia maszynowego.

W tym artykule omówiono sposób wykonywania następujących zadań:

  • Wprowadzanie zależności za pośrednictwem projektu kodu usługi Functions
  • Wprowadzanie zależności za pośrednictwem instalowania udziału plików platformy Azure

Wprowadzanie zależności z katalogu projektu

Jednym z najprostszych sposobów na wprowadzenie zależności jest umieszczenie plików/artefaktów razem z kodem aplikacji funkcji w strukturze katalogów projektu usługi Functions. Oto przykład przykładowy katalog w projekcie funkcji języka Python:

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

Umieszczając zależności w folderze wewnątrz katalogu projektu aplikacji funkcji, folder zależności zostanie wdrożony wraz z kodem. W związku z tym kod funkcji może uzyskiwać dostęp do zależności w chmurze za pośrednictwem interfejsu API systemu plików.

Uzyskiwanie dostępu do zależności w kodzie

Oto przykład uzyskiwania dostępu do katalogu i wykonywania ffmpeg zależności, która jest umieszczana w <project_root>/ffmpeg_lib katalogu.

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)

Uwaga

Może być konieczne podanie chmodExecute praw do pliku binarnego ffmpeg w środowisku systemu Linux

Jednym z najprostszych sposobów umieszczenia zależności jest umieszczenie plików/artefaktów razem z kodem aplikacji funkcji w strukturze katalogów projektów funkcji. Oto przykład przykładowy katalog w projekcie funkcji Języka Java:

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

W przypadku języka Java należy w szczególności uwzględnić artefakty w folderze build/target podczas kopiowania zasobów. Oto przykład dotyczący tego, jak to zrobić w narzędziu 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>
...

Umieszczając zależności w folderze wewnątrz katalogu projektu aplikacji funkcji, folder zależności zostanie wdrożony wraz z kodem. W związku z tym kod funkcji może uzyskiwać dostęp do zależności w chmurze za pośrednictwem interfejsu API systemu plików.

Uzyskiwanie dostępu do zależności w kodzie

Oto przykład uzyskiwania dostępu do katalogu i wykonywania ffmpeg zależności, która jest umieszczana w <project_root>/ffmpeg_lib katalogu.

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

    }

Uwaga

Aby uzyskać ten fragment kodu do pracy na platformie Azure, należy określić niestandardowe ustawienie aplikacji "BASE_PATH" z wartością "/home/site/wwwroot"

Przenoszenie zależności przez zainstalowanie udziału plików

Podczas uruchamiania aplikacji funkcji w systemie Linux istnieje inny sposób na wprowadzenie zależności innych firm. Usługa Functions umożliwia zainstalowanie udziału plików hostowanego w Azure Files. Rozważ to podejście, jeśli chcesz rozdzielić zależności lub artefakty z kodu aplikacji.

Najpierw należy utworzyć konto usługi Azure Storage. Na koncie należy również utworzyć udział plików w usłudze Azure Files. Aby utworzyć te zasoby, postępuj zgodnie z tym przewodnikiem

Po utworzeniu konta magazynu i udziału plików użyj polecenia az webapp config storage-account add , aby dołączyć udział plików do aplikacji funkcji, jak pokazano w poniższym przykładzie.

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>
Flaga Wartość
identyfikator niestandardowy Dowolny unikatowy ciąg
typ magazynu Obecnie obsługiwane są tylko pliki AzureFiles
nazwa udziału Istniejący udział
ścieżka instalacji Ścieżka, w której udział będzie dostępny wewnątrz kontenera. Wartość musi być formatem /dir-name i nie może zaczynać się od /home

Więcej poleceń do modyfikowania/usuwania konfiguracji udziału plików można znaleźć tutaj

Przekazywanie zależności do Azure Files

Jedną z opcji przekazywania zależności do Azure Files jest Azure Portal. Zapoznaj się z tym przewodnikiem , aby uzyskać instrukcje dotyczące przekazywania zależności przy użyciu portalu. Inne opcje przekazywania zależności do Azure Files to interfejs wiersza polecenia platformy Azure i program PowerShell.

Uzyskiwanie dostępu do zależności w kodzie

Po przekazaniu zależności w udziale plików można uzyskać dostęp do zależności z poziomu kodu. Zainstalowany udział jest dostępny w określonej ścieżce instalacji, takiej jak /path/to/mount. Dostęp do katalogu docelowego można uzyskać za pomocą interfejsów API systemu plików.

W poniższym przykładzie przedstawiono kod wyzwalacza HTTP, który uzyskuje dostęp do ffmpeg biblioteki, która jest przechowywana w zainstalowanym udziale plików.

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)

Podczas wdrażania tego kodu w aplikacji funkcji na platformie Azure należy utworzyć ustawienie aplikacji z nazwą FILE_SHARE_MOUNT_PATH klucza i wartością zainstalowanej ścieżki udziału plików, która w tym przykładzie to /azure-files-share. Aby przeprowadzić lokalne debugowanie, musisz wypełnić FILE_SHARE_MOUNT_PATH ścieżkę pliku, w której zależności są przechowywane na komputerze lokalnym. Oto przykład ustawiania FILE_SHARE_MOUNT_PATH przy użyciu polecenia local.settings.json:

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

Następne kroki