Скопируйте большой двоичный объект из одной учетной записи хранения в другую с помощью функции Azure, написанной на Java

Я пишу функцию Azure на Java для копирования больших двоичных объектов между учетными записями хранения в одном клиенте без предварительной загрузки их в память. Я наткнулся на этот пост , в котором предлагалось использовать для этого AzCopy. Я скачал двоичный файл AzCopy из этого места и добавил его в корневой каталог функции перед созданием образа Docker. Ниже приведен мой код для вызова двоичного файла azcopy в Java, он отлично работает локально, но ничего не делает, когда функция развернута в Kubernetes. Не уверен, проблема ли это в двоичном файле или в среде, поскольку функция развертывается в Kubernets, а не в функциональном приложении.

Источником и местом назначения являются URL-адреса с временными токенами SAS.

ProcessBuilder processBuilder = new ProcessBuilder(azCopyBinaryLocation, "copy", source, destination);
    Process process = processBuilder.start();

    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;

    StringBuilder sb = new StringBuilder();

    while ((line = br.readLine()) != null) {
        sb.append("\n");
        sb.append(line);
    }

    context.getLogger().info("Logs: "+sb.toString()); //print logs in console

Я не уверен, что я на правильном пути, например, следует ли мне использовать azcopy или вместо этого попытаться использовать Java SDK, для SDK я не уверен, загружает ли blob APIs содержимое в память перед копированием в другую учетную запись хранения, если это так, то это будет быть медленным и требовательным к памяти, чего я хочу избежать любой ценой. Я ищу вариант, который использует магистраль Azure так же, как azcopy.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я использовал метод copyfromurl для копирования файла из одного хранилища в другое.

Ниже приведенный код работал у меня.

Я использовал то же имя в качестве имени файла назначения. если вы хотите изменить имя файла, вы можете использовать любое имя файла.

При использовании getBlobUrl в storage account => Configuration должно быть включено разрешение анонимного доступа к BLOB-объектам. если нет, нужно использовать SAS_url.

package com.function;

import java.util.*;
import com.microsoft.azure.functions.annotation.*;
import com.azure.storage.blob.BlobClient;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.microsoft.azure.functions.*;
import com.azure.identity.*;;

public class HttpTriggerJava1 {
    @FunctionName("HttpTriggerJava1")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");
         
        
        //Source Account
        String sourceContainerName = "source";
        String blobName = "oldfile.txt";


        BlobServiceClient sourceServiceClient = new BlobServiceClientBuilder().credential(new DefaultAzureCredentialBuilder().build()).endpoint("https://storage29aug.blob.core.windows.net").buildClient();

        BlobContainerClient sourceContainerClient = sourceServiceClient.getBlobContainerClient(sourceContainerName);

        BlobClient sourceBlobClient = sourceContainerClient.getBlobClient(blobName);


        //Destination Account
        String destinationContainerName = "destination";

        BlobServiceClient destinationServiceClient = new BlobServiceClientBuilder().credential(new DefaultAzureCredentialBuilder().build()).endpoint("https://destinationstorage29aug.blob.core.windows.net").buildClient();

        BlobContainerClient destinationContainerClient = destinationServiceClient.getBlobContainerClient(destinationContainerName);

        BlobClient destinatiBlobClient = destinationContainerClient.getBlobClient(blobName);

        destinatiBlobClient.copyFromUrl(sourceBlobClient.getBlobUrl());
        
        return request.createResponseBuilder(HttpStatus.OK).body("blob copied successfully").build();
    }
}

pom.xml:

<dependencies>
        <dependency>
            <groupId>com.microsoft.azure.functions</groupId>
            <artifactId>azure-functions-java-library</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-storage-blob</artifactId>
            <version>12.27.1</version>
        </dependency>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-identity</artifactId>
            <version>1.13.2</version>
        </dependency>
</dependencies>

OUTPUT:

Спасибо @vivek. Пробовали ли вы это с большими файлами, сколько времени занимает копирование больших файлов (например, 1 гигабайт) между учетными записями хранения?

Sandy 31.08.2024 07:50

@Сэнди, я еще не пробовал работать с большим файлом.

Vivek Vaibhav Shandilya 31.08.2024 08:07
Ответ принят как подходящий

Проблема заключалась в том, что AZCOPY_LOG_LOCATION и AZCOPY_JOB_PLAN_LOCATION отсутствовали в переменных среды, установка необходимых переменных через значение docker ENV устранила проблему.

Окончательный файл докера выглядит так

# Use a base image with the necessary dependencies
FROM mcr.microsoft.com/azure-functions/java:4-java17

# Install dependencies for azcopy
RUN apt-get update && apt-get install -y wget

# Download and install azcopy
RUN wget https://aka.ms/downloadazcopy-v10-linux -O azcopy.tar.gz && \
    tar -xvf azcopy.tar.gz && \
    cp ./azcopy_linux_amd64_*/azcopy /usr/bin/ && \
    chmod +x /usr/bin/azcopy && \
    rm -rf azcopy.tar.gz azcopy_linux_amd64_*

COPY ./target ./package

RUN mkdir -p /home/site/wwwroot && \
    cd /package/azure-functions/ && \
    cd $(ls -d */|head -n 1) && \
    cp -a . /home/site/wwwroot && \
    groupadd appuser -g 2000 && \
    useradd -r -M -s /sbin/nologin -g appuser -c appuser appuser -u 1000 && \
    mkdir -p /home/appuser/.local && \
    chown -R appuser:appuser /azure-functions-host && \
    chown -R appuser:appuser /home/appuser/.local

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
    ASPNETCORE_URLS=http://+:8080 \
    FUNCTIONS_WORKER_RUNTIME=java \
    JAVA_OPTS = "--add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED"

RUN mkdir -p /home/site/wwwroot/log_files && \
    chown -R appuser:appuser /home/site/wwwroot/log_files && \
    chmod 777 /home/site/wwwroot/log_files

ENV AZCOPY_LOG_LOCATION=/home/site/wwwroot/log_files
ENV AZCOPY_JOB_PLAN_LOCATION=/home/site/wwwroot/log_files

# Switch to the user
USER appuser

# Expose the port
EXPOSE 8080

и Java-код

File azCopyPath = new File("/usr/bin/azcopy");

ProcessBuilder processBuilder = new ProcessBuilder(azCopyPath.getAbsolutePath(), "copy", sourceFileSasUrl, destinationFileSasUrl);
Process process = processBuilder.start();

Другие вопросы по теме