Перейти до контенту
Усі відповіді

Телеметрія там, де звʼязок падає на години

Телеметрію зазвичай проєктують в офісі, де інтернет є завжди. Потім її ставлять на придорожню мийку або промисловий майданчик, де мобільний звʼязок зникає щотижня, іноді на пів дня, і виявляється, що система вміє лише два стани: «усе добре» і «немає даних». Нижче — як зробити так, щоб обрив звʼязку був звичайною подією, а не аварією, і щоб після нього дані були повними, а не дірявими.

Обрив — це нормальний стан

Перше рішення, від якого залежить усе інше: обʼєкт має працювати сам, без сервера. Термінал приймає оплату, контролер запускає пост, події пишуться локально. Сервер — це місце, куди дані доходять, а не місце, де вони народжуються. Якщо обʼєкт не може працювати без сервера, ніяка телеметрія не врятує: вона просто зафіксує простій.

У мережі мийок, яку ми супроводжуємо, термінали побудовані саме так: приймають оплату без звʼязку і досилають транзакції, коли канал повертається. Через них пройшло 14 мільйонів платіжних транзакцій, і частина з них ішла саме цим шляхом — спершу локально, потім на сервер.

Друге рішення: дані мають бути повними, а не свіжими. Пропущені пʼять хвилин показників — не страшно. Пропущена оплата — це гроші, які не зійдуться на звірці. Тому черга подій має бути надійною для платежів і може бути «з втратами» для показників, які все одно оновлюються щохвилини.

Буфер: що зберігати і скільки

Локальний буфер — це не структура в памʼяті, яка зникне при перезавантаженні, а сховище на диску, що переживає відключення живлення. На обʼєкті живлення падає частіше, ніж звʼязок, і саме в момент, коли звʼязку теж немає.

Розмір буфера рахується від найдовшого обриву, який ви готові пережити без втрат, а не від середнього. Якщо звʼязок може зникнути на добу, буфер має вмістити добу подій усіх типів на найзавантаженіший день. Це небагато байтів, але це має бути порахованим числом, а не припущенням.

Коли буфер повний, потрібне правило: що викидати. Правильна відповідь — старі показники, ніколи не платежі. І це правило має бути в коді, а не в голові. Окремо: буфер, який ніколи не спорожняється, бо сервер повертає помилку на одну подію і черга зупиняється на ній, — найчастіший спосіб втратити тиждень даних. Проблемна подія відкладається вбік, решта йде далі.

Годинник, який бреше

Контролер без синхронізації часу дрейфує, і за місяць може розійтись із сервером на хвилини. Поки звʼязок є, це непомітно: сервер ставить свою мітку при отриманні. Коли події досилаються після обриву, мітка отримання вже нічого не означає, і залишається лише мітка обʼєкта — та, що дрейфує.

Тому кожна подія має нести дві мітки: час обʼєкта і час отримання сервером. Різниця між ними в момент, коли звʼязок є, — це виміряний дрейф, і його можна застосувати до подій, досланих із буфера. Час зберігається в UTC; місцевий час — лише для показу.

Окремий випадок — обʼєкт, який перезавантажився без батарейки годинника і прокинувся в 1970 році. Такі події видно одразу, якщо система їх шукає, і вони губляться назавжди, якщо не шукає. Правило просте: мітка часу, раніша за дату встановлення системи, — це помилка, а не подія.

Дедуплікація

Досилання після обриву майже гарантує дублікати: обʼєкт відправив, сервер отримав, підтвердження не дійшло, обʼєкт відправив ще раз. Якщо сервер рахує обидві, виручка за день подвоюється саме в ті дні, коли звʼязок був поганий, — і це найгірший момент для помилки, бо ті дні і так важко звірити.

Кожна подія повинна мати ідентифікатор, який обʼєкт створює сам у момент події, а не сервер у момент отримання. Сервер, отримавши подію з відомим ідентифікатором, відповідає «прийнято» і нічого не робить. Обʼєкт, отримавши «прийнято», видаляє подію з буфера. Це весь механізм, і він має бути з першого дня, бо додати його пізніше означає перерахувати історію.

Ідентифікатор має бути унікальним між обʼєктами, а не лише всередині одного. Номер поста плюс лічильник, який скидається при перезавантаженні, — не унікальний. Ідентифікатор обʼєкта, час і випадкова частина — так.

Що має показувати панель

Найважливіше число на панелі обʼєкта — не виручка і не температура, а вік останніх даних. «Пост 3: оновлено 4 хвилини тому» і «Пост 3: оновлено 6 годин тому» — це два різні стани, і панель, яка показує в обох випадках одне й те саме зелене значення, бреше.

Кожен показник має вік, і панель показує його явно — кольором, підписом, як завгодно, але помітно. Значення, старше за певний поріг, показується як застаріле, а не як актуальне. Це стосується і зведених чисел: виручка за сьогодні по мережі, в якій один обʼєкт шість годин без звʼязку, — це не виручка, а нижня межа, і панель має так і казати.

Друга річ — розмір буфера на кожному обʼєкті. Буфер, що росте, означає обрив, який ще триває. Буфер, який не спорожнився після відновлення звʼязку, означає помилку в досиланні. Обидва стани мають бути видимі без того, щоб хтось заходив на обʼєкт по SSH.

Сповіщення, які не кричать даремно, і вибір каналу

Сповіщення про обрив звʼязку, яке приходить при кожному обриві, перестають читати за тиждень. Правило, яке працює: сповіщати не про факт обриву, а про його тривалість понад поріг, і поріг ставити від того, скільки обʼєкт може працювати сам. Обрив на десять хвилин — нічого. Обрив, довший за половину буфера, — так.

Друге правило: сповіщати про те, що вимагає дії, і мовчати про решту. «Звʼязок відновлено» — не вимагає дії, це для журналу. «Буфер не спорожнюється після відновлення» — вимагає. «Пост не дав жодної події за годину в робочий час» — вимагає, і це часто корисніше за будь-яке сповіщення про звʼязок, бо ловить і обрив, і зламаний пост, і зламаний термінал.

Щодо каналу. Мобільний звʼязок дешевий, ставиться за день і падає. Дротовий — дорогий у прокладанні, але стабільний. Наш досвід: якщо на обʼєкті є можливість дротового каналу, він окупається; якщо ні — мобільний із резервом від другого оператора і телеметрія, побудована як описано вище. Помилка — розраховувати на мобільний канал як на постійний і будувати систему, яка без нього стоїть.

Часті питання

Скільки має вміщати буфер
Стільки, скільки подій обʼєкт створює за найдовший обрив, який ви готові пережити, на найзавантаженіший день, із запасом. Це число треба порахувати для вашого обʼєкта, а не взяти типове. Для платежів — без втрат; для показників, які оновлюються щохвилини, допустимо зберігати рідше.
Чому виручка після обриву звʼязку вища, ніж мала б бути
Найімовірніше, дублікати: обʼєкт дослав подію, яку сервер уже отримав, але не встиг підтвердити. Ліки — ідентифікатор події, створений на обʼєкті, і сервер, який ігнорує повтори. Якщо цього немає — історію доведеться чистити вручну, і краще зробити це один раз, додавши механізм, ніж щомісяця.
Мобільний канал чи дріт
Дріт, якщо його реально прокласти. Мобільний — із резервом і з телеметрією, яка переживає обриви. Найгірший варіант — мобільний без буфера: він працює до першого довгого обриву, і саме тоді ви дізнаєтесь, що дані за той день втрачено.

Ще відповіді

Оновлено: 2026-09-22