Lim: Messenger for Mikrotik
Lim: Messenger for Mikrotik

Почему в роутеры не встраивают мессенджеры? Хотя бы самые простые, с передачей только текста. Это же как будто синонимы, маршрутизатор и мессенджер. Оба передают данные от отправителя к получателю. Уже ИИ встраивают в роутер, скоро видеокарту встроят, а мессенджеров нет. Или есть?

Я попробовал сделать мессенджер для роутера. От настольного hAP AC3 LTE6 я на время отстал, в этот раз играюсь с CHR на VPS и немножко с hAP_AX2. На CHR у меня одно ядро 2200MHz, 512мб оперативка, 16гб диск. Лицензия на CHR P1, но для текстовых сообщений думаю подойдёт и бесплатная с ограничением в 1мб скорости на портах.

Делаю всё в одном казане проекте Android Studio, клиентское приложение и серверная часть в отдельном модуле. Серверная часть "Limserver", это просто база данных SQL на HikariCP с 4 таблицами и HTTPS сервер. У сервера 8 рабочих потоков и 8 коннектов к базе данных. Можно через файл конфига server.properties задать свои значения потоков и коннектов к БД, кводы объёма дискового пространства для папки /media. Папка /media хранить пересываемые пользователями файлы. Сам серверный модуль получился всего 14 МБ. Чтобы запуститься в контейнере RouterOS, ему нужна Java-среда. Готовый образ JRE весит больше 150 МБ. Поэтому делаем такую сборку: сначала в JDK (eclipse-temurin:21-jdk-alpine) собираем минимально необходимый кастомный JRE-рантайм (только с нужными модулями), а затем запаковываем его вместе с JAR в alpine linux. Обязательно указываем таймауты HTTPS серверу, я выбрал 3 минуты. Уж очень слабо мой CHR принимает файлы иногда.

# Сборка кастомной JRE (Tree Shaking)
FROM docker.io/library/eclipse-temurin:21-jdk-alpine AS jre-builder

RUN $JAVA_HOME/bin/jlink \
    --add-modules \
java.base,\
java.sql,\
java.naming,\
java.management,\
java.logging,\
jdk.httpserver,\
jdk.crypto.ec,\
jdk.unsupported \
    --strip-debug \
    --no-man-pages \
    --no-header-files \
    --compress=zip-9 \
    --output /javaruntime

# Финальный легковесный образ
FROM docker.io/library/alpine:latest
WORKDIR /app

# Устанавливаем совместимость с glibc (для нативной либки SQLite в Alpine)
RUN apk add --no-cache gcompat libstdc++

# Копируем кастомную JRE и твой JAR
COPY --from=jre-builder /javaruntime /javaruntime
COPY limserver-chr.jar /app/limserver-chr.jar

# Создаем папки для монтирования (чтобы права доступа были верные)
RUN mkdir -p /app/db /app/media

# Запуск с ограничением памяти для роутера
CMD ["/javaruntime/bin/java", \
     "-Dsun.net.httpserver.maxReqTime=180", \
     "-Dsun.net.httpserver.maxRspTime=180", \
     "-Dsun.net.httpserver.nodelay=true", \
     "-Xms32m", "-Xmx96m", \
     "-jar", "/app/limserver-chr.jar"]

На выходе получается 71мб. Заливаем кипятком на CHR этот файл, создаём там же две папки для мессенджера, одна /db для базы данных, сертификата и настроек сервера server.properties, вторая /media для пересылаемых файлов. Для https сервера внутри контейнера, надо ещё создать самоподписной сертификат, его же можно добавить в клиентское приложение по вкусу. Сам контейнер я запускаю на 128мб в Memory High и 144мб в Memory Max. Указал бы больше, но нету больше.

Энергетическая ценность мессенджера

  • Все чаты только тет-а-тет, групповых нет.

  • Пересылка файлов любых форматов до 50мб, в том числе голосовые сообщения.

  • Есть уведомления и онлайн статусы собеседников.

  • Limserver хранит в БД в зашифрованном виде: сообщения, файлы, приватные ключи пользователей для синхронизации, хэши паролей пользователей для авторизации.

  • Limserver хранит в БД в открытом виде логины, отображаемые имена, публичные ключи.

  • Нет внешних сервисов, поэтому когда приложение на телефоне будет не активно, сервер будет опрашиваться раз в 15 минут Worker'ом для получения новых сообщений, не чаще.

  • Ваш Limserver должен работать на ip из локального диапазона, чтоб клиент смог к нему подключиться.

  • Самостоятельно на CHR можно дополнительно ограничить ip контейнера доступом долько в разрешённые ему сети

С текстовыми сообщениями и фотками проблем не заметил, с большими файлами тяжелее.

даже смайлики поддерживаются :)
даже смайлики поддерживаются :)

Все исходящие сообщения решил отправлять в 3х разных потоках, в зависимости от id чата, хотел дать возможность писать в один чат без проблем пока в другом чате отправляется видосик. Передача файлов с такими ограничениями памяти проходит довольно медленно, не зависимо от скорости сети. На сервере приходится после каждого принятого или отправленого файла чистить cache page, так как он, кэш, сам чистится только при удалении файла после успешной выгрузки получателю. Если этого не делать при моих размерах памяти в контейнере, после второго же файла 35+мб память (кэш) в контейнере получается почти полностью забита. И скорость загрузки/выгрузки начинает сильно падает. В качестве стрест теста я пересылал одновременно между телефоном и планшетом по 10 файлов размером по 35мб. Два устройство одновременно и заливали и качали файлы. В итоге 700мб трафика прошли через контейнер с 50мб свободной памяти за 30 минут.

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

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

Сильно с интерфейсом я не возился, просто добавил 4 цвета для сообщений собеседника на выбор. По максимуму постарался переиспользовать элементы UI. Например настройки чата открываются при дооолгом клике по чату. Тоже самое с записью голоса, доооолгий клик на + добавления файла. Кнопку отправить делать не стал. Все знают что вилку надо держать в левой руке, а отправлять сообщения кликом справа от ввода текста.

Мне интересней было поковырятся с UX, чтоб без лишних действий отправить сообщение. Для начала переписки между зарегистрироваными на вашем Limserver пользователями, надо просто в новый чат отправить логин собеседника, сервер сам создаст чат. Или дождаться первого сообщения от собеседника, оно тоже само создаст чат. Или для того чтоб отобразить скрытый чат, не надо искать кнопку найти чат или отобразить скрытые чаты, надо просто в новый чат написать логин собеседника, и чат всплывёт сам.

Изначально я делал мессенджер именно для CHR, но запускать его можно и на ПК с установленой Java. В этом случае не забудьте так же создать две папки db и media там же где будете запускать jar файл limserver, нафаршировать /db файлами настроек и сертификатом. Весь код серверной части Limserver и андроид клиента Lim можно посмотреть на гитхабе. Они там всегда свежие. Скачать готовые .tar файлы контейнеров там же. А видео инструкцию установки контейнера на ютюбе. Правда я её записал сильно заранее. К моменту публикации я уже думал что пройду закрытый тест в Google Play, но первую попытку завернули. Если кто то будет пробовать месенджер у себя и будет желание помочь пройти тест, напишите на почту указанную на гит.

Закуска

А для тех кто на диете или является рыцарем ордена одноразового кипячения чайника есть ARM64 вариант контейнера, работающий например на hAP_AX2, памяти в нём свободной правда остаётся всего 14мб, зато есть оперативки пол гига свободной. Можно нужно в ней создать ramDisk, переместить в него скачаный .tar файл и тогда уже создавать контенйнер. Иначе он не установится из за нехватки флеш памяти в роутере. Туда же в ramDisk примонтировать папку /media для файлов. Не забудьте в файле конфига server.properties указать квоты для папки media (максимум использования и минимум запаса свободного места), где бы вы её не примонтировали. Ещё я удалил все кости из рыбы логи из базы данных HikariCP уровня дэбаг, их там тьма. Может это не сильно облегчит работу процессору, но зато можно будет вдоволь насладиться оставшимися.

hAP_AX2
hAP_AX2

Комментарии (0)