<rmcreative>

RSS

Все заметки с тегом «cdn»

Можно уточнить:

    (1)
    (1)
  1. Yii 2 за балансировщиком нагрузки

    14 октября 2020

    Система asset-ов Yii 2 очень удобна. Можно расположить ресурсы в пакетах или ближе к исходникам и фреймворк при первом запросе на генерируемую PHP страницу скопирует их (или сделает симлинк) в нужное место.

    Пока экземпляр приложения один, всё работает замечательно, а вот когда появляется балансировщик, это уже не работает потому как запрос каждый раз уходит на разный сервер. Проблем тут несколько. Yii, чтобы избавить от залипания браузерного кеша, при выборе директории, в которую копируется ресурс, использует время изменения директории:

    $path = (is_file($path) ? dirname($path) : $path) . filemtime($path);
    return sprintf('%x', crc32($path . Yii::getVersion() . '|' . $this->linkAssets));

    На каждом экземпляре приложения время будет разным, поэтому ресурсы окажутся в разных директория и если HTML будет запрошен с одного сервера, а ресурсы с других, получим 404.

    Решается просто. В конфиге задаём hashCallback для компонента assetManager:

    'hashCallback' => static function ($path) {
        return hash('md4', $path);
    }

    Но до конца это проблему не решает. Теперь пути совпадают, но при первых запросах получается что в HTML прописан путь к ресурсу с другого сервера, а там ещё запросы не обрабатывались и такого ресурса нет. Опять 404.

    Бороться с этим можно несколькими способами. Первый сводится к тому, что ресурсы собираются на машине разработчика или билд-сервере и раскатываются вместе с приложением. Вариаций тут много:

    1. Отказаться от asset manager, использовать файлы в вебруте.
    2. Использовать webpack или другую систему сборки на node.
    3. Собирать ресурсы командой asset.

    Второй способ — сделать ресурсы общими. Здесь опять несколько вариаций:

    1. Использовать NFS чтобы сделать файловую систему ресурсов общей. Но это не очень быстро и надёжно.
    2. Использовать CDN. Например, ресурсы закинуть на S3 и раздавать оттуда. Заодно получим снижение нагрузки на серверах приложений.

    Последний вариант делается при помощи пакета mikk150/yii2-asset-manager-flysystem. Ставим, настраиваем:

    'assetManager' => [
        'class' => mikk150\assetmanager\AssetManager::class,
        'basePath' => './',
        'baseUrl' => 'Базовый URL статического контента',
        'flySystem' => [
            'class' => creocoder\flysystem\AwsS3Filesystem::class,
            'host' => 'Хост статического контента',
            'key' => 'Ключик S3',
            'secret' => 'Secret S3',
            'region' => 'Регион S3',
            'version' => 'Версия файлов',
            'bucket' => 'Bucket',
            'prefix' => 'Путь к ресурсам' . '/assets',
        ],
    ],
    Комментировать