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"
}
}