Свой Firebase за 7$ или практический опыт внедрения Appwrite как сервера для мобильного приложения

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Когда речь идет о каких то готовых решениях в качестве сервера для мобильного приложения первое что приходит на ум это Firebase или же какие то решения от Amazon. Соглашусь, что этого бывает достаточно даже в рамках Spark тарифа Firebase. Однако, если хочется чего то большего, включая возможность расширять функционал сервера не только силами Cloud Functions, то для этих целей отлично может подойти Appwrite.

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

  • Kuzzle - из интересного, это реалтайм база данных

  • Purse Server - имеет массу различных адаптеров, включая адапер для push-уведомлений

  • Strapi - больше как CMS, но может есть что то интересное среди плагинов

  • Superbase - достаточно молодой, относительно аналогов, проект. Однако, активно развивается

Изначально, Appwrite привлек тем, как раз своей документацией, по которой не сложно ориентироваться и различными опциями рантаймов для функций. Сегодня я бы хотел уделить время именно Appwrite и подводных камнях с которыми пришлось столкнуться в процессе выхода в продакшн. Я не буду переписывать дословно что указано в документации или приводить огромные листинги кода, актуальная информация все равно будет официальной документации и готовых примерах на гитхабе, но расскажу о основных деталях развертки и о том что в документации не найти или легко пропустить.

Функционал

Интеграция

У Appwrite есть SDK для всех основных платформ которые могут пригодится iOS, Android, Web и Flutter. По сему не стоит особо беспокоится о интеграциях. Стоит заметить, что iOS фреймворк имеет минимальную версию 15.0, хоть спокойно может работать и на 13.0. Так что если нужно поддержать более древние версии iOS то можно форкнуть и поправить версию самостоятельно.

Если вам захочется самостоятельно поддержать API, то есть REST с GraphQL. Так же есть веб-сокеты, которые в документации называется Realtime - https://appwrite.io/docs/realtime

Пользователи

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

База данных

База данных хранится в MariaDB и, к моему сожалению, не имеет каких либо удобных инструментов для миграций. Однако, можно написать скрипты чтобы применить изменения массово, например, использовав готовый пример на питоне - https://github.com/appwrite/playground-for-python. Он спасал меня не малое количество раз, прежде чем я не начал полноценно встраивать функции. Так же стоит сделать ремарку по поводу пагинации - лимит запрашиваемых записей 100, максимальный offset - 5000. Поэтому, если у вас большая база и нужно полностью перебрать все записи, то лучше двигаться по страницам с помощью курсора - https://appwrite.io/docs/pagination#cursor-pagination.

Хранение файлов

Выбор места для хранения файлов достаточно велик: S3, DOSpaces, Backblaze, Linode, Wasabi ну или локально, что может быстро выйти за рамки дроплета. Так как мы разворачивали сервер на Digital Ocean то решили использовать DOSpaces, подключили конфиг и забыли. Стоит еще заметить, что можно подрубить антивирус в виде https://www.clamav.net/.

Функции

Функции доступны на обширном наборе языков - список в доках, выбор ограничен лишь env конфигом который поможет поддержать тот или иной рантайм. Функции удобно создаются через CLI, который может полностью заменить вам web-интерфейс.

Прочее

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

Установка

Заводится Appwrite достаточно просто. Достаточно запустить дроплет с ним в Digital Ocean и можно пользоваться. Однако, если нет желания тратить на него дроплет, то существует огромный Docker Compose конфиг. Редактируем конфиг с нужными вам volumes, добавляем .env файл и можно запускать.

Настройка

Настройка происходит с помощью изменения файла .env. Если вы устанавливали Appwrite сразу из Digital Ocean, то он будет находится по адресу /root/appwrite/.env. Особо править в нем ничего не надо. Как минимум указать _APP_DOMAIN_TARGET с адресом хоста. Можно еще настроить SMTP сервер, но не обязательно, особенно если не планируете, что пользователи будут регистрироваться. Так же, если планируется хранить много файликов, то хорошо бы подключить какой то из предложенных в конфигурации решений. Например, для DOSpaces это будет 4 поля:

_APP_STORAGE_DO_SPACES_ACCESS_KEY=
_APP_STORAGE_DO_SPACES_SECRET=
_APP_STORAGE_DO_SPACES_REGION=
_APP_STORAGE_DO_SPACES_BUCKET=

Тут же можно встретить настройки рантаймов для функций - _APP_FUNCTIONS_RUNTIMES . На данный момент доступны такие варианты: node-14.5, node-16.0, node-18.0, php-8.0, php-8.1, ruby-3.0, ruby-3.1, python-3.8, python-3.9, python-3.10, deno-1.21, deno-1.24, dart-2.15, dart-2.16, dart-2.17, dotnet-3.1, dotnet-6.0, java-8.0, java-11.0, java-17.0, java-18.0, swift-5.5, kotlin-1.6, cpp-17.0

На этом все. Можно заходить на ваш сервер, создавать админа и начать настройку первого проекта.

Проект

Сперва требуется создать организацию, в которых будут создаваться проекты. Очень удобно, например, если необходимо дать доступ к группе проектов клиенту. В проект нужно добавить приложения которые будут подключаться к серверу: iOS, Android, Web и пр. Так же есть возможность сгенерить токен для доступа к API.

База данных

Проект может содержать несколько баз данных. Например, для своего проекта я создал две базы. Одну для хранения токенов, вторую для хранения контента для юзера. При создании базы не очень очевидно, что можно самому выбрать id, тапом по кнопке под полем названия БД Database ID.

Форма создания базы данных
Форма создания базы данных

Свой ID очень полезен тем, что прописывая какие либо триггеры на события или же просто подключаясь к ней c клиента вам визуально будет видно что это за БД. Каждая БД содержит коллекции (таблицы) в которых будут наши данные. Тут так же можно вписать свой ID как и при создании самой базы данных. В настройках коллекции уже более развернутый список опций.

  • Documents - содержимое нашей коллекции. Лимит offset 5000 поэтому внизу может быть написано, что коллекция содержит 5000 документов, даже если у вас их в разы больше. Возможно это когда нибудь поправят.

  • Attributes - описание полей с их типами.

  • Indexes - нужны для ускорения доступа к базе данных. А так же просто необходимы если нужно получить данные в какой либо сортировке.

  • Activity - Показывает последние девайсы с которых были произведены изменения в бд, но не за все время.

  • Usage - Различные графики чтения, записи, удаления и пр. Не сильно актуальные данные, но при необходимости у Appwrite есть возможность отдавать стату на другие сервисы плюс есть API. На практике не проверял.

  • Settings - Тут можно поменять название, настроить права для групп пользователей. В моем случае мне не нужно было авторизовать или регистрировать пользователей приложения, поэтому доступ я дал практически полный, кроме записи для read-only коллекций.

Хранилище

Хранилище разделяется на бакеты. На каждый бакет, да и на каждый файл, в бакете можно настроить права доступа. Если вы будете хранить какие либо изображения, то для доступа к ним есть отдельный интерфейс который обрежет, отмасштабирует и даже добавит скругление - https://appwrite.io/docs/client/storage?sdk=web-default#storageGetFilePreview. Среди пул реквестов видел поддержку HLS, так что, возможно, в будущем будет возможность пошустрее грузить и видео файлы.

Функции

Для того чтобы создавать функции удобно использовать CLI Appwrite, но можно это сделать и через SDK. Для функций очень много различных примеров. На своем проекте мы использовали их для подготовки превью видео роликов (сжатие и обрезка через ffmpeg), которая запускалась при каждом изменении коллекции с видеороликами. А так же операции записи пуш токенов и отправке уведомлений.

Стоит заметить интересный момент. По умолчанию, в функцию передается токен пользователя который ее запустил, но если вам нужен какой то другой доступ, то ключи с токеном доступа необходимо указать самостоятельно. Иначе вы можете долго гадать почему же выполнение падает. По крайней, мере я гадал когда писал функции на питоне, приходилось смотреть логи контейнера через Docker. Если что то крашится и логов не видно, то логи контейнера вам помогут. Id активного рантайма указано в поле `Deployment ID`.

Push-уведомления

Серьезный недостаток Appwrite в том что у него нет поддержки пушей из коробки. Но для этого можно использовать другие решения и реализовать остальное функциями и базой данных. Для этого нам нужна будет коллекция где мы будем хранить пуши и функция которая позволит их писать. Я не стал разрешать пользователям читать в эту коллекцию, за это будет отвечать функция которая будет принимать id пользователя, платформу и токен пушей.

В качестве отправителя уведомлений я взял go реализацию appleboy/gorush и добавил ее в Docker Compose файл Appwrite.

gorush:
  image: appleboy/gorush
  container_name: push-server
  restart: unless-stopped
  networks:
    appwrite:
    runtimes:
  volumes:
    - ${PWD}/../gorush/config.yml:/config.yml:rw

Тут я добавляю доступ к сетям рантаймов и, на всякий, случай самомой appwrite.

При массовой рассылке пушей стоит учесть, лимиты offset значения у БД. Лучше собрать токены для рассылки путем пагинации через курсор о котором я поминал ранее (документация). Так же не плохо бы продумать механизм удаления неактивных пушей, так как у них есть свойство терять актуальность. К сожалению, с последним автоматического решения я еще не нашел. Только через парсинг логов gorush контейнера, выделения токенов которые провалились и удалением их из БД. Благо операция не такая частая и можно решить ее bash-ем + cron. Пользуясь логами, я удалил порядка половины всех хранившехся токенов.

Аналтика

К сожалению замены аналитики у Appwrite нет, но если хочется полностью отказаться от Fiebase можно посмотреть в сторону https://github.com/Countly/countly-server. Он так же умеет собирать краши и отправлять push уведомления. Уверен, это не единственное решние.

Заключение

Appwrite подающий надежны аналог Firebase который продолжает развиваться и имеет сильный потенциял. У них есть достаточно активный дискорд где можно задать вопросы по каждому модулю в различных чатах, что порой очень помогает. Наш проект c Appwrite находится в продакшене уже 3й месяц. При чем он переживал нагрузку в 17 тысяч пользователей в сутки на самом дешевом дроплете DigitalOcean-а и серьезных проблем с загрузкой я не заметил. Следил через Firebase Performance по отдельным моментам, такие как скорость загрузки видео с сервера. Сами запросы к нашему серверу Firebase автоматически не трекает если использовать SDK. В целом результат нас устроил. Не хватает только какого то дополнительного CMS для БД. Заполнять поля БД вручную бывает утомительно.

Источник: https://habr.com/ru/post/718574/


Интересные статьи

Интересные статьи

Привет, Хабр! Этот пост подготовили два разработчика Росбанка — Максим из команды развития фронт-офисных систем и Никита из команды интернет-банка. Речь пойдет о том, как мы делаем микрофронтенды. Сна...
С 16 по 19 мая команда сотрудников «Газинформсервис» принимала участие в кибербитве The Standoff, на стороне защиты. О том, как это было, рассказал участник проекта, Никита Платов инженер-проектировщи...
Дисклаймер: Я написал такую статью, какую сам хотел бы прочитать полгода-год назад, когда мы стартовали миграцию в облако. Мне бы она здорово помогла сэкономить силы, время и нервы – надеюсь, теперь п...
В советское время человек после вуза устраивался в контору и работал там чуть ли не всю жизнь. В наше время ситуация поменялась, но все еще существует мнение, что для карьерного роста лучше оставаться...
В новом дайджесте боремся с потерями пушей, разбираемся с музыкой Apple, изучаем работу звука в Android, экономим деньги при разработке игры, ищем приложение Росстата, отличаем плохой дизайн от х...