Кэширование ответа на запрос в python

Я пишу несколько бэкэнд-скриптов на python, которые должны быть связаны с веб-интерфейсом, использующим django.

Веб-приложение позволяет просматривать слои, поступающие из различных веб-сервисов. В рамках своих задач я разработал инструмент, который запрашивает данные о высоте с геосервера (сервис WCS), а затем, основываясь на предыдущей линии, нарисованной пользователем во фронт-энде, может генерировать поперечный срез базовых данных.

Короче говоря, когда пользователь проводит линию по слою, а затем нажимает кнопку draw-profile, моя функция запрашивает данные, пересекает линию по связанному растру/слою и возвращает рисунок на фронт-енд.

Проблема такого подхода заключается в том, что каждый раз, когда пользователь нажимает кнопку draw-profile, запрос выполняется заново, что занимает некоторое время.

Когда запрос выполнен, данные сохраняются в DTM object (класс, который я сделал) в self.raster свойстве.

Упрощенная версия функции, запрашивающей данные, показана ниже.

def get_dtm_from_wcs100(
    self,
    raster_source: str = "YY",
    layer: str = "XX",
    format: str = "image/tiff",
    version: str = "1.0.0",
    resx: int = 1,
    resy: int = 1,
) -> None:
    """
    Get raster and metadata from a WCS service

    Parameters
    ----------
    raster_source : str, optional
        URL of WCS service. The default is "YY" which is the company geoserver
    layer : str, optional
        CoverageID. The default is 'XX'.
    format : str, optional
        File type of the request. The default is 'image/tiff'.
    version : str, optional
        Version of the WCS protocol. The default is "1.0.0".
    resx : int, optional
        Pixel resolution in x-coordinate. The default is 1.
    resy : int, optional
        Pixel resolution in y-coordinate. The default is 1.

    Returns
    -------
    None.

    """

    try:
        # Connect to WCS and try getting a coverage
        wcs = WebCoverageService(raster_source, version=version)
        response = wcs.getCoverage(
            identifier=layer,
            bbox=self.bbox,
            crs=self.epsg,
            format=format,
            resx=resx,
            resy=resy,
        )

    except Exception as e:
        raise Exception("An unexpected error has ocurred:", e)

    else:
        self._read_response(response)
        self._set_masked_raster()

При выполнении self._read_response(response) заполняется свойство self.raster (numpy array).

Знаете ли вы, что я могу сделать, чтобы как-то сохранить этот ответ и не вызывать его каждый раз, когда я хочу нарисовать профиль?

Вы можете использовать декоратор @cache из питоновского functools. https://docs.python.org/3/library/functools.html

Можно использовать службу кэширования памяти, например Memcached, Redis и т. д., и привязать сессию пользователя к кэшированной версии ответа от WebCoverageService.

Вы также можете сериализовать ответ (сопоставив его с пользовательской сессией) и хранить его локально.

Ваш подход будет зависеть от среды, в которой вы запускаете эту службу. Если ваш сервис работает в классической инфраструктуре виртуальных машин, например Amazon EC2, то локальный файловый кэш будет работать. Однако если вы работаете в Kubernetes, вам действительно следует изучить Memcached, Redis и т. д.

Вернуться на верх