Skip to content
Anton Kiyatkin edited this page Dec 11, 2016 · 18 revisions

Реализация параметров окружения посетителя с поддержкой public кэширования

Под окружением понимается набор параметров определённых для текущего посетителя сайта, например

  • lang - язык сайта,
  • region - регион посетителя
  • theme - тема сайта
  • zone - часовой пояс.
  • default - true - значит всё окружение определёно по умолчанию и может кэшироваться на промежуточных близких серверах

Даже если параметр окружения (theme) будет изменён пользователем и закэширован на прокси сервере. При попытке показать этот кэш для другого пользователя сработает location.reload(true) до загрузки основного содержания из-за различия имени окружения в cookie и в получшенном кэше. На самом деле при любом изменении дефолтных параметров окружения появится флаг default:false, что сделает кэш этого пользователя приватным Cache-control:private и кэш не будет сохраняться на промежуточных серверах для этого пользователя.

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

По смыслу окружение похоже на локаль в php.

Целесообразность хранения параметра в окружении определяется следующими рассуждениями:

  1. Всё что находится в окружении определяет содержание страницы, которая попадает в кэш, как пользователя, так и провайдера или прокси-серверов, тем самым обеспечивая быструю загрузку страницы.
  2. При первом посещении страницы может показаться кэш содержания по окружению другого пользователя, должна быть значительная вероятность, что этот кэш подходит и для нового пользователя (язык, регион, часовой пояс) если это не так, будет очень быстрый location.reload(true) в head без ожидания загрузки всей страницы, но вероятность такого исхода нужно минимизировать. Если же пользователь явно изменил определённые по умолчанию значения будет использоваться Cache-control:private означающий, что данный кэш не подойдёт для других посетителей.
  3. В окружение хранятся постоянные для пользователя константы определяющие содержания многих страниц сайта.
  4. От обратного если параметр не будет хранится в окружении он будет запрещать содание public кэша для страницы, так как будет определятся динамически и кэш.
  5. Параметр окружения для пользователя меняется лишь в исключительной ситуация, изменение требует неприятной перезагрузки location.reload(true) на каждой странице, которая была посещена, и на которую пользователь зайдёт снова после изменения. И изменение окружения запрещает использовать CDN для этого пользователя и делает его кэш приватным.
  6. Для каждого набора будет создаваться отдельное имя и умножение параметров приведёт к безграничному росту имён, так как для каждой комбинации генерируется своё имя, которое сохраняется с параметрами в папке ~.env/ и устанавливается в cookie.

Имя окружения

Каждому набору параметров в окружении даётся какое-то сокращённое имя. Например окружение blabla может содержать в себе информацию и о всех параметрах.

Серверная часть канонического адреса попадает в локальный кэш с заголовками Etag и modified. Имя окружения попадает в Etag. Отдельные параметры из окружения или всё имя окружения указывается в условиях кэширования Access::cache Cache::exec программистом в зависимых скриптах.

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

Имя окружения хранится в cookie. -env=bla Если его нет, определяется автоматически. Если есть, будет использоваться установленное.

Обновление локального кэша

Если страница содержит заголовки кэширования public изменение окружения не обновит локальный кэш.

При посещении страницы, содержание которой берётся из локального кэша, скрипт сравнивает имя окружения собранной страницы с именем окружения хранящегося в cookie и если они разные выполняется location.reload(true);. Если посетитель перейдёт на новую страницу и снова обновит страницу и получит локальный старый кэш reload сработает снова. При обновлении страницы со старым Etag c сервера придёт новый Etag и новый ответ попадёт в локальный кэш. Повторный заход пользователя на страницу не потребует вызова reload, так как cookie окружения совпадёт с окружением сгенерированной страницы. Подробней про Etag

Обновление локального кэша ресурсов

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

Интерфейс доступа к параметрам окружения по имени окружения используется только в шаблонах html и шаблонах адресов до данных изменения адреса изменяет кэш слоя. {~env.region}, {~env.lang}

Страница не зависит от окружения

Кэш страницы с новым окржением заменяет кэш старой страницы со старым окружением. Серверный кэш отдельных слоёв определяется отдельными параметрами и вслепую для всех окружений не делается.

Другим словами везде, где кэш привязан к адресу, теперь же нужно учитывать, что адрес не идентифицирует содержание и нужно учитывать имя текущего окружения Env::name(), а лучше вообще кэш на сервере не привзяывать к адресу страницы, а находить более точные индетификации включая данные из окружения.

Параметры окружения

Управляются по логике infrajs/mark по адресу /-env/?mark=sdw:lang=eng. Так как проверка устанавливаемых значений происходит на сервере, клиент не может полагаться, что значение установится.

/-env/?mark=sdw:lang=eng установит новый cookie если значение применится и возвращает все параметры.

На клиенте после изменения запускается check(); Env.get(name) возвращает актуальное значение параметра и зависимые слои обновляются.

Для определения нового параметра

Нужно определить функцию определения значения по умолчанию. Например, новый параметр region и вот функция, которая его определяет.

Env::add('region', function () {
  return 'samara';
}, function ($newval) {
  return in_array($newval, array('togliatti','samara'));
});

Расширение infrajs/env по моим общей реализации предоставляет стандарт наименования параметров

Нужно определить функцию проверки параметра устанавливаемого пользователем Если новое значение проверку не проходит текущее значение не меняется.

Как получить красивое имя для окружения

  1. В папке с метками ~.env/ создаётся файл с правильным именем. В оригинальном файле даляются все параметры и остаётся только строчка с новым правильным именем для метки взамен оригинального.

CDN

Теоретически использование CDN не исключается, из расчёта что CDN находится в том же регионе и окружение определённое для него подойдёт большинству посетителей с большой вероятностью и CDN и будет тем самым проксирующим public сервером, до тех пор пока пользователь не изменит своё окружение и тогда за документом страницы должно сработать прямое обращение, а остальные ресурсы могут продолжать грузится с CDN. Но вот если location.reload(true) продолжит забирать страницу с CDN это приведёт к зависанию страницы. Защиты от зависания нет, нужно тестировать работу CDN и проверять будет ли запрос к реальному серверу при location.reload(true). И возможно автор не совсем корректно представляет работу CDN (сеть по доставки контента) по этому только теория.

Clone this wiki locally