- 21, Oct 2024
- #1
Сценарий: у нас есть страница конфигурации в Tridion, иногда на производственных серверах появляется ошибка, что страница конфигурации не опубликована, это означает, что ее нет ни в кэше DD4T, ни в брокере. Мы используем DD4T 2.2 и SDL Web 8.5.
Выводы: Ошибка возникает ровно в одно и то же время (5 минут, как ни странно, это также продолжительность кэша DD4T), затем исчезает, и кажется, что все работает нормально. Когда я просматривал код для фабрики страниц DD4T, он в основном пытается найти страницу в кеше DD4T, и если ее нет в кеше, он извлекает страницу от брокера, и если он находит страницу, то сохраняет ее в кеше DD4T, поэтому в следующий раз он будет обслуживать страницу только из кэша DD4T. Есть еще одна вещь, например, если страница не находится ни в кеше, ни в брокере, тогда она сохраняет страницу в кеше с заголовком страницы «DD4T-Special-Value-PageNotFound», поэтому в следующий раз, если мы посетим любую страницу и если страница будет в кэше, но с заголовком страницы «DD4T-Special-Value-PageNotFound», тогда он напрямую вернет значение null из самого кэша. И это будет происходить до истечения срока действия кэша, установленного в файле конфигурации. Таким образом, в основном в первый раз, если страница не находится ни в Cache, ни в Broker, DD4T устанавливает этот специальный заголовок страницы и сохраняет такие страницы в Cache, поэтому в следующий раз он будет напрямую возвращать ноль из самого Cache. (Поправьте меня, если я ошибаюсь).
Вот что я получил на странице DD4T Factry Method:
В нашем случае, как и в случае с фабрикой страниц, мы получаем ноль ровно в течение 5 минут (продолжительность кэша DD4T), я предполагаю, что заголовок страницы установлен на этот заголовок специальной страницы DD4T, и мы получаем ошибку страницы конфигурации. Теперь большой вопрос: как? Я подозреваю, что, поскольку он использует PublicationId для генерации ключа кэша, а в некоторых особых случаях он не может разрешить идентификатор публикации, и именно поэтому для заголовка страницы установлено значение «DD4T-Special-Value-PageNotFound». Но поскольку он использует частную собственность класса DD4T FactoryBase «PublicationID», которая фактически установила его из PublicationReolver, я не знаю, как он не сможет решить эту проблему? Вот что мы получили в базовом классе DD4t Factory: Примечание. У нас есть собственный преобразователь публикаций, который разрешает PublicationID с использованием метода GetPublicationMapping класса DynamicMappingRetriever Tridion.ContentDelivery.DynamicContent. И мы добавили туда блокировку около 6 месяцев назад, чтобы исправить некоторые другие проблемы с потоками в сборке Tridion.
Для URL не найдено подходящей локализации
private Dictionary<string, string> LoadConfiguration() { var pubId = _publicationResolver.ResolvePublicationId(); _logger.Debug("about to load configuration page. Url: {0}".FormatString(URL)); var page = GetPage(URL); if (page == null) { _logger.Error("configuration page is not published. Url : {0}".FormatString(URL)); throw new Exception("configuration page not found. Url: {0}; Is the page published?".FormatString(URL)); }} public IPage GetPage(string url) { _logger.Debug("GetPage - Processing request for page: {0}", url); var currentUrl = _publicationResolver.GetBaseUri().AbsolutePath ; IPage page; if (_pageFactory.TryFindPage(Uri.EscapeUriString(currentUrl), out page)) { return page; } else return null; }
Я не уверен, возникла ли эта проблема после No Localization Fix или нет.
Итак, мы делаем это:
public IDictionary<string, string> RetrieveConfiguration()
{
var pubId = _publicationResolver.ResolvePublicationId();
var key = _cacheKeyFormat.FormatString(pubId);
var configuration = _cacheAgent.Load(key) as IDictionary<string, string>;
if (configuration == null)
{
configuration = LoadConfiguration();
if (configuration != null)
{
_cacheAgent.Store(key, _cacheRegion, configuration);
}
}
}
Где ResolvePublicationId — это метод нашего класса настраиваемого преобразователя публикаций.
Для получения конфигураций мы вызываем наш собственный PUblicationResolver, а в методе LoadConfiguration мы вызываем метод PageFctory TryFindPage для получения страницы, где она именно прерывается.
public int ResolvePublicationId()
{
return this.FindMapping().PublicationId;
}
Я не уверен, действительно ли пользовательский преобразователь публикаций вызывает проблему или нет, поскольку в идеале этого не должно быть, потому что метод TryFindPage pageFactory должен использовать свой собственный PublicationReolver для разрешения идентификатора публикации. Потому что это решается с Фабрики Базы.
Вот код LoadConfiguration: Где Url — это URL-адрес страницы конфигурации, а GetBaseURI — это метод нашего настраиваемого преобразователя публикаций, который возвращает базовый URI текущей публикации.
Я получил дополнительную информацию из предупреждений New Relic: