Схема генерации динамического изображения

Node.js внешний интерфейс Ресурсы изображений
Схема генерации динамического изображения

1. Предпосылки

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

Xnip2021-12-29_15-46-01 (1).jpg

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

Во-вторых, сравнение программ

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

2.1 Реализация клиента — html2canvas

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

sharp架构图优化.png

Но раз уж вы использовали html2canvas, то должны знать, что этот процесс не так уж и гладок. Как говорится в файле readme, он не обязательно на 100% восстанавливает внешний вид html-элементов на веб-страницах. Проявляется множество проблем:

а. Совместимость: несоответствие на разных концах,Некоторые свойства не поддерживаются

б) сгенерированное изображение неполное из-за медленной загрузки ресурсов

в) слишком долго

г. Комплексная отладка

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

2.2 Реализация сервера: Puppeteer

Поскольку у html2canvas так много ям, можем ли мы отказаться от схемы рендеринга в Canvas, но напрямую отображать html в веб-странице, а затем напрямую делать скриншот. Кукольник может сделать это за нас.

На самом деле Puppeteer — это браузер Chrome, которым можно управлять с помощью кода.Вы можете открыть вкладку Chrome через API Puppeteer, отобразить Html и сделать снимок экрана. Таким образом мы унифицируем среду генерации образов и решаем проблему совместимости.

sharp流程图.png

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

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

2.3 Другие реализации сервера

Мы также провели некоторые исследования других серверных решений (на основе NodeJS):

  • Инструменты для работы с изображениями (Jimp/Sharp):Этот тип инструмента представляет собой инструмент обработки графики, который в основном может выполнять такие операции, как растяжение, обрезка и наложение изображений.
  • Рисунок холста на стороне сервера (domjs+canvas-node/fabric.js):Такое решение похоже на процесс html -> canvas -> изображение, но теперь этот процесс обрабатывается на стороне сервера.
  • webshot (инструмент, похожий на Puppeteer):Он работает как безголовый браузер.

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

2.4 Окончательное решение: Голанг

Проанализировав приведенные выше различные схемы динамической генерации изображений, мы обнаружили, что будь то генерация на стороне клиента или генерация на стороне сервера через Nodejs + Puppeteer и т. д., совместимость и производительность не очень хороши. Итак, можем ли мы вырваться из присущего интерфейсу образа мышления, выбрать внутренний язык, преодолеть ограничения, налагаемые NodeJ (не подходит для операций с интенсивным использованием ЦП), и эффективно генерировать изображения?

Благодаря исследованиям большинство языков программирования имеют библиотеки, поддерживающие синтез изображений (например, imagemagick), учитывая, что Nodejs не подходит для таких ресурсоемких задач, мы наконец принялиРендеринг Golang + хранилище данных NodeJsдля генерации изображений. Почему стоит выбрать Golang: Причина очень проста, главная причина в том, что относительно просто ознакомиться с синтаксисом, интерфейс можно использовать быстро, а принцип можно напрямую скомпилировать вМашинный код, не зависит от других библиотек, быстрое время компиляции, высокая эффективность разработки и работы, а также некоторые концепции сопрограмм;

3. Конкретные решения

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

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

Xnip2021-12-29_15-29-39.jpg

3.1 Общий дизайн

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

платформа визуализации: Создайте новый проект и используйте слои для создания желаемого изображения;

сервисный уровень nodejs: Сохранение, чтение и другие операции с данными слоя;

слой рендеринга изображений golang: Слой данных для создания изображений;

image.png

Глядя на приведенное выше изображение слева направо, слева показан процесс генерации внешнего изображения, а справа — промежуточный процесс управления внутренним слоем изображения. Оба читают данные через нижнюю базу данных, а наши данные - это информация слоя, хранящаяся в формате json. Вся система (и внешняя, и внутренняя) читает и модифицирует эти данные слоя. Формат данных Вероятно, следующий:

[
    {
        "type": "image", // 类型。比如:image、text、canvas
        "name": "画布", // 自定义的名称
        "w": 251, // 宽度
        "h": 323, // 高度
        "x": 0, // x 偏移量
        "y": 0, // y 偏移量
        "paramName": "", // 绑定的变量名
        "content": "xxx", // 内容
        "color": null, // 颜色
        "opacity": 1, // 透明度
        "bgColor": "rgba(255, 255, 255, 0)", // 背景色
        "contentType": "img", // 内容的类型
        ...
    }
]

3.2. Внутреннее — визуальная платформа конфигурации

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

Kapture 2022-01-04 at 20.32.35.gif

Возможности, предоставляемые платформой: Обеспечьте встроенные компоненты: компонент изображения, компонент текста, компонент QR-кода

Перетаскивание компонентов: вы можете быстро изменить положение компонентов, перетащив их

Настройки свойств: вы можете установить различные свойства для компонентов, такие как ширина и высота, цвет, выравнивание

Настройки параметров: вы можете привязывать параметры к компонентам и изменять параметры в URL-адресе при их использовании для динамического отображения.

Режим разработчика: когда встроенные функции платформы не могут удовлетворить потребности, вы можете использовать режим разработчика для достижения

Сгенерируйте json, описывающий информацию о слоях для серверной генерации изображений.

Функция автоматического сохранения

3.3 Внешнее — генерация изображений Golang

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

image (1).png

  1. Сборка данных: синтез данных слоя и переменных параметров для получения данных слоя графика.
  2. Генерация слоя: в настоящее время существует три типа слоев (в будущем их будет больше), которые обрабатываются по-разному:
    1. Текстовый слой: создание текстового слоя в соответствии с данными слоя (шрифт, размер шрифта, насыщенность, цвет...)
    2. Слой изображения: изображение будет кэшировано локально, если кеш есть, то оно будет прочитано из кеша, в противном случае оно будет получено из сети. Затем создайте слой изображения на основе данных слоя (прозрачность, закругленные углы...)
    3. Слой QR-кода: используйте инструмент генерации QR-кода, чтобы преобразовать URL-адрес в слой изображения QR-кода.
  3. Состав слоя: слой изображения и текстовый слой накладываются друг на друга по порядку, и, наконец, создается и возвращается изображение.

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

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

4. Резюме и перспективы

строить планы совместимость представление Эффективность разработки
Интерфейс canvas2html генерирует изображения Низкий высоко Низкий
Генерация сервера Puppeteer+Nodejs высоко Низкий Низкий
Окончательный план реализации Golang + Nodejs высоко высоко высоко

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

Надеюсь, эта статья поможет вам.