Русский
Русский
English
Статистика
Реклама

Metadata

Перевод DataHub универсальный инструмент поиска и обнаружения метаданных

28.09.2020 12:18:44 | Автор: admin

DataHub: универсальный инструмент поиска и обнаружения метаданных.


Как оператор крупнейшей в мире профессиональной сети и экономического графика, отдел данных LinkedIn постоянно работает над масштабированием своей инфраструктуры в соответствии с требованиями нашей постоянно растущей экосистемы больших данных. По мере роста объема и разнообразия данных специалистам по данным и инженерам становится все сложнее обнаруживать доступные активы данных, понимать их происхождение и предпринимать соответствующие действия на основе полученных данных. Чтобы помочь нам продолжить масштабировать производительность и вносить инновации в базу данных, мы создали универсальный инструмент поиска и обнаружения метаданных, DataHub.


Примечание редактора: с момента публикации этого сообщения в блоге, команда в феврале 2020 года открыла DataHub с исходным кодом. Подробнее о том, как открыть исходный код для платформы, можно узнать здесь.


Масштабирование метаданных


Чтобы повысить продуктивность группы данных LinkedIn, мы ранее разработали и открыли исходный код WhereHows центральное хранилище метаданных и портал для наборов данных. Тип хранимых метаданных включает как технические метаданные (например, местоположение, схемы, разделы, владение), так и метаданные процесса (например, происхождение, выполнение задания). WhereHows также имеет поисковую систему, которая помогает находить интересующие вас наборы данных.


С момента нашего первого выпуска WhereHows в 2016 году, в отрасли наблюдается растущий интерес к повышению продуктивности специалистов по обработке данных с помощью метаданных. Например, инструменты, разработанные в этой области, включают Dataportal AirBnb, Databook Uber, Metacat Netflix, Amundsen Lyft и совсем недавно Data Catalog от Google. В LinkedIn мы также были заняты расширением объема сбора метаданных для новых вариантов использования при сохранении конфиденциальности. Однако мы пришли к выводу, что у WhereHows были фундаментальные ограничения, которые не позволяли удовлетворить наши растущие потребности в метаданных. Вот то, что мы смогли узнать во время работы с масштабированием WhereHows:


  1. Push лучше, чем pull: хотя получение метаданных непосредственно из источника кажется наиболее простым способом сбора метаданных. Более масштабируемым является использование отдельных поставщиков метаданных для передачи информации в центральный репозиторий через API или сообщения. Такой подход на основе push также обеспечивает более своевременное отображение новых и обновленных метаданных.
  2. Общее лучше, чем конкретное: WhereHows категорически придерживается мнения о том, как должны выглядеть метаданные для набора данных или задания. Это приводит к упрямому API, модели данных и формату хранения. Небольшое изменение модели метаданных приведет к каскаду необходимых изменений вверх и вниз по стеку. Он был бы более масштабируемым, если бы мы разработали общую архитектуру, не зависящую от модели метаданных, которую она хранит и обслуживает. Это, в свою очередь, позволило бы нам сосредоточиться на адаптации и развитии строго самоуверенных моделей метаданных, не беспокоясь о нижних уровнях стека.
  3. Онлайн так же важен, как и офлайн. После того, как метаданные собраны, естественно необходимо проанализировать эти метаданные, чтобы извлечь из них пользу. Одно из простых решений сбросить все метаданные в автономную систему, такую как Hadoop, где можно выполнять произвольный анализ. Однако вскоре мы обнаружили, что одной только поддержки автономного анализа недостаточно. Есть много вариантов использования, таких как управление доступом и обработка конфиденциальности данных, для которых необходимо запрашивать последние метаданные в Интернете.
  4. Взаимоотношения действительно важны. Метаданные часто передают важные взаимосвязи (например, происхождение, владение и зависимости), которые обеспечивают мощные возможности, такие как анализ воздействия, объединение данных, повышение релевантности поиска и т. д.
  5. Многоцентровая вселенная: мы поняли, что недостаточно просто моделировать метаданные, сосредоточенные вокруг одного объекта (набора данных). Существует целая экосистема данных, кода и человеческих сущностей (наборы данных, специалисты по обработке данных, команды, код, API микросервисов, показатели, функции ИИ, модели ИИ, информационные панели, записные книжки и т. Д.), Которые необходимо интегрировать и связать через единый граф метаданных.

Встречайте DataHub


Примерно год назад мы вернулись к чертежной доске и заново создали WhereHows с нуля, основываясь на этих знаниях. В то же время мы осознали растущую потребность LinkedIn в единообразном поиске и обнаружении различных объектов данных, а также в графе метаданных, которая соединяет их вместе. В результате мы решили расширить масштаб проекта, чтобы создать полностью обобщенный инструмент поиска и обнаружения метаданных, DataHub, с амбициозным видением: соединить сотрудников LinkedIn с данными, которые для них важны.


Мы разделили монолитный стек WhereHows на два отдельных стека: интерфейс модульного пользовательского интерфейса и бэкэнд общей архитектуры метаданных. Новая архитектура позволила нам быстро расширить сферу сбора метаданных, не ограничиваясь только наборами данных и заданиями. На момент написания DataHub уже хранит и индексирует десятки миллионов записей метаданных, которые охватывают 19 различных сущностей, включая наборы данных, показатели, задания, диаграммы, функции ИИ, людей и группы. Мы также планируем в ближайшем будущем внедрить метаданные для моделей и меток машинного обучения, экспериментов, информационных панелей, API микросервисов и кода.


Модульный интерфейс


Веб-приложение DataHub это то, как большинство пользователей взаимодействуют с метаданными. Приложение написано с использованием Ember Framework и работает на среднем уровне Play. Чтобы сделать разработку масштабируемой, мы используем различные современные веб-технологии, включая ES9, ES.Next, TypeScript, Yarn with Yarn Workspaces, а также инструменты качества кода, такие как Prettier и ESLint. Уровни представления, управления и данных разделены на пакеты, так что определенные представления в приложении построены на основе композиции соответствующих пакетов.


Структура обслуживания компонентов


Применяя модульную инфраструктуру пользовательского интерфейса, мы создали веб-приложение DataHub как серию связанных компонентов, согласованных по функциям, которые сгруппированы в устанавливаемые пакеты. Эта архитектура пакета использует в основе Yarn Workspaces и надстройки Ember и разбита на компоненты с использованием компонентов и сервисов Ember. Вы можете думать об этом как о пользовательском интерфейсе, который построен с использованием небольших строительных блоков (например, компонентов и сервисов) для создания более крупных строительных блоков (например, надстроек Ember и пакетов npm / Yarn), которые при объединении в конечном итоге составляют веб-приложение DataHub .


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


Взаимодействие с DataHub


На самом высоком уровне интерфейс обеспечивает три типа взаимодействия: (1) поиск, (2) просмотр и (3) просмотр / редактирование метаданных. Вот несколько примеров скриншотов из реального приложения:








Как и в обычной поисковой системе, пользователь может искать один или несколько типов объектов, предоставляя список ключевых слов. Они могут далее нарезать и нарезать результаты, фильтруя список аспектов. Опытные пользователи также могут использовать такие операторы, как OR, NOT и регулярное выражение, для выполнения сложного поиска.


Сущности данных в DataHub могут быть организованы и просматриваться в виде дерева, где каждой сущности разрешено появляться в нескольких местах дерева. Это дает пользователям возможность просматривать один и тот же каталог разными способами, например, с помощью конфигурации физического развертывания или функциональной организации бизнеса. Может быть даже выделенная часть дерева, показывающая только сертифицированные объекты, которые курируются в рамках отдельного процесса управления.


Последнее взаимодействие просмотр / редактирование метаданных также является наиболее сложным. У каждого объекта данных есть страница профиля, на которой показаны все связанные метаданные. Например, страница профиля набора данных может содержать метаданные о его схеме, владении, соответствии, работоспособности и происхождении. Он также может показать, как объект связан с другими, например, задание, которое создало набор данных, метрики или диаграммы, которые вычисляются из этого набора данных, и т. Д. Для метаданных, которые доступны для редактирования, пользователи также могут обновлять их непосредственно через пользовательский интерфейс.


Обобщенная архитектура метаданных


Чтобы полностью реализовать видение DataHub, нам нужна была архитектура, способная масштабироваться с помощью метаданных. Проблемы масштабируемости бывают четырех разных форм:


  1. Моделирование: моделируйте все типы метаданных и отношений в удобной для разработчиков манере.
  2. Прием: прием большого количества изменений метаданных в любом масштабе как через API, так и через потоки.
  3. Обслуживание: обслуживайте собранные необработанные и производные метаданные, а также множество сложных запросов к метаданным в любом масштабе.
  4. Индексирование: индексируйте метаданные в масштабе, а также автоматически обновляйте индексы при изменении метаданных.

Моделирование метаданных


Проще говоря, метаданные это данные, которые предоставляют информацию о других данных. Когда дело доходит до моделирования метаданных, это предъявляет два различных требования:


  1. Метаданные это также данные: для моделирования метаданных нам нужен язык, который по крайней мере так же многофункциональн, как те, которые используются для моделирования данных общего назначения.
  2. Метаданные распределены: нереально ожидать, что все метаданные поступают из одного источника. Например, система, которая управляет списком управления доступом (ACL) набора данных, скорее всего, будет отличаться от той, которая хранит метаданные схемы. Хорошая среда моделирования должна позволять нескольким командам независимо развивать свои модели метаданных, одновременно представляя единое представление всех метаданных, связанных с объектом данных.

Вместо того, чтобы изобретать новый способ моделирования метаданных, мы решили использовать Pegasus, хорошо зарекомендовавший себя язык схем данных с открытым исходным кодом, созданный LinkedIn. Pegasus разработан для моделирования данных общего назначения и поэтому хорошо работает с большинством метаданных. Однако, поскольку Pegasus не предоставляет явного способа моделирования отношений или ассоциаций, мы ввели некоторые специальные расширения для поддержки этих вариантов использования.


Чтобы продемонстрировать, как использовать Pegasus для моделирования метаданных, давайте рассмотрим простой пример, проиллюстрированный следующей измененной диаграммой сущностей-отношений (ERD).



Пример содержит три типа сущностей Пользователь, Группа и Набор данных представленных синими кружками на диаграмме. Мы используем стрелки для обозначения трех типов отношений между этими объектами, а именно OwnedBy, HasMember и HasAdmin. Другими словами, группа состоит из одного администратора и нескольких членов пользователя, которые, в свою очередь, могут владеть одним или несколькими наборами данных.


В отличие от традиционного ERD, мы помещаем атрибуты сущности и отношения непосредственно внутри круга и под именем отношения, соответственно. Это позволяет нам присоединять к объектам новый тип компонента, известный как аспекты метаданных. Разные команды могут владеть и развивать различные аспекты метаданных для одного и того же объекта, не мешая друг другу, таким образом выполняя требование моделирования распределенных метаданных. Три типа аспектов метаданных: владение, профиль и членство включены в приведенный выше пример в виде зеленых прямоугольников. Связь аспекта метаданных с сущностью обозначается пунктирной линией. Например, профиль может быть связан с пользователем, а владение может быть связано с набором данных и т. д.


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


Чтобы смоделировать пример в Pegasus, мы переведем каждую из сущностей, отношений и аспектов метаданных в отдельный файл схемы Pegasus (PDSC). Для краткости мы включим сюда только по одной модели из каждой категории. Во-первых, давайте взглянем на PDSC для объекта User:


{  "type": "record",  "name": "User",  "fields": [    {      "name": "urn",      "type": "com.linkedin.common.UserUrn",    },    {      "name": "firstName",      "type": "string",      "optional": true    },    {      "name": "lastName",      "type": "string",      "optional": true    },    {      "name": "ldap",      "type": "com.linkedin.common.LDAP",      "optional": true    }  ]}

Каждая сущность должна иметь глобально уникальный идентификатор в форме URN, который можно рассматривать как типизированный GUID. Сущность User имеет атрибуты, включая имя, фамилию и LDAP, каждое из которых соответствует необязательному полю в записи пользователя.


Далее следует модель PDSC для отношения OwnedBy:


{  "type": "record",  "name": "OwnedBy",  "fields": [    {      "name": "source",      "type": "com.linkedin.common.Urn",    },    {      "name": "destination",      "type": "com.linkedin.common.Urn",    },    {      "name": "type",      "type": "com.linkedin.common.OwnershipType",    }  ],  "pairings": [    {      "source": "com.linkedin.common.urn.DatasetUrn",      "destination": "com.linkedin.common.urn.UserUrn"    }  ]}

Каждая модель отношений, естественно, содержит поля источник и место назначения, которые указывают на конкретные экземпляры сущности с использованием их URN. Модель может дополнительно содержать другие поля атрибутов, например, в данном случае тип. Здесь мы также вводим настраиваемое свойство, называемое пары, чтобы ограничить отношения конкретными парами исходных и целевых типов URN. В этом случае отношение OwnedBy может использоваться только для подключения набора данных к пользователю.


Наконец, ниже вы найдете модель аспекта метаданных владения. Здесь мы решили смоделировать владение как массив записей, содержащих поля type и ldap. Однако при моделировании аспекта метаданных практически нет ограничений, если это действительная запись PDSC. Это позволяет удовлетворить требование метаданные это также данные, сформулированное ранее.


{  "type": "record",  "name": "Ownership",  "fields": [    {      "name": "owners",      "type": {        "type": "array",        "items": {          "name": "owner",          "type": "record",          "fields": [            {              "name": "type",              "type": "com.linkedin.common.OwnershipType"            },            {              "name": "ldap",              "type": "string"            }          ]        }      }    }  ]}

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


Получение метаданных


DataHub предоставляет две формы приема метаданных: либо через прямые вызовы API, либо через поток Kafka. Первый предназначен для изменений метаданных, которые требуют согласованности чтения после записи, тогда как второй больше подходит для обновлений, ориентированных на факты.


API DataHub основан на Rest.li, масштабируемой строго типизированной сервисной архитектуре RESTful, широко используемой в LinkedIn. Поскольку Rest.li использует Pegasus в качестве определения интерфейса, все модели метаданных, определенные в предыдущем разделе, могут использоваться дословно. Прошли те времена, когда требовалось преобразование нескольких уровней моделей от API до хранилища API и модели всегда будут синхронизироваться.


Ожидается, что для приема на основе Kafka производители метаданных будут генерировать стандартизированное событие изменения метаданных (MCE), которое содержит список предлагаемых изменений конкретных аспектов метаданных, введенных с помощью соответствующего URN объекта. Схема для MCE находится в Apache Avro, но автоматически создается из моделей метаданных Pegasus.


Использование одной и той же модели метаданных для схем событий API и Kafka позволяет нам легко развивать модели без кропотливого обслуживания соответствующей логики преобразования. Однако, чтобы добиться истинной непрерывной эволюции схемы, нам нужно ограничить все изменения схемы, чтобы они всегда были обратно совместимы. Это применяется во время сборки с дополнительной проверкой совместимости.


В LinkedIn мы склонны больше полагаться на поток Kafka из-за слабой связи, которую он обеспечивает между производителями и потребителями. Ежедневно мы получаем миллионы MCE от различных производителей, и ожидается, что их объем будет расти экспоненциально только по мере того, как мы расширяем объем нашей коллекции метаданных. Чтобы построить конвейер приема потоковых метаданных, мы использовали Apache Samza в качестве нашей платформы обработки потоковой информации. Задание Samza приема специально разработано, чтобы быть быстрым и простым для достижения высокой пропускной способности. Он просто преобразует данные Avro обратно в Pegasus и вызывает соответствующий API Rest.li для завершения приема.



Обслуживание метаданных


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


  1. Документно-ориентированные запросы
  2. Графические запросы
  3. Сложные запросы, включающие соединения
  4. Полнотекстовый поиск

Для этого DataHub необходимо использовать несколько типов систем данных, каждая из которых специализируется на масштабировании и обслуживании ограниченных типов запросов. Например, Espresso это база данных NoSQL LinkedIn, которая особенно хорошо подходит для масштабируемого документально-ориентированного CRUD. Точно так же Galene может легко индексировать и обслуживать полнотекстовый поиск в Интернете. Когда дело доходит до нетривиальных запросов к графам, неудивительно, что специализированная графовая БД может выполнять на порядки лучше, чем реализации на основе СУБД. Однако оказывается, что структура графа также является естественным способом представления отношений внешнего ключа, позволяя эффективно отвечать на сложные запросы соединения.


DataHub дополнительно абстрагирует базовые системы данных с помощью набора общих объектов доступа к данным (DAO), таких как DAO ключ-значение, запрос DAO и поиск DAO. После этого реализация DAO для конкретной системы данных может быть легко заменена, без изменения какой-либо бизнес-логики в DataHub. В конечном итоге это позволит нам открыть DataHub с открытым исходным кодом с эталонными реализациями для популярных систем с открытым исходным кодом, в то же время используя все преимущества проприетарных технологий хранения LinkedIn.



Еще одно ключевое преимущество абстракции DAO стандартизированный сбор данных об изменениях (CDC). Независимо от типа базовой системы хранения данных, любая операция обновления через DAO ключ-значение автоматически генерирует событие аудита метаданных (MAE). Каждый MAE содержит URN соответствующего объекта, а также изображения до и после определенного аспекта метаданных. Это позволяет использовать лямбда-архитектуру, в которой MAE могут обрабатываться как пакетами, так и потоками. Подобно MCE, схема MAE также автоматически генерируется из моделей метаданных.


Индексирование метаданных


Последний недостающий элемент головоломки конвейер индексации метаданных. Это система, которая объединяет модели метаданных и создает соответствующие индексы в графической БД и поисковой системе для облегчения эффективных запросов. Эти бизнес-логики фиксируются в форме построителя индексов и построителей графиков и выполняются как часть задания Samza, обрабатывающего MAE. Каждый разработчик зарегистрировал свой интерес к конкретным аспектам метаданных в задании и будет вызван с соответствующим MAE. Затем построитель возвращает список идемпотентных обновлений, которые будут применяться к БД индекса поиска или графа.


Конвейер индексации метаданных также хорошо масштабируется, поскольку его можно легко разделить на основе URN объекта каждого MAE для поддержки упорядоченной обработки для каждого объекта.



Заключение и с нетерпением жду


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


DataHub работает в LinkedIn в течение последних шести месяцев. Каждую неделю его посещают более 1500 сотрудников, которые поддерживают поиск, обнаружение и различные рабочие процессы для конкретных действий. График метаданных LinkedIn содержит более миллиона наборов данных, 23 системы хранения данных, 25 тысяч показателей, более 500 функций искусственного интеллекта и, что наиболее важно, всех сотрудников LinkedIn, которые являются создателями, потребителями и операторами этого графика.


Мы продолжаем улучшать DataHub, добавляя в продукт больше интересных пользовательских историй и алгоритмов релевантности. Мы также планируем добавить встроенную поддержку GraphQL и использовать язык Pegasus Domain Specific Language (PDL) для автоматизации генерации кода в ближайшем будущем. В то же время мы активно работаем над тем, чтобы поделиться этой эволюцией WhereHows с сообществом разработчиков ПО с открытым исходным кодом, а после публичного выпуска DataHub мы сделаем объявление.

Подробнее..

Кастомные декораторы для NestJS от простого к сложному

14.07.2020 12:05:49 | Автор: admin

image


Введение


NestJS стремительно набирающий популярность фрeймворк, построенный на идеях IoC/DI, модульного дизайна и декораторов. Благодаря последним, Nest имеет лаконичный и выразительный синтаксис, что повышает удобство разработки.


Декораторы или аннотации наследники аспектов, которые позволяют декларативно описывать логику, модифицировать поведение классов, их свойств, аргументов и методов.
Технически декораторы это просто функции, но их вызовом полностью управляет компилятор.
Важная особенность заключается в том, что в зависимости от контекста, сигнатуры аргументов будут различаться. Материалов на эту тему существует довольно много, однако мы сосредоточимся на специфике, связанной непосредственно с Nest.


Базовые декораторы


Возьмем простейший http-контроллер. Допустим, нам требуется, чтобы только определенные пользователи могли воспользоваться его методами. Для этого кейса в Nest есть встроенная функциональность гардов.
Guard это комбинация класса, реализующего интерфейс CanActivate и декоратора @UseGuard.


@Injectable()export class RoleGuard implements CanActivate {  canActivate(    context: ExecutionContext,  ): boolean | Promise<boolean> | Observable<boolean> {    const request = context.switchToHttp().getRequest();    return getRole(request) === 'superuser'  }}@Controller()export class MyController {  @Post('secure-path')  @UseGuards(RoleGuard)  async method() {    return  }}

Захардкоженный superuser не самое лучшее решение, куда чаще нужны более универсальные декораторы.
Nest в этом случае предлагает использовать
декоратор @SetMetadata. Как понятно из названия, он позволяет ассоциировать метаданные с декорируемыми объектами классами или методами.
Для доступа к этим данным используется экземпляр класса Reflector, но можно и напрямую через reflect-metadata.


@Injectable()export class RoleGuard implements CanActivate {  constructor(private reflector: Reflector) {}  canActivate(    context: ExecutionContext,  ): boolean | Promise<boolean> | Observable<boolean> {    const role = this.reflector.get<string>('role', context.getHandler());    const request = context.switchToHttp().getRequest();    return getRole(request) === role  }}@Controller()export class MyController {  @Post('secure-path')  @SetMetadata('role', 'superuser')  @UseGuards(RoleGuard)  async test() {    return  }}

Композитные декораторы


Декораторы зачастую применяются в связках.
Обычно это обусловлено тесной связностью эффектов в каком-то бизнес-сценарии. В этом случае имеет смысл объединить несколько декораторов в один.
Для композиции можно воспользоваться утилитной функцией applyDecorators.


const Role = (role) => applyDecorators(UseGuards(RoleGuard), SetMetadata('role', role))

или написать агрегатор самим:


const Role = role => (proto, propName, descriptor) => {  UseGuards(RoleGuard)(proto, propName, descriptor)  SetMetadata('role', role)(proto, propName, descriptor)}@Controller()export class MyController {  @Post('secure-path')  @Role('superuser')  async test() {    return  }}

Полиморфные декораторы


Легко столкнуться с ситуацией, когда оказывается нужным задекорировать все методы класса.


@Controller()@UseGuards(RoleGuard)export class MyController {  @Post('secure-path')  @Role('superuser')  async test1() {    return  }  @Post('almost-securest-path')  @Role('superuser')  async test2() {    return  }  @Post('securest-path')  @Role('superuser')  async test3() {    return  }}

Такой код можно сделать чище, если повесить декоратор на сам класс. И уже внутри декоратора класса обойти прототип, применяя эффекты на все методы, как если бы декораторы были повешены на каждый метод по-отдельности.
Однако для этого обработчику необходимо различать типы объектов применения класс и метод и в зависимости от этого выбирать поведение.
Реализация декораторов в typescript не содержит этот признак в явном виде,
поэтому его приходится выводить из сигнатуры вызова.


type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;const Role = (role: string): MethodDecorator | ClassDecorator => (...args) => {  if (typeof args[0] === 'function') {    // Получение конструктора    const ctor = args[0]    // Получение прототипа    const proto = ctor.prototype    // Получение методов    const methods = Object      .getOwnPropertyNames(proto)      .filter(prop => prop !== 'constructor')    // Обход и декорирование методов    methods.forEach((propName) => {      RoleMethodDecorator(        proto,        propName,        Object.getOwnPropertyDescriptor(proto, propName),        role,      )    })  } else {    const [proto, propName, descriptor] = args    RoleMethodDecorator(proto, propName, descriptor, role)  }}

Есть вспомогательные библиотеки, которые берут на себя часть этой рутины: lukehorvat/decorator-utils, qiwi/decorator-utils.
Это несколько улучшает читаемость.


import { constructDecorator, CLASS, METHOD } from '@qiwi/decorator-utils'const Role = constructDecorator(  ({ targetType, descriptor, proto, propName, args: [role] }) => {    if (targetType === METHOD) {      RoleMethodDecorator(proto, propName, descriptor, role)    }    if (targetType === CLASS) {      const methods = Object.getOwnPropertyNames(proto)      methods.forEach((propName) => {        RoleMethodDecorator(          proto,          propName,          Object.getOwnPropertyDescriptor(proto, propName),          role,        )      })    }  },)

Совмещение в одном декораторе логики для разных сценариев дает очень весомый плюс для разработки:
вместо @DecForClass, @DecForMethood, @DecForParam получается всего один многофункциональный @Dec.


Так, например, если роль пользователя вдруг потребуется в бизнес-слое контроллера, можно просто расширить логику @Role.
Добавляем в ранее написанную функцию обработку сигнатуры декоратора параметра.
Так как подменить значение параметров вызова напрямую нельзя, createParamDecorator делегирует это вышестоящему декоратору посредством метаданных.
И далее именно декоратор метода / класса будет резолвить аргументы вызова (через очень длинную цепочку от ParamsTokenFactory до RouterExecutionContext).


// Сигнатура параметра  if (typeof args[2] === 'number') {    const [proto, propName, paramIndex] = args    createParamDecorator((_data: unknown, ctx: ExecutionContext) => {      return getRole(ctx.switchToHttp().getRequest())    })()(proto, propName, paramIndex)  }

Также стоит отметить, что при помощи метадаты можно решать разные интересные кейсы, например, вводить ограничения для повторяемости или сочетаемости аннотаций.
Предположим, нам потребовалось ограничение размера запроса, и соответствующий декоратор повесили дважды. Какому значению доверять?
Без знания логики компилятора возникает неопределенность. Правильнее, наверное, было бы бросить ошибку.


class SomeController {   @RequestSize(1000)   @RequestSize(5000)   @Post('foo')   method(@Body() body) {   }}

Вот другой пример: необходимо ограничить работу методов контроллера отдельными портами. Здесь, скорее, требуется не затирать предыдущие значения,
а добавлять новые к имеющимся.


class SomeController {   @Port(9092)   @Port(8080)   @Post('foo')   method(@Body() body) {   }}

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


class SomeController {  @Post('securest-path')  @Role('superuser')  @Role('usert')  @Role('otheruser')  method(@Role() role) {  }}

Обобщая рассуждения, реализация декоратора для последнего примера с использованием reflect-metadata и полиморфного контракта
может иметь вид:


import { ExecutionContext, createParamDecorator } from '@nestjs/common'import { constructDecorator, METHOD, PARAM } from '@qiwi/decorator-utils'@Injectable()export class RoleGuard implements CanActivate {  canActivate(context: ExecutionContext): boolean | Promise<boolean> {    const roleMetadata = Reflect.getMetadata(      'roleMetadata',      context.getClass().prototype,    )    const request = context.switchToHttp().getRequest()    const role = getRole(request)    return roleMetadata.find(({ value }) => value === role)  }}const RoleMethodDecorator = (proto, propName, decsriptor, role) => {  UseGuards(RoleGuard)(proto, propName, decsriptor)  const meta = Reflect.getMetadata('roleMetadata', proto) || []  Reflect.defineMetadata(    'roleMetadata',    [      ...meta, {        repeatable: true,        value: role,      },    ],    proto,  )}export const Role = constructDecorator(  ({ targetType, descriptor, proto, propName, paramIndex, args: [role] }) => {    if (targetType === METHOD) {      RoleMethodDecorator(proto, propName, descriptor, role)    }    if (targetType === PARAM) {      createParamDecorator((_data: unknown, ctx: ExecutionContext) =>        getRole(ctx.switchToHttp().getRequest()),      )()(proto, propName, paramIndex)    }  },)

Макродекораторы


Nest спроектирован таким образом, что его собственные декораторы удобно расширять и переиспользовать. На первый взгляд довольно сложные кейсы, к примеру, связанные с добавлением поддержки новых протоколов, реализуются парой десятков строк обвязочного кода. Так, стандартный @Controller можно обсахарить
для работы с JSON-RPC.
Не будем останавливаться на этом подробно, это слишком бы далеко вышло за формат этой статьи, но покажу основную идею: на что способны декораторы, в сочетании с Nest.


import {  ControllerOptions,  Controller,  Post,  Req,  Res,  HttpCode,  HttpStatus,} from '@nestjs/common'import { Request, Response } from 'express'import { Extender } from '@qiwi/json-rpc-common'import { JsonRpcMiddleware } from 'expressjs-json-rpc'export const JsonRpcController = (  prefixOrOptions?: string | ControllerOptions,): ClassDecorator => {  return <TFunction extends Function>(target: TFunction) => {    const extend: Extender = (base) => {      @Controller(prefixOrOptions as any)      @JsonRpcMiddleware()      class Extended extends base {        @Post('/')        @HttpCode(HttpStatus.OK)        rpc(@Req() req: Request, @Res() res: Response): any {          return this.middleware(req, res)        }      }      return Extended    }    return extend(target as any)  }}

Далее необходимо извлечь @Req() из rpc-method в мидлваре, найти совпадение с метой, которую добавил декоратор @JsonRpcMethod.
Готово, можно использовать:


import {  JsonRpcController,  JsonRpcMethod,  IJsonRpcId,  IJsonRpcParams,} from 'nestjs-json-rpc'@JsonRpcController('/jsonrpc/endpoint')export class SomeJsonRpcController {  @JsonRpcMethod('some-method')  doSomething(    @JsonRpcId() id: IJsonRpcId,    @JsonRpcParams() params: IJsonRpcParams,  ) {    const { foo } = params    if (foo === 'bar') {      return new JsonRpcError(-100, '"foo" param should not be equal "bar"')    }    return 'ok'  }  @JsonRpcMethod('other-method')  doElse(@JsonRpcId() id: IJsonRpcId) {    return 'ok'  }}

Вывод


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

Подробнее..

7 вещей, которые нужно проработать, прежде чем запускать OpenShift в продакшн

24.12.2020 16:21:15 | Автор: admin
Взрывной рост использования контейнеров на предприятиях впечатляет. Контейнеры идеально совпали с ожиданиями и потребностями тех, кто хочет снизить затраты, расширить свои технические возможности и продвинуться вперед по пути agile и devops. Контейнерная революция открывает новые возможности и для тех, кто подзадержался с обновлением ИТ-систем. Контейнеры и Kubernetes это абсолютно и принципиально новый способ управления приложениями и ИТ-инфраструктурой.



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

Многие решают ускорить переход на контейнеры с помощью Red Hat OpenShift Container Platform, ведущей отраслевой Kubernetes-платформы для корпоративного сектора. Это решение автоматически берет на себя множество задач первого дня и предлагает лучшую Kubernetes-экосистему на базе единой, тщательно протестированной и высоко защищенной платформы. Это наиболее комплексное и функциональное решение для предприятий, которое содержит всё необходимое для начала работы и устраняет массу технических барьеров и сложностей при построении Kubernetes-платформы.

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

1. Стандартизация правил именования и метаданных


В компьютерных науках есть только две трудные вещи: аннулирование кэша и именование сущностей.
Фил Карлтон (Phil Karlton)

У всякой сущности в OpenShift и Kubernetes есть свое имя. И у каждого сервиса должно быть свое DNS-имя, единственное ограничение здесь правила именования DNS. А теперь представьте, что монолитное приложение разложилось на 100500 отдельных микросервисов, каждый с собственной базой данных. И да, в OpenShift всё является либо иерархическим, связанным, либо должно соответствовать шаблону. Так что именовать придется массу и массу всего. И если заранее не подготовить стандарты, это получится настоящий Дикий Запад.

Вы уже распланировали схему реализации сервисов? Допустим, это будет одно большое пространство имен, например, databases, в котором все будут размещать свои базы данных. OK, и даже допустим, что все так и будут делать, но потом-то они начнут размещать свои кластеры Kafka в своих собственных пространствах имен. Да, а нужно ли заводить пространство имен middleware? Или лучше назвать его messaging? И как обычно, в какой-то момент появляются ребята, которые всегда идут своим путем и считают себя особенными, и говорят, что им нужны собственные пространства имен. И слушайте, у нас же в организации 17 подразделений, может надо приделать ко всем пространствам имен наши стандартные префиксы подразделений?

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

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

2. Стандартизация корпоративных базовых образов


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

Возьмем, к примеру, базовое java-приложение. Ваши разработчики вряд ли ошибутся с выбором OpenJDK, а вот с управлением уязвимостями, обновлением библиотек и прочими вопросами ИТ-гигиены вполне могут. Мы все знаем, что бизнес-задачи зачастую решаются ценой технических компромиссов, вроде намеренного использования старых версий Java. К счастью, такие задачи легко автоматизируются и управляются на уровне предприятия. Вы по-прежнему может использовать базовые образы вендора, но одновременно задавать и контролировать свои циклы обновления, создавая собственные базовые образы.

Возвращаясь к примеру выше, допустим, разработчикам нужна Java 11, а вам, соответственно, надо, чтобы они всегда использовали самую последнюю версию Java 11. Тогда вы создаете корпоративный базовый образ (registry.yourcompany.io/java11), используя в качестве отправной точки базовый образ от вендора ОС (registry.redhat.io/ubi8/openjdk-11). А когда этот базовый образ обновляется, вы автоматом помогаете разработчикам задействовать последние обновления. К тому же, таким образом реализуется уровень абстракции, позволяющий бесшовно дополнять стандартный образ необходимыми библиотеками или Linux-пакетами.

3. Стандартизация проверок работоспособности и готовности


Контроль исправности, он нужен практически везде. Считается, что для человека достаточно ежегодного медосмотра. Исправность приложений надо проверять, понятно, гораздо чаще, и контролировать две ключевые вещи:

  • Запущено ли приложение (health check работоспособность).
  • Готово ли приложение (readiness check готовность).

Существует масса и других метрик, чтобы облегчить мониторинг приложений, но вот эти две это основа основ не только мониторинга, но и масштабирования. Работоспособность обычно определяется наличием сетевого подключения и способностью узла, на котором выполняется приложение, отозваться на запрос. Что касается готовности, то здесь уже каждое приложение должно реагировать на запросы по своим стандартам. Например, запуск приложения с очень низкими задержками может сопровождаться длительным обновлением кэша или прогревом JVM. И соответственно, пауза между ответами Запущено и Готово может достигать нескольких минут. А вот, например, для stateless REST API с реляционной базой данных эти ответы будут приходить одновременно.

Самое главное в этих проверках не отходить от сугубо двоичной логики. Запущено значит запущено, без всяких там как бы запущено. Готово значит готово, и никаких градаций, вроде на такие запросы готово отвечать, а на такие нет. Принцип простой: всё или ничего.

Второй аспект таких проверок это стандартизация. Как проверить готовность? Если у вас нет стандартов, то даже такой простой вопрос может стать настоящим кошмаром для мониторинга. Просто сравните, как разошлись друг от друга стандарты Quarkus и стандарты Spring Boot. А ведь никто этого не хотел, но со стандартами всегда так. Единственная разница в том, что теперь ваша организация сама имеет власть разрабатывать и вводить стандарты.
Примечание на полях. Не изобретайте свои стандарты. Просто найдите и используйте какой-нибудь готовый.

4. Стандартизация логов


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

Стандартизировать надо структуру. Повторимся: целостность стандартов важнее их правильности. Вы должны быть способы написать отдельный лог-парсер для каждого приложения, которое есть на предприятии. Да, это будут сугубо штучные, не тиражируемые вещи. Да, у вас будет куча исключений, которые нельзя контролировать, особенно для коробочных приложений. Но не выплескивайте ребенка вместе с водой, уделите внимание деталям: например, временная метка в каждом логе должна отвечать соответствующему стандарту ISO; сам вывод должен быть в формате UTC с точностью до 5-го знака в микросекундах (2018-11-07T00:25:00.07387Z). Уровни журнала должны быть оформлены CAPS-ом и там должны быть элементы TRACE, DEBUG, INFO, WARN, ERROR. В общем, задайте структуру, а уже затем разбирайтесь с подробностями.

Стандартизация структуры заставит всех придерживаться одних правил и использовать одни и те же архитектурные шаблоны. Это верно для логов как приложений, так и платформ. И не отклоняйтесь от готового решения без крайней нужды. EFK-стек (Elasticsearch, Fluentd и Kibana) платформы OpenShift должен быть в состоянии обработать все ваши сценарии. Он ведь вошел в состав платформы не просто так, и при ее обновлении это еще одна вещь, о которой не надо беспокоиться.

5. Переход на GitOps


Одна из главных прелестей OpenShift заключается в том, что здесь всё буквально: всё в конечном является либо конфигурацией, либо кодом, а значит, может контролироваться через систему управления версиями. Это позволяет революционизировать способы доставки и избавиться от бюрократии при запуске в продакшн.

В частности, традиционную схему на основе тикетов можно полностью заменить на модель с pull-запросами git. Допустим, владелец приложения хочет подкорректировать выделяемые приложению ресурсы после реализации в нем новых функций, например, увеличить память с 8 до 16 ГБ. В рамках традиционной схемы разработчику для этого надо создать тикет и ждать, пока кто-то другой выполнит соответствующую задачу. Этим кем-то другим чаще всего оказывается ИТ-эсплуатант, который лишь вносит ощутимую задержку в процесс реализации изменений, никак не повышая ценность этого процесса, или хуже того, навешивая на этот процесс лишние дополнительные циклы. В самом деле, у эсплуатанта есть два варианта действий. Первое: он рассматривает заявку и решает ее выполнить, для чего входит в продакшн-среду, вносит затребованные изменения вручную и перезапускает приложение.
Помимо времени на проведение самой работы здесь возникает и дополнительная задержка, поскольку у эксплуатанта, как правило, всегда есть целая очередь заявок на выполнение. Кроме того, возникает риск человеческой ошибки, например, ввод 160 ГБ вместо 16 ГБ. Второй вариант: эксплуатант ставит заявку под сомнение и тем самым запускает цепную реакцию по выяснению причин и последствий запрашиваемых изменений, да так, что иногда уже приходится вмешиваться начальству.

Теперь посмотрим, как это делается в GitOps. Запрос на изменения попадает в репозиторий git и превращается в pull-запрос. После чего разработчик может выставить этот pull-запрос (особенно, если это изменения в продакшн-среде) для утверждения причастными сторонами. Таким образом, специалисты по безопасности могут подключиться уже на ранней стадии, и всегда есть возможность отследить последовательность изменений. Стандарты в этой области можно внедрять программно, используя соответствующие средства в инструментальной цепочке CI/CD. После того, как его утвердили, pull-запрос версионируется и легко поддается аудиту. Кроме того, его можно протестировать в среде pre-production в рамках стандартного процесса, полностью устранив риск человеческой ошибки.

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

6. Схемы приложений (Blueprints)


Переход от монолитных приложений к микросервисам усиливает роль шаблонов проектирования (паттернов) приложений. В самом деле, типичное монолитное приложение не особо поддается классификации. Как правило, там есть и REST API, и пакетная обработка, и событиями оно управляется. HTTP, FTP, kafka, JMS и Infinispan? Да пожалуйста, а еще оно одновременно работает с тремя разными базами данных. И как прикажете создавать схему, когда здесь намешана целая куча шаблонов интеграции корпоративных приложений? Да никак.

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

  • REST API для управления данными в СУБД.
  • Пакетная обработка, которая проверят FTP-сервер на предмет обновления данных и отправляет их в топик kafka.
  • Camelадаптер, берущий данные из этого kafka-топика и отправляющий их в REST API
  • REST API, которые выдают обобщенную информацию, собираемую из Data Grid, которая действует как конечный автомат.

Итак, теперь у нас есть схемы, а схемы уже можно стандартизировать. REST API должны отвечать стандартам Open API. Пакетные задания будут управляться как пакетные задания OpenShift. Интеграции будут использовать Camel. Схемы можно создавать для API, для пакетных заданий, для AI/ML, для multicast-приложений, да для чего угодно. А затем уже можно определять, как развертывать эти схемы, как их конфигурировать, какие шаблоны использовать. Имея такие стандарты, не надо будет каждый раз изобретать колесо, и вы сможете лучше сфокусироваться на действительно важных задачах, вроде создания нового бизнес-функционала. Проработка схем может показаться пустой тратой времени, но затраченные усилия сторицей вернутся в будущем.

7. Подготовьтесь к API


Вместе с микросервисной архитектурой приходят и API. Ими тоже придется управлять и лучше подготовиться к этому заранее.

Во-первых, здесь опять понадобятся стандарты. В качестве отправной точки можно взять стандарты Open API, но придется углубиться в дебри. Хотя здесь важно соблюсти баланс и не впасть в чрезмерную зарегламентированность с кучей ограничений. Посмотрите на эти вопросы: когда новая сущность создается с помощью POST, что надо возвращать, 201 или 200? разрешается ли обновлять сущности с помощью POST, а не PUT? В чем разница между 400-ми и 500-ми ответами? примерно такой уровень детализации вам нужен.

Во-вторых, понадобится сервисная сетка service mesh. Это реально сильная вещь и со временем она станет неотъемлемой частью Kubernetes. Почему? Потому что трафик рано или поздно превратится в проблему, и вам захочется управлять им как внутри дата-центра (т.н. трафик восток-запад), так и между дата-центром и внешним по отношению к нему миром (север-юг). Вам захочется вытащить из приложений аутентификацию и авторизацию и вывести их на уровень платформы. Вам понадобятся возможности Kiali по визуализации трафика внутри service mesh, а также сине-зеленые и канареечные схемы развертывания приложений, или, к примеру, динамический контроль трафика. В общем, service mesh без вопросов входит в категорию задач первого дня.

В-третьих, вам понадобится решение для централизованного управления API. Вам захочется иметь одно окно для поиска и повторного использования API. Разработчикам понадобится возможность зайти в магазин API, найти там нужный API и получить документацию по его использованию. Вы захотите единообразно управлять версиями и deprecation-ами. Если вы создаете API для внешних потребителей, то такое решение может стать конечной точкой север-юг во всем, что касается безопасности и управления нагрузкой. 3Scale даже может помочь с монетизицией API. Ну и рано или поздно ваше руководство захочет получить отчет, отвечающий на вопрос Какие у нас есть API?.

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

Однако, надежда есть, и она заключается в автоматизации. Любой из перечисленных выше стандартов можно внедрить с помощью автоматизации. Процесс GitOps может проверять, что во всех соответствующих yaml-файлах присутствуют все требуемые метки и аннотации. Процесс CI/CD может контролировать соблюдение стандартов на корпоративные образы. Все может быть кодифицировано, проверено и приведено в соответствие. Кроме того, автоматизацию можно доработать, когда вы вводите новые стандарты или меняете существующие. Безусловное преимущество стандартизации через автоматизацию заключается в том, что компьютер не избегает конфликтов, а просто констатирует факты. Следовательно, при достаточной проработанности и инвестициях в автоматизацию, платформа, в которую вы вкладываете столько средств сегодня, может принести гораздо больший возврат инвестиций в будущем в виде повышения производительности и стабильности.
Подробнее..

Правильное автоматическое заполнение метатегов alt и title изображений для WordPress

28.07.2020 20:05:54 | Автор: admin


Приветствую вас, уважаемые читатели Хабра. Как часто мы сталкиваемся с заполнением атрибутов для изображений? Я довольно часто. И каждый раз начиная пользоваться WordPress на очередном сайте, этот процесс вызывает некоторое раздражение. Поскольку из коробки CMS устанавливает метатеги изображений не корректно, точнее не так, как того требуют поисковые системы для грамотного предоставления информации о картинке. Я решил исправить эту несправедливость.

Проблематика


WordPress по умолчанию устанавливает название файла в поле Заголовок, которое соответствует атрибуту title, а поле Атрибут alt, которое соответствует атрибуту alt, оставляет пустым. Это вызывает дополнительные манипуляции при заполнении атрибутов у каждого изображения. При использовании стандартного загрузчика, параметры файла выглядят следующем образом:



Как пишет Яндекс, в своей документации:
Атрибут alt это альтернативный источник информации для пользователей, у которых показ изображений в браузере отключен. Если атрибут alt определен, то, когда показать картинку будет невозможно, на ее месте отобразится текст атрибута.

Атрибут title предоставляет дополнительную информацию о картинке. Текст, заключенный в этом атрибуте, появляется при наведении курсора на картинку

А также, предупреждает, что оставлять атрибуты пустыми нежелательно и рекомендует для каждой картинки указывать уникальный title. То есть alt и title не должны быть одинаковыми.

Google, в своей справке, упоминает только alt:
Замещающий текст в атрибутах alt делает контент доступным для пользователей, которые не видят изображения на страницах (например, потому что используют программы для чтения с экрана или из-за медленного подключения к Интернету).

Определяя тему изображения, Google учитывает описания в атрибутах alt и контент страницы, а также опирается на алгоритмы компьютерного зрения. Кроме того, если вы решите использовать изображение в качестве ссылки, замещающий текст можно сделать ее текстом.

Исходя из моего опыта, можно сделать вывод о том, что alt существенно важнее title. Но тем не менее заполнять все-таки лучше два атрибута. Помимо этого, важно учитывать, что название файла изображения на сайте (используя транслитерацию) должно соответствовать alt. То есть грамотная оптимизация изображения для поисковых систем может выглядеть следующем образом:

  • название файла: Метатеги для изображений.png;
  • адрес до изображения: /metategi-dlya-izobrazhenij.png;
  • alt: Метатеги для изображений;
  • title: Изображение метатеги для изображений.

Решение


Так как заполнять два атрибута бывает несколько утомительно, а title просто дополняет alt. Мы, в своих проектах используем какое-то дополнительное слово или конструкцию для title. Важно, чтобы конструкция была универсальная и подходила для всех картинок на сайте. Поэтому, Я написал простое решение, которое изменяет работу стандартного загрузчика WordPress следующем образом:

  • атрибут alt (alt): Название файла;
  • заголовк (title): Изображение название файла.

Получая, такие параметры файла:



Установка решения


Для установки решения необходимо добавить следующий код в functions.php вашей темы:

# Automatically sets the image Title, Alt-Text, Caption & Description upon uploadadd_action('add_attachment', 'pami_set_image_meta_upon_upload');# Helper functionif (!function_exists('pami_image_meta_first')) {function pami_image_meta_first($my_image_title, $encoding = 'UTF-8') {$my_image_title = mb_ereg_replace('^[\ ]+', '', $my_image_title);$my_image_title = mb_strtoupper(mb_substr($my_image_title, 0, 1, $encoding), $encoding). mb_substr($my_image_title, 1, mb_strlen($my_image_title), $encoding);return $my_image_title;}}# Main functionfunction pami_set_image_meta_upon_upload($post_ID) {if (!wp_attachment_is_image($post_ID)) return;$my_image_title = get_post($post_ID)->post_title;// Sanitize the title: remove hyphens, underscores & extra spaces:$my_image_title = preg_replace('%\s*[-_\s]+\s*%', ' ', $my_image_title);// Sanitize the title: capitalize first letter of every word (other letters lower case):$my_image_title = str_replace('"', '', $my_image_title);$my_image_title = str_replace('', '', $my_image_title);$my_image_title = str_replace('', '', $my_image_title);$my_image_title = str_replace('', '', $my_image_title);$my_image_title = str_replace(':', '', $my_image_title);$my_image_title = str_replace('  ', ' ', $my_image_title);$my_image_title = str_replace('   ', ' ', $my_image_title);$my_image_title = pami_image_meta_first(mb_strtolower($my_image_title));// Set the image Alt-Textupdate_post_meta($post_ID, '_wp_attachment_image_alt', $my_image_title);$my_image_title = mb_strtolower($my_image_title);$my_image_meta = ['ID' => $post_ID,'post_title' => 'Изображение  ' . $my_image_title, // Set image Title to sanitized title]; // Set the image meta (e.g. Title, Excerpt, Content)wp_update_post($my_image_meta);}

Предложенное решение так же удаляет лишние символы (кавычки, дефисы, двойне пробелы и другие символы) из названия изображения. А конструкцию для title Изображение , можно легко изменить на любую другую (56 строчка, при просмотре в редакторе).

Надеюсь, что решение будет полезным для вас и поможет сэкономить некоторое количество времени работы контент-менеджерам.

P.S. Для тех кто не хочет добавлять код самостоятельно, предлагаю просто установить плагин Prostudio Auto Meta Images из официального репозитория WordPress.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru