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

Сайт https://wiregoose.com

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

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

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

Итак, перечислим необходимые ингредиенты.

  • Серверное приложение
  • Сканер RSS
  • Экстрактор статей
  • SSR (рендеринг на стороне сервера) для SEO в социальных сетях
  • Прокси изображения
  • Фронтенд-приложение
  • Оркестратор служб

Правило разделения услуг ясно с самого начала. Есть некоторые первоначальные замечания относительно реализации. Наши потребности отличаются от классического бэкенд-фронтенд-приложения. Нам пришлось создать собственную инфраструктуру и отказаться от использования решения «сервер как услуга». Вот некоторые из основных причин:

  1. Сканер RSS состоит из бесконечного цикла, который никогда не прекращает получать и обрабатывать внешние ресурсы. Следовательно, если мы развернем его в инфраструктуре SAS, стоимость будет огромной.
  2. Сканер RSS полностью отличается от серверного приложения. Если мы поместим его в то же монолитное приложение, это вызовет проблемы с производительностью во всей инфраструктуре.

Учитывая вышеизложенное, мы решили создать стек из 4 микросервисов, фронтенд-приложения и оркестратора.

Сканер RSS

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

Экстрактор статей

Это функциональность, которую мы обычно не видим в отрасли. Наша цель — извлечь со страницы только полезный контент статьи, без рекламы, боковых панелей и всплывающих окон. Полезный контент, который мы определяем на странице статьи, представляет собой комбинацию текста, заголовка, изображений и видео. После долгих исследований мы пришли к выводу, что эта функциональность уже реализована в современных браузерах. Название функционала — статья «читабельность». Он уже существует как расширение в Chrome и Firefox внутри контекста выполнения браузера.

Что нам нужно было сделать, так это получить статью на сервере, добавить ее в реализацию server-dom (jsdom) и использовать библиотеку удобочитаемости, чтобы извлечь полезные сегменты страницы. После некоторых экспериментов результат был потрясающим. Процент успеха был вполне приемлемым, даже тот факт, что язык страницы был не латиницей. Иногда бывают ложные срабатывания, но результат не раздражает. В этом процессе есть 2 наблюдения:

  1. Это тяжелый процесс, поэтому нам пришлось добавить механизм кэширования.
  2. Успех процесса не гарантирован. Многие шаги могут привести к неправильным результатам, от шага загрузки страницы статьи до извлечения содержимого статьи. Таким образом, во внешнем интерфейсе должна быть реализована красивая страница ошибок.
  3. Фидов слишком много, мы не можем делать эту процедуру для каждого фида, поэтому делаем это по требованию.

Прокси изображения

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

  1. Интерфейсному приложению требуется исходное изображение из нашего прокси-сервиса изображений с необязательными размерами ширины и высоты.
  2. Наш сервис загружает изображение во временную папку и применяет необходимые преобразования в размерах и размерах.
  3. Кэширует образ с помощью политики LRU в памяти.
  4. Отправляет изображение во внешнее приложение

ССР

Необходимая функциональность для каждого современного приложения. К сожалению, мы не можем жить без него. Это единственный способ сделать SPA доступным для ботов Google и механизмов предварительного просмотра Twitter, Facebook и т. д. Мы провели здесь много исследований о том, что мы можем сделать, чтобы сделать эту функциональность максимально легкой. насколько это возможно. Все готовые к производству решения не работали должным образом.

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

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

  1. Используйте реактивный шлем во внешнем интерфейсе, чтобы внедрить все SEO-теги на каждую страницу. Название, изображение, описание и т. д.
  2. Запустите экземпляр страницы puppeteer в службе SSR.
  3. Откройте URL-адрес на странице и подождите, пока сеть не освободится. Затем мы предполагаем, что страница прочитана для моментального снимка.
  4. Отправьте внутренний HTML-код страницы и кэшируйте его.

Серверное приложение

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

База данных

Мы используем MongoDB в качестве основной базы данных для наших нужд. Все приложение обрабатывает последовательности и потоки данных. RSS-каналы хранятся последовательно, а временная шкала внешнего интерфейса отображает ту же структуру, что и в базе данных. Документно-ориентированная база данных, такая как MongoDB, хорошо подходит для наших нужд.

Фронтенд-приложение

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

Оркестратор служб

Есть много сегментов услуг, которые мы еще не объяснили. Как все эти службы взаимодействуют друг с другом и как они развертываются в рабочей среде. Мы использовали Nginx для нашего оркестратора сервисов. Все сервисы являются приложениями NodeJS. Приложения, работающие как публичные серверы, используют фреймворк ExpressJS. Nginx выполняет следующие процессы:

  • Публичные сервисы защищены обратным прокси.
  • Прокси-сервис изображений находится в домене img.wiregoose.com.
  • Серверные службы находятся в домене api.wiregoose.com.
  • Фронтенд-приложение представляет собой статический набор файлов. Он перенаправляет все запросы к index.html статических файлов, если в wiregoose.com/* нет соответствующих файлов.
  • Nginx проверяет агент запроса и решает, является ли он сканером/ботом или обычным запросом. Обычный запрос обслуживается из статических файлов. Боты перенаправляются на службу SSR. Этот метод очень похож на настройку prerender.io Nginx.
  • Домены сертифицированы плагином для расшифровки, предназначенным для Nginx.

Мы настроили конфигурацию таким образом, что NodeJS выполняет основную работу, а Nginx обрабатывает все тривиальные части связи между службами. Мы также оборачиваем экземпляры NodeJS под диспетчер процессов PM2. Таким образом, мы максимально снижаем нагрузку на экземпляры NodeJS и предотвращаем простои. Все сервисы запускаются в продакшн с использованием конфигурации docker-compose.

Веб-сайт https://www.wiregoose.com/
Github https://github.com/apostolidhs/wiregoose2
Страница Facebook https://www.facebook.com/wiregoose/

использованная литература