Compartir por


Ajuste del rendimiento para cargas y descargas con Python

Cuando una aplicación transfiere datos mediante la biblioteca cliente de Azure Storage para Python, hay varios factores que pueden afectar a la velocidad, al uso de memoria e incluso a la ejecución correcta o incorrecta de la solicitud. Para maximizar el rendimiento y la confiabilidad de las transferencias de datos, es importante ser proactivo en la configuración de las opciones de transferencia de la biblioteca cliente en función del entorno en el que se ejecuta la aplicación.

En este artículo se describen varias consideraciones para optimizar las opciones de transferencia de datos. Cuando se ajusta correctamente, la biblioteca cliente puede distribuir eficazmente los datos entre varias solicitudes, lo que puede dar lugar a mejorar la velocidad de operación, el uso de memoria y la estabilidad de la red.

Ajuste del rendimiento de los cargas

El ajuste correcto de las opciones de transferencia de datos es clave para obtener un rendimiento confiable para las cargas. Las transferencias de almacenamiento se dividen en varias subtransferencias en función de los valores de estos argumentos. El tamaño máximo de transferencia admitido varía según la operación y la versión del servicio, por lo que asegúrese de consultar la documentación para determinar los límites. Para más información sobre los límites de tamaño de transferencia para Blob Storage, consulte Objetivos de escalabilidad de Blob Storage.

Establecimiento de opciones de transferencia para cargas

Se pueden ajustar los siguientes argumentos en función de las necesidades de la aplicación:

  • max_single_put_size: tamaño máximo de un blob que se va a cargar con una sola solicitud. El valor predeterminado es 64 MiB.
  • max_block_size: longitud máxima de una transferencia en bytes al cargar un blob en bloques en fragmentos. El valor predeterminado es 4 MiB.
  • max_concurrency: número máximo de subtransferencias que se pueden usar en paralelo.

Nota

Las bibliotecas cliente usarán los valores predeterminados para cada opción de transferencia de datos, si no se proporciona. Estos valores predeterminados suelen tener un buen rendimiento en un entorno de centro de datos, pero es probable que no sean adecuados para entornos de consumidores domésticos. Un ajuste deficiente de opciones de transferencia de datos puede dar lugar a operaciones excesivamente largas e incluso tiempos de espera de solicitud. Es mejor ser proactivo al probar los valores y ajustarlos en función de las necesidades de la aplicación y el entorno.

max_single_put_size

El argumento max_single_put_size es el tamaño máximo de blob en bytes para una sola carga de solicitud. Si el tamaño del blob es menor o igual que max_single_put_size, el blob se carga con una sola solicitud Put Blob. Si el tamaño del blob es mayor que max_single_put_size, o si se desconoce el tamaño del blob, el blob se carga en fragmentos mediante una serie de llamadas Put Block seguidas de Put Block List.

Es importante tener en cuenta que el valor que especifique para max_block_size no limite el valor que defina para max_single_put_size. El argumento max_single_put_size define una limitación de tamaño independiente para que una solicitud realice toda la operación a la vez, sin subtransfers. A menudo, se desea que max_single_put_size sea al menos tan grande como el valor que defina para max_block_size, si no mayor. Este enfoque puede ser más eficaz en función del tamaño de la transferencia de datos, ya que la transferencia se completa con una única solicitud y evita la sobrecarga de varias solicitudes.

Si no está seguro de qué valor es mejor para su situación, una opción segura es establecer max_single_put_size en el mismo valor que se usa para max_block_size.

max_block_size

El argumento max_block_size es la longitud máxima de una transferencia en bytes al cargar un blob en bloques en fragmentos. Como se mencionó anteriormente, este valor no limita a max_single_put_size, que puede ser mayor que max_block_size.

Para que los datos se muevan de forma eficaz, es posible que las bibliotecas cliente no siempre alcancen el valor de max_block_size en cada transferencia. En función de la operación, el valor máximo admitido para el tamaño de transferencia puede variar. Para más información sobre los límites de tamaño de transferencia para Blob Storage, consulte el gráfico en Objetivos de escalabilidad de Blob Storage.

Ejemplo de código

En el ejemplo de código siguiente, se muestra cómo especificar opciones de transferencia de datos al crear un objeto BlobClient y cómo cargar datos mediante ese objeto de cliente. Los valores proporcionados en este ejemplo no están diseñados para ser una recomendación. Para ajustar correctamente estos valores, debe tener en cuenta las necesidades específicas de la aplicación.

def upload_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for upload
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_block_size=1024*1024*4, # 4 MiB
        max_single_put_size=1024*1024*8 # 8 MiB
    )
    
    with open(file=os.path.join(r'file_path', blob_name), mode="rb") as data:
        blob_client = blob_client.upload_blob(data=data, overwrite=True, max_concurrency=2)

En este ejemplo, establecemos el número de trabajos de transferencia en paralelo en 2 mediante el argumento max_concurrency en la llamada de método. Esta configuración abre hasta dos conexiones simultáneamente, lo que permite que la carga se produzca en paralelo. Durante la creación de instancias de cliente, establecemos el argumento max_single_put_size en 8 MiB. Si el tamaño del blob es inferior a 8 MiB, solo se necesita una única solicitud para completar la operación de carga. Si el tamaño del blob es mayor que 8 MiB, el blob se carga en fragmentos con un tamaño máximo de fragmento de 4 MiB, tal y como establece el argumento max_block_size.

Consideraciones de rendimiento para las cargas

Durante una carga, las bibliotecas cliente de Storage dividen un flujo de carga determinado en varias subcargas en función de las opciones de configuración definidas durante la construcción del cliente. Cada carga secundaria tiene su propia llamada dedicada a la operación REST. Para un objeto BlobClient, esta operación es Put Block. La biblioteca cliente de Storage administra estas operaciones REST en paralelo (según las opciones de transferencia) para llevar a cabo la carga completa.

Puede obtener información sobre cómo la biblioteca cliente controla el almacenamiento en búfer en las secciones siguientes.

Nota

Los blobs en bloques tienen un número máximo de bloques de 50 000 bloques. El tamaño máximo del blob en bloques, por tanto, es de 50 000 veces max_block_size.

Almacenamiento en búfer durante las cargas

La capa REST de Storage no admite reanudar una operación de carga REST donde se dejó; las transferencias individuales se completan o se pierden. Para garantizar la resistencia de las cargas de flujos, las bibliotecas cliente de Storage almacenan en búfer los datos de cada llamada REST individual antes de iniciar la carga. Además de las limitaciones de velocidad de la red, este comportamiento de almacenamiento en búfer es una razón para considerar un valor más pequeño para max_block_size, incluso cuando se carga en secuencia. Al disminuir el valor de max_block_size, se reduce la cantidad máxima de datos que se almacenan en búfer en cada solicitud y cada reintento de una solicitud con errores. Si experimenta tiempos de espera frecuentes durante las transferencias de datos de un tamaño determinado, al reducir el valor de max_block_size, se reduce el tiempo de almacenamiento en búfer y puede dar lugar a un mejor rendimiento.

De forma predeterminada, el SDK almacena en búfer los datos de max_block_size bytes por solicitud de subcarga simultánea, pero el uso de memoria puede limitarse a 4 MiB por solicitud si se cumplen las condiciones siguientes:

  • El argumento max_block_size debe ser mayor que min_large_block_upload_threshold. El argumento min_large_block_upload_threshold se puede definir durante la creación de instancias del cliente y es el tamaño mínimo del fragmento en bytes necesarios para usar el algoritmo eficaz de memoria. El argumento min_large_block_upload_threshold tiene 4*1024*1024 + 1 como valor predeterminado.
  • La secuencia proporcionada debe poder buscarse. Una secuencia que permite búsquedas es una secuencia que admite la consulta y modificación de la posición actual dentro de una secuencia.
  • El blob debe ser un blob en bloques.

Aunque esta estrategia se aplica en la mayoría de las situaciones, todavía es posible que se produzca más almacenamiento en búfer si el código usa otras características de la biblioteca cliente que requieren almacenamiento en búfer.

Ajuste del rendimiento de las descargas

El ajuste correcto de las opciones de transferencia de datos es clave para obtener un rendimiento confiable para las descargas. Las transferencias de almacenamiento se dividen en varias subtransferencias en función de los valores de estos argumentos.

Establecimiento de opciones de transferencia para descargas

Se pueden ajustar los siguientes argumentos en función de las necesidades de la aplicación:

  • max_chunk_get_size: tamaño máximo de fragmento que se usa para descargar un blob. El valor predeterminado es 4 MiB.
  • max_concurrency: número máximo de subtransferencias que se pueden usar en paralelo.
  • max_single_get_size: tamaño máximo de un blob que se va a descargar en una sola llamada. Si el tamaño total del blob supera max_single_get_size, el resto de los datos del blob se descarga en fragmentos. El valor predeterminado es 32 MB.

Ejemplo de código

def download_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for download
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_single_get_size=1024*1024*32, # 32 MiB
        max_chunk_get_size=1024*1024*4 # 4 MiB
    )

    with open(file=os.path.join(r'file_path', 'file_name'), mode="wb") as sample_blob:
        download_stream = blob_client.download_blob(max_concurrency=2)
        sample_blob.write(download_stream.readall())

Consideraciones de rendimiento para las descargas

Durante una descarga, las bibliotecas cliente de Storage dividen una descarga determinada en varias subdescargas en función de las opciones de configuración definidas durante la construcción del cliente. Cada descarga secundaria tiene su propia llamada dedicada a la operación REST. En función de las opciones de transferencia, las bibliotecas cliente administran estas operaciones REST en paralelo para llevar a cabo la descarga completa.

max_single_get_size para descargas

Durante una descarga, las bibliotecas cliente de Storage realizan una solicitud de intervalo de descarga con max_single_get_size antes de hacer nada más. Durante esta solicitud de descarga inicial, las bibliotecas cliente conocen el tamaño total del recurso. Si la solicitud inicial descargó correctamente todo el contenido, se completa la operación. De lo contrario, las bibliotecas cliente siguen realizando solicitudes de intervalo hasta el valor de max_chunk_get_size hasta que se lleve a cabo la descarga completa.

Pasos siguientes