Розробка серверної частини мобільних додатків. Розробка мобільних програм: Синхронізація з сервером Розробка серверної частини програми

22.04.2021 Безпека

БЕКАПИ

Навіщо потрібні бекапи на мобільній платформі

Фахівці знають, наскільки часом ненадійні мобільні програми на 1С: будь-якої миті можуть виникнути помилки, через які бази користувачів просто руйнуються. Одночасно ми стикаємося з ненадійністю самих пристроїв: їх можна розбити, втратити, можуть вкрасти, а користувачі хочуть зберегти свої дані. І аж до версії 8.3.9 ми не мали платформного механізму збереження бекапу.

Оскільки раніше користувачі не мали кнопки «зберегти копію», розробникам програми Boss довелося самим робити бекапи. Як ми це зробили?

Самі дані бази ми зберігаємо як ХML.

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

Таким чином, розробники додатково себе страхують. Якщо щось пішло не так, і раптом зламався механізм створення копій на Google-Диску або Яндекс-Диску, завжди можна сказати користувачеві, що в Наразірозробник розбирається з помилкою, а поки що він може зберегти дані альтернативним способом. І користувачі залишаються задоволені, тому що вони можуть бути спокійними за свої дані.

Обов'язково потрібно зробити акцент на хмарні сервіси , тому що якщо пристрій загубиться або розіб'ється, а користувач зберігав копію на цьому ж пристрої, дані будуть втрачені.

Також ми обов'язково нагадуємо користувачеві про необхідність створення бекапів.

Як зберігати копії, якщо змінюється конфігурація?

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

Є кілька варіантів зберігання цієї структури даних, зокрема її можна зберігати у самій конфігурації. Тобто при випуску кожної нової версії зберігати структуру метаданих попередньої версіїмакет у конфігурації.

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

Тому у випадку з мобільним додатком кращий інший шлях - зберігати структуру метаданих безпосередньо у файлі з даними. На виході у нас виходить ось такий файлик, де спочатку ми зберігаємо якісь допоміжні дані - версію конфігурації, схему конфігурації, межі послідовностей, вже після записуємо самі дані користувачів в формат XML. Причому в розділі файлу "Допоміжні дані" можна зберігати й інші важливі дані, які з якихось причин не вдалося записати в XML.

Беремо ту схему даних, яку зберегли у файл, і на її підставі будуємо пакет XDTO для читання файлу. Створюємо аналогічний об'єкт у базі даних, заповнюємо його, виконуємо обробки дозаповнення при оновленні, і зберігаємо вже готовий об'єкт у базу даних.

Нижче на зображенні можна подивитися підказку, як красиво записати модель XDTO даних конфігурацій. У компанії, що випустила програму Boss, експериментували з цим, знаходили кілька способів, але зупинилися саме на такому варіанті записування схеми метаданих. Коли відкривається сам файл із даними, там видно звичайний структурований XML, читальний, в якому перераховані всі метадані додатки.

// Запис схеми конфігурації Модель XDTO = Фабрика XDTO. Експорт Моделі XDTO ("http://v8.1c.ru/8.1/data/enterprise/current-config"); ФабрикаXDTO.ЗаписатиXML(ФайлВивантаження, МодельXDTO); // Читання схеми конфігурації Модель XDTO = Фабрика XDTO. ФабрикаВивантаження = Новий ФабрикаXDTO(МодельXDTO);

Щоб убезпечити користувача, потрібно обов'язково перепитувати його, а чи потрібно відновлення бекапа. Може, він просто експериментував і натискав на всі поспіль кнопочки у додатку:) І зараз поточні дані у нього можуть загубитися. Тому ми завжди при виконанні потенційно "небезпечних" дій уточнюємо, а чи справді він цього хоче і як це має відбуватися. Користувач повинен усвідомлювати свої дії.

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

Однак користувачі використовують бекапи не завжди так, як ми від них очікуємо :) Вони дуже часто використовують їх для того, щоб просто відкотити дані назад. Це правда дуже дивна поведінка, але користувачам мобільних додатківліньки розбиратися, де вони могли припуститися помилки при введенні даних, і вони просто відкочують дані назад і знову заводять дані за поточний день. Проаналізувавши статистику роботи з програмою Boss, ми усвідомили, що це нормальна практика і така поведінка користувачів зустрічається частіше, ніж ми могли припустити.

І якщо у вас використовується синхронізація з іншими пристроями, ви повинні це обробити. Тут є кілька шляхів вирішення:

  • розірвати зв'язок із сервером, уточнюючи, що дані на ньому залишаться такими, як були, а копія відновиться лише на пристрої користувача;
  • краще для користувача – дати йому відновити копію відразу на всіх пристроях, попередньо прописавши такі механізми.

Тут є ще один момент. Досі ми бекапи зберігали самі, контролювали весь процес, прямо в коді відловлювали дії користувача, коли він натискав кнопку «зберегти копію». Все це можна потім опрацювати. У платформі 8.3.9 з'явилася можливість зберігати бекапи саме засобами платформи. І користувач робить це без нашого відома. Якщо використовується синхронізація з центральною базою, потрібно обов'язково обробити такий сценарій. Ми повинні якось на своєму сервері дізнатися, що користувач відновив раніше збережену копію і маємо видати йому якесь рішення. Ми не можемо собі дозволити, щоб дані розсинхронізувалися.

ОБМІНИ

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

Але якщо ми говоримо про масову програму, де багато баз даних, у кожної з яких дуже багато користувачів, ситуація ускладнюється. Користувачі завантажили програму з маркету, і вони хочуть синхронізуватися один з одним. Наприклад, чоловік скачав програму для обліку особистих фінансів, і тепер хоче, щоб дружина теж підключилася, і вони разом працювали в одному додатку. Користувачів багато, додаток розвивається, зростає, і з'являється необхідність у великій кількості баз даних. Як це все організувати? Користувачі не будуть персонально звертатися до розробників, щоб ті створили для них окрему базу та включили можливість синхронізації. Вони хочуть натиснути на кнопку, і щоб все відразу ж запрацювало. В цей же момент.

Як вчинити? Тут на допомогу приходить механізм поділу даних. Він дозволяє організувати єдину базу даних, де є одна загальна конфігурація, але при цьому в рамках однієї загальної бази зберігається багато баз користувачів.

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

Як це зробити? Перше і найпростіше рішення – написати свою серверну базу із цим механізмом. Коли наша компанія починала робити програму Boss та обміни в ній, у першій версії ми так і зробили: написали серверну базу з механізмом поділу даних. Все працювало, тим більше, що нічого складного не було - роздільником баз є загальний реквізит.

Але потім ми зрозуміли, що винаходимо велосипед:) Насправді вже готове рішення, причому в ньому вже враховані моменти, про які ми ще навіть не думали. Це 1С: Фреш.

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

Загалом Фреш для нас – щось нове та цікаве. Потихеньку ми намагаємося розібратися в ньому, але здебільшого ми просто задоволені його роботою.

Передача даних. Як реалізувати її для обміну між пристроями

Платформа надає два механізми - це SOAP та http сервіси. Тут є аспекти, як звертатися до цих сервісів, коли задіяний механізм поділу даних. Зокрема, потрібно додати параметри, які вказують конкретний номер області, до якої ви звертаєтесь, тому що на ім'я користувача платформа не може визначити, до якої бази звертатися. Крім того, той самий користувач може працювати з кількома базами в рамках єдиної бази (див. картинку).

Щодо сервісів, у додатку Boss реалізовано миттєвий обмін: один користувач вводить дані, а інший їх отримує. Користувачі мобільних додатків звикли, що все відбувається миттєво, тому ми задумалися, яким краще сервісомкористуватися - SOAP або http. Ключову роль зіграла швидкість з'єднання. У http швидкість з'єднання набагато вище, а підключаючись по SOAP, ми отримуємо опис сервісу, який важкий і довго вантажиться. У платформи є спосіб зберігати опис сервісу, але через параметри, які ми додаємо динамічно, ми не можемо використовувати WS-посилання. Крім того, звернення до http-сервісів зручніше та гнучкіше, на наш досвід.

Отже, наша мета – реалізувати обмін у режимі реального часу. Тобто ми намагаємося не робити так, щоб користувачеві довелося зайти кудись, натиснути на якусь кнопку, думати про те, наскільки актуальні дані, чи повинен він проводити актуалізацію ... У користувачів дані повинні бути актуальні. Вони так звикли, працюючи в месенджерах – один дані відправив, інший їх одразу отримав. Все відбувається миттєво. Те саме стосується додатків, що стосуються бізнесу: один продавець оформив продаж, інший повинен відразу побачити актуальну ситуацію, ніяких дій при цьому не роблячи.

Тому в Boss використовуються для обміну фонові завдання. Після кожного запису даних до бази, запускається фонове завдання, яке ініціює обмін. Перша частина - надіслати дані на сервер. Потім інші пристрої повинні дізнатись, що є нові дані. Для цього ми використовуємо PUSH-повідомлення. Ця схема вже працює і вона працює досить швидко.

Але ми захотіли ще швидше, оскільки працюємо в режимі реального часу та даних у нас, як правило, небагато. У нас маленькі XML, але при цьому ми відправляємо з першого пристрою на сервер повідомлення з цими даними, сервер відправляє PUSH на інший пристрій, а то другий пристрій після отримання PUSH ініціює обмін зі свого боку, звертається до сервера і запитує дані, отримує ці дані і потім надсилає відповідь, що дані отримані. Це довго, а самих даних було зовсім небагато.

Ми замислилися, як можна прискорити цей процес.

Для цього ми розібралися, що містить у собі PUSH, як його ще можна використовувати. Виявилося, що PUSH містить такі поля, як дані та текст. У документації iOS та Android вказані обмеження за розміром PUSH-повідомлень, але нам цього здалося мало і ми захотіли досвідченим шляхом у всьому розібратися. І ми перевірили, що для iOS сума допустимих символів становить 981 знак, а для Android – 3832 символи. В останньому випадку обмеженням можна користуватися, в такий обсяг можна впхнути один або кілька об'єктів бази. І тоді розробники компанії змінили трохи схему. Коли даних небагато, ми відправляємо їх з одного пристрою, отримуємо їх на сервері, там пакуємо їх в PUSH і прямо в ньому відправляємо на інший пристрій. Схема стала коротшою, а обмін став відбуватися ще швидше:)

Важливий момент використання PUSH – не дратуємо користувачів.

Дуже легко позбутися такої ситуації: просто не надсилати користувачеві багато PUSH-повідомлень:) Якщо він працює зараз у додатку, надсилати багато повідомлень можна. Коли платформа працює, користувач не бачить PUSH, все відбувається автоматично. А ось коли програма закрита, у клієнта з'являється багато непрочитаних повідомлень. Тому в жодному разі не можна відправляти наступні PUSH, поки не отримано відповідь від пристрою, що програма працює, активно та попередній PUSH вже оброблений.

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

Подивімося на прикладі реєстрації пристрою, що відбувається в додатку, коли користувач хоче зареєструватися. Він веде облік якийсь час, він ввів досить багато даних, але потім хоче, щоб продавець теж працював з цією базою. Користувач натискає кнопку «зареєструватися». Спочатку все було дуже просто: взяли його дані, записали на сервері, і, будь ласка, можна працювати та підключати користувачів. Але потім ми зіткнулися із ситуацією, коли в деяких користувачів бази даних на пристрої на момент реєстрації вже сильно розросталися. І це схема не працювала, т.к. поки йшов запис усієї бази на сервері, спрацьовував тайм-аут з'єднання або просто обривався інтернет. Тому ми замінили один синхронний виклик на багато коротких. Наразі дані діляться, а не передаються всі за один раз. Ми не чекаємо в жодному разі, поки сервер оброблятиме і записуватиме дані. Відправили дані, отримали відповідь, що отримані дані, закрили з'єднання. Періодично треба опитувати сервер, що там і як відбувається, а на сервері працює фонове завдання, яке записує отримані дані. Таким чином, виходить багато викликів сервера, але ми маємо гарантію того, що все пройде добре. І ні таймаути, ні нестабільність інтернету не завадять вивантажити всі дані на сервер.

ОБНОВЛЕННЯ

Обмін між пристроями з різними версіями програми

Оскільки ми говоримо про масовий додаток, що випускається в маркети, треба враховувати деякі особливості процесу оновлень та обміну даними.

Якщо ви випустили додаток для одного підприємства і вирішили його оновити, то зазвичай ви просто даєте команду, щоб усі співробітники дружно встановили новий додаток. З користувачами, які завантажили програму з маркету, так зробити не можна. Ви взагалі не можете їм вказувати, що робити. Наприклад, вони працюють у додатку і не хочуть оновлювати його ні зараз, ні взагалі ніколи. У них не варто автооновлення, тому цілком звичайна ситуація, коли до центральної бази підключено кілька пристроїв, і всі вони з різними версіями. Ще одна причина такого явища – час публікації в маркетах: воно різне для iOS та Android. Ми часто впроваджуємо ключові штуки, наприклад, виправляємо критичні помилки, і не хочемо чекати, поки iOS перевіряє два тижні нову версію, ми хочемо хоча б тільки для Android, але випустити оновлення зараз.

Ми не маємо права командувати користувачами. Якщо вони хочуть, то оновлюються, а якщо ні – нічого не роблять. На малюнку видно співвідношення установок програми Boss за версіями GooglePlay, а також статистика з нашого сервера - реальне співвідношення версій програми, які встановлені на пристроях, що обмінювалися з сервером даними протягом останнього тижня. Ось такий набір, із яким треба працювати. Це різні версіїта різні метадані. І нам треба організувати нормальний обмін при цьому:)

Перед розробниками стоять такі завдання:

  • Потрібно, щоб усе це працювало. Користувачі не повинні відчувати дискомфорт від того, що вони забули оновитися. Вони взагалі не повинні цього помічати. Обновилися - стало краще, та й добре.
  • Ми повинні забезпечити збереження даних. Наприклад, в одного користувача з'явився довідник та новий реквізит, а в іншого ще немає. При цьому якщо користувач, який не має нових реквізитів, змінить у себе на пристрої щось, то на інших пристроях дані не повинні зникнути.
  • Потрібно забезпечити актуалізацію даних, коли ми переходимо на нову версію. Коли користувач вирішить, що він готовий оновитися, у нього автоматично повинні з'явитися нові відомості, яких у нього не було тільки тому, що у нього була стара версія.

Як ми це зробили?

1. Ми використовуємо на сервері 2 плани обміну. Перший – для обміну між пристроями, а другий – для оновлень. Наприклад, ми відправили довідник користувачеві, але він не має одиниць виміру, тобто неповні дані. Ми маємо запам'ятати це. А коли він оновиться, ми повинні надіслати йому всі ті відомості, яких він не мав. Для цього потрібен другий план обміну.

2. Для запису та читання об'єктів ми використовуємо той же механізм, який використовується для бекапів, тобто зберігаємо версію метаданих. В даному випадку ми працюємо з сервером, і ми можемо дозволити собі прямо в конфігурацію додавати все, що завгодно, тому просто у вигляді макетів додаємо в конфігурацію схеми метаданих у міру розвитку програми.

Як моніторити масові помилки під час обміну та на сервері

По-перше, треба контролювати доступність самого сервера. Із серверами таке буває – вони падають. Ми не вигадували нічого особливого для моніторингу, а просто знайшли робота в телеграмі, який кричить, якщо щось не так. Він щохвилини перевіряє працездатність сервера, і якщо сервер недоступний, починає кричати, адміни це бачать і піднімають сервер.

Також ми збираємо лог помилок з журналу реєстрації. Теж нічого надприродного - кожні три години збираємо лог помилок, відправляємо їх на пошту, періодично їх переглядаємо. Це допомагає бачити часті проблемита якісь виняткові ситуації. Не складно переглядати пошту, відстежувати та швидко виправляти помилки. Але це дозволяє оперативно виявляти та вирішувати проблеми, які можуть розростатися зі зростанням баз даних.

Ще важливий момент- обов'язково надавати користувачеві можливість "поскаржитися". Це покращує наш статус у їхніх очах і рятує нас. Є користувачі, як ми їх називаємо, "істерички", які за найменшої помилки починають надсилати нам на пошту купу повідомлень, що нічого не працює, база не завантажується, все страшно погано. Але іноді вони реально нас рятують, бо знаходять часом такі баги, які інші ще не виявили дивом, серйозні баги.

Користувача не можна лякати. Не страшними повідомленнями, нічим іншим. Їм треба гарно все пояснювати та пропонувати поскаржитися. А ми обіцяємо все вирішити. Тоді й користувачі задоволені, адже вони бачать, що про них дбають, і одразу вірять, що їм допоможуть:)

Ця стаття написана за підсумками доповіді, прочитаної на конференції INFOSTART EVENT 2016 DEVELOPER. Більше статей можна прочитати.

У 2020 році запрошуємо всіх взяти участь у 7 регіональних мітапах, а також ювілейній INFOSTART EVENT 2020 у Москві.

Розробка серверної частини програми

Вступ

Присутність в інтернеті стала потребою для сучасних компаній. Без цього неможливо побудувати повноцінну взаємодію з клієнтами. Часто для вирішення подібного завдання вдаються до створення клієнт-серверних додатків. Кожна з них складається з клієнтської частини та Back-end. Під останнім терміном мається на увазі серверна частина програми. Якщо надалі потрібно самостійно змінювати контент мобільної програми, то Back-end має бути створено особливо якісно. Компанія Appomart гарантує виконання поставлених завдань відповідно до вимог. Тому, замовляючи створення серверних програм, можете бути впевнені в належному результаті.

Навіщо потрібен Back-end?

Розробка клієнт-серверних додатків передбачає створення двох частин. Перший, Front-end, приймає запити від користувачів. Вона видно з екранів мобільних пристроївклієнтів. Друга, серверна програма, обробляє отримані запити, виконує роль адміністративної панелі. Тут зберігаються бази даних, логіка програми. Без цього не буде працювати жодна клієнт-серверна програма. По суті Back-end – це серце програми. Це інтелект, який відповідає за обробку запитів клієнтів, швидкість роботи програми. Тому важливо, щоб архітектура серверної програми була продумана до дрібниць, щоб навіть високонавантажені сервіси працювали безперебійно та швидко.

Як вибрати мову програмування?

У ході підготовки технічного завдання(Частини робочої документації за проектом), архітектор проектує систему баз даних і зв'язків, описує об'єкти та їх властивості, а також розробляє необхідні методи сервера (запити, якими будуть "користуватися" мобільні додатки звертаючись до сервера).

Важливість документації та "кинуті" проекти

В Appomart досить часто звертаються замовники, яких "кинули" з тих чи інших причин інші підрядники. І ми беремо чужий, часом навіть некоректно працюючий проект, здійснюємо його аудит і подальше доопрацювання та підтримку. У процесі вивчення вихідного кодуі матеріалів, отриманих від замовника, ми стикаємося з тим, що багато розробників навмисно не документують методи сервера, щоб прив'язати до себе клієнта, за рахунок несумірності трудовитрат передачі проекту на підтримку іншому розробнику, через відсутність документації до серверної частини, а часом просто з- через непрофесіоналізм. Цей факт, на жаль, є не лише сумним, але й поширеним. Замовнику, в цьому випадку, необхідно оплачувати розробку документації за існуючим проектом, а також аудит вихідного коду, перш ніж можна буде судити про працездатність, зручність та доцільність підтримки проекту. Співробітники Appomart завжди ведуть електронну документацію методів серверної частини у форматі, який підтримує Postman і Swagger, для подальшого використання.

Як перевірити підрядника до підписання договору?

Ми закликаємо Вас уважно вибирати підрядника, і орієнтуватися не тільки на привабливу ціну, а й на перелік документів, які ви отримаєте разом з проектом, а також умови передачі вихідного коду, та покриття коду коментарями, схеми баз даних (будь то Mongo DB чи MySQL ). Запорукою успіху, як правило, стає грамотна робоча документація, яка явно вказує на вимоги до переданої Вам по завершенню кожного з етапів роботи матеріалів.

Особливості розробки

PHP для серверної частини

Створення серверної частини програм (не плутати з серверами як "залізом" або комп'ютерами, оскільки йдеться про програмну частину) вимагає специфічних професійних навичок та знання мови програмування, яка застосовується на стороні сервера. Якщо розглядати приклади клієнт-серверних додатків, то видно, що користується популярністю PHP. Це безперечний лідер у галузі розробки серверних програм. Цією мовою написано в тій чи іншій конфігурації більше половини сайтів у світі. PHP зручний для розробки та підтримки, і крім того існують спеціальні framework-і для прискорення розробки на PHP.

Framework

Framework (програмна платформа) - використовується для систематизації та підвищення рівнів абстракції, що дозволяє зробити проект більш гнучким та масштабованим. Однак, варто розуміти, що рамкароботи повинна бути обрана коректно, на основі глибинного аналізу робочої документації проекту, без якої неможливо розробити якісний продукт.

Delphi, JAVA, Python

Є інші мови, які використовуються для створення Back-end. Так, поширені створені в середовищі Delphiсерверні програми. З її допомогою програма отримує покращену налагодження, в середовищі також просто сформувати унікальні програми, передбачено візуальне створення, що дає змогу зробити гарний, зрозумілий та зручний інтерфейс. Також популярність набули серверні програми на Java. Такі легко доповнюються, легко виконуються на будь-яких платформах та відрізняються гідним рівнем безпеки. Ще однією популярною мовою вважається Python. Серверні програми з його допомогою створюються швидко, просто, без серйозних витрат.

Розповсюдження

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

Створимо клієнт-серверний додаток Android, iOS якісно та вчасно

Розробка "під ключ"

Програмісти Appomart досвідчені та кваліфіковані, щоб реалізувати завдання найрізноманітніших рівнів. Ми однаково добре реалізуємо соціальні мережі, високонавантажені бізнес-проекти або програмну частину для невеликих стартапів. При необхідності ми створимо клієнтську частину програми під управлінням Android, iOS відповідно до наявних потреб, що висуваються вимогами.

Back-end в Appomart

Наші програмісти працюють з різними технологіями і роблять це однаково добре. В Appomart ви можете замовити клієнт-серверну програму на Java, PHP і Node.JS. Системні вимоги аналізуються для кожного із проектів індивідуально, що дозволяє забезпечити оптимальну продуктивність програми. Створимо клієнт-серверну програму Java, PHP і Node.JS з нуля або візьмемо в саппорт існуюче для покращень та оновлень. Якщо вас цікавить розробка нової серверної частини або підтримка існуючої - залиште заявку, щоб отримати детальний розрахунок вартості робіт та варіантів співробітництва.

Значна частина сучасних додатків для мобільних платформ(iOS, Android тощо) працює в парі із сервером. Програма зі застарілими даними втрачає свою корисність. Тому важливо забезпечити постійне оновлення даних із сервера на пристрій. Це стосується офлайн-додатків, які повинні працювати і без інтернету. Для повністю онлайн додатків, які не працюють (або непотрібні) без інтернету (наприклад, Foursquare, Facebook) є своя специфіка, яка виходить за рамки поточної статті.

Я розповім на прикладі одного нашого офлайн програми, які підходи ми використовували для синхронізації даних. У перших версіях ми розробилипрості алгоритми та, надалі, з досвідом, ми їх удосконалювали. Аналогічна послідовність представлена ​​й у статті – від найпростіших очевидних практик до складніших.

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

Загальні положення для всіх підходів

Наприклад, ми розглядатимемо передачу на пристрій довідника страв (“dishes”). Вважатимемо, що пристрій робить запит на url “/service/dishes/update”, обмін йде за протоколом http у форматі JSON ( www.json.org). На сервері є таблиця “dishes” з полями: id (ідентифікатор запису), name (найменування страви), updated (момент оновлення страви, краще відразу підтримувати timezone, “YYYY-MM-DDThh:mm:ssTZD”, наприклад, “1997 -07-16T19:20:30+01:00”), is_deleted (ознака віддаленого запису).

Ремарка щодо наявності останнього поля. За умовчанням його значення дорівнює 0. У додатку, де сутності синхронізуються між клієнтом та сервером, фізично видаляти дані з сервера не рекомендується (щоб не було помилок). Тому у віддалених страв виставляється is_deleted = 1. Після приходу на пристрій сутності з is_deleted = 1 вона видаляється з пристрою.

За будь-якого підходу, який буде розглядатися нижче, сервер повертає на пристрої JSON масивоб'єктів (може бути порожній):

[
(id: ,name: ,updated: ,isDeleted: },…
]

Приклад відповіді сервера:

[
(id: 5625,name: "Bread",updated: "2013-01-06 06:23:12",isDeleted: 0),
(id: 23,name: "Cooked semolina",updated: "2013-02-01 14:44:21",isDeleted: 0),(

name: "Fish-soup",

updated: "2013-08-02 07:05:19",

Принципи оновлення даних на пристрої

  1. Якщо прийшов елемент, який є на пристрої, і isDeleted = 0, він оновлюється
  2. Якщо прийшов елемент, якого немає на пристрої, та isDeleted = 0, то він додається
  3. Якщо прийшов елемент, який є на пристрої, і isDeleted = 1, він видаляється
  4. Якщо прийшов елемент, якого немає на пристрої, та isDeleted = 1, то нічого не робиться

Підхід 1: Синхронізується завжди все

Це найпростіший метод. Пристрій запитує список страв сервера і сервер надсилає весь список повністю. Щоразу список надходить весь. Чи не сортований.

Приклад запиту: null, або “()”

Переваги:

  • логіка на сервері проста - віддаємо завжди все
  • логіка на пристрої проста - перезаписуємо завжди все

Недоліки:

  • якщо запитувати список часто (кожні 10 хвилин), то буде великий інтернет трафік
  • якщо запитувати список рідко (щодня), то буде порушено актуальність даних

Галузь застосування:

  • для додатків з невеликим трафіком
  • передача даних, що дуже рідко змінюються (список міст, категорій)
  • передача налаштувань програми
  • на початку проекту для першого прототипу мобільного додатка

Підхід 2: Синхронізується лише оновлене

Пристрій запитує список страв, оновлений із попередньої синхронізації. Список надходить відсортований за “updated” у порядку зростання (необов'язково, але зручно). Пристрій зберігає значення "updated" у останньої надісланої страви і при наступному запиті надсилає його серверу в параметрі "lastUpdated". Сервер надсилає список страв, які новіші “lastUpdated” (updated > lastUpdated). При першому запиті сервер “lastUpdated” = null.

Приклад запиту: ( lastUpdated: “2013-01-01 00:00:00” )

На схемі: “last_updated” – значення, яке зберігається у пристрої. Зазвичай, на пристрої створюється окрема таблиця для зберігання цих значень “last_updated” за кожною сутністю (страви, міста, організації тощо)

Цей підхід підходить для синхронізації простих лінійних списків, у яких правила приходу на пристрій однакові для всіх пристроїв. Для більш вибіркової синхронізації див. “Підхід 5: Синхронізація зі знанням того, що вже є на пристрої”.

Зазвичай цей підхід перекриває більшість потреб. На пристрій приходять лише нові дані, синхронізуватися можна хоч щохвилини – трафік буде невеликий. Однак, тут виникають проблеми, пов'язані з обмеженнями мобільних пристроїв. Це пам'ять та процесор.

Підхід 3: Синхронізація порціями

У мобільних пристроїв мало оперативної пам'яті. Якщо в довіднику 3000 страв, то парсинг великого рядка json від сервера в об'єкти на пристрої може викликати брак пам'яті. У цьому випадку програма або аварійно завершиться, або не збереже ці 3000 страв. Але навіть якщо пристрій зміг переварити такий рядок, то продуктивність програми в моменти синхронізації у фоні буде низька (лаги інтерфейсу, не плавне прокручування тощо). Тому необхідно запитувати список дрібнішими порціями.

Для цього пристрій передає інший параметр (“amount”), який визначає розмір порції. Список надсилається обов'язково відсортований за полем “updated” за зростанням. Пристрій, аналогічно попередньому підходу, запам'ятовує значення updated у останньої надісланої сутності і передає його в поле lastUpdated. Якщо сервер надіслав таку саму кількість сутностей, то пристрій продовжує синхронізацію і знову робить запит, але вже з оновленим “lastUpdated”. Якщо сервер надіслав менше сутностей, це означає, що більше нових даних у нього немає, і синхронізація завершується.

На схемі: “last_updated” та “amount” – значення, які зберігаються у мобільному додатку. "last_item" - остання надіслана з сервера сутність (страва). Саме новіше цього значення буде запрошено наступний список.

Приклад запиту: ( lastUpdated: “2013-01-01 00:00:00”, amount: 100 )

Переваги:

  • На пристрій приходить стільки даних, скільки він може обробити за один раз. Розмір порції визначається практичними тестами. Прості сутності можна синхронізувати по 1000 штук за один раз. Але буває і таке, що сутності з великою кількістюполів та складною логікою обробки збереження синхронізуються нормально не більше 5 штук.

Недоліки:

  • Якщо буде 250 страв з однаковим updated, то у amount = 100 останні 150 не прийдуть на пристрої. Така ситуація цілком реальна та описана в наступному підході.

Підхід 4: Коректна синхронізація порціями

У попередньому підході можлива ситуація, що якщо в таблиці є 250 страв з однаковим “updated” (наприклад, “2013-01-10 12:34:56”) та розмір порції дорівнює 100, то прийдуть лише перші 100 записів. Інші 150 будуть відсічені жорсткою умовою (updated > lastUpdated). Чому так станеться? При запиті перших 100 записів lastUpdated встановиться в "2013-01-10 12:34:56", і наступний запит матиме умову (updated > "2013-01-10 12:34:56"). Не допоможе навіть пом'якшення умови (updated >= “2013-01-10 12:34:56”), тому що пристрій тоді нескінченно запитуватиме перші 100 записів.

Ситуація з однаковим “updated” не така рідкісна. Наприклад, при імпорті даних з текстового файлуполе “updated” було виставлено у NOW(). Імпорт файлу з тисячами рядків може тривати менше секунди. Може статися і так, що весь довідник матиме однаковий “updated”.

Щоб це виправити, треба використовувати якесь поле страви, яке було б унікальним хоча б у межах одного моменту (“updated”). Поле “id” унікальне взагалі по всій таблиці, тому слід додатково в синхронізації використовувати саме його.

Отже, реалізація цього підходу виглядає так. Сервер віддає список відсортований за “updated” та “id”, а пристрої запитують дані за допомогою “lastUpdated” та нового параметра “lastId“. У сервера умова вибірки ускладнюється: ((updated > lastUpdated) OR (updated = lastUpdated and id > lastId)).

На схемі: “last_updated”, “last_id” та “amount” – значення, що зберігаються у мобільному додатку. "last_item" - остання надіслана з сервера сутність (страва). Саме новіше цього значення буде запрошено наступний список.

Підхід 5: Синхронізація зі знанням того, що вже є на пристрої

Попередні підходи не враховують факту, що сервер насправді не знає, наскільки успішно дані збереглися на пристрої. Пристрій міг просто не зберегти частину даних через нез'ясовані помилки. Тому непогано було б отримувати від пристрою доказ, що всі (або не всі) страви збереглися.

Крім цього, користувач програми може так налаштувати програму, що йому потрібна буде лише частина даних. Наприклад, користувач хоче синхронізувати страви тільки з 2 міст із 10. Описаними вище синхронізаціями цього не досягти.

Ідея підходу така. Сервер зберігає в собі (в окремій таблиці "stored_item_list") інформацію про те, які страви є на пристрої. Це може бути просто перелік пар “id – updated”. У цій таблиці зберігаються всі списки пар “id – updated” страв всіх пристроїв.

Інформацію про страви, що є на пристрої (список пар “id – updated“) пристрій надсилає серверу разом із запитом на синхронізацію. При запиті сервер перевіряє те, які страви мають бути на пристрої та які є зараз. Після цього на пристрій надсилається різниця.

Як сервер визначає, які страви мають бути на пристрої? У найпростішому випадку сервер робить запит, який поверне йому список пар “id – updated” всіх страв (наприклад, SELECT id, updated FROM dishes). На схемі це робить “WhatShouldBeOnDeviceMethod()” метод. У цьому недолік підходу - серверу доводиться обчислювати (іноді роблячи важкі SQL-запити), що має бути на пристрої.

Як сервер визначає, які страви є на пристрої? Він запитує таблицю “stored_item_list” з цього пристрою і отримує список пар “id – updated”.

Аналізуючи ці два списки, сервер вирішує, що слід надіслати на пристрій, а що видалити. На схемі це “delta_item_list”. Тому в запиті немає “lastUpdated” та “lastId”, їх завдання виконують пари “id – updated”.

Як сервер дізнається про страви, що є на пристрої? У запиті до сервера додається новий параметр “items”, який містить список id страв, надісланих на пристрій у минулій синхронізації (“device_last_stored_item_list”). Звичайно, можна надсилати список id всіх страв, які є на пристрої, та не ускладнювати алгоритм. Але якщо на пристрої 3000 страв і вони щоразу все відсилатимуться, то витрати трафіку будуть дуже великі. У переважній кількості синхронізацій параметр "items" буде порожнім.

Сервер повинен постійно оновлювати у себе "stored_item_list" даними, які прийшли з пристрою у параметрі "items".

Слід реалізувати механізм очищення серверних даних stored_item_list. Наприклад, після переустановки програми на пристрої сервер вважатиме, що на пристрої все ще є актуальні дані. Тому при установці програми пристрій повинен якось проінформувати сервер, щоб він очистив stored_item_list по цьому пристрої. У нашому додатку ми надсилаємо додатковий параметр"clearCache" = 1 у цьому випадку.

Висновок

Зведена таблиця щодо характеристик цих підходів:

Підхід Обсяг трафіку(5 – великий) Трудомісткість розробки(5 – висока) Використання пам'яті пристрою(5 – висока) Коректність даних на пристрої(5 – висока) Можна виділити конкретний пристрій
1 Синхронізується завжди все 5 1 5 5 ні
2 Синхронізується лише оновлене 1 2 5 3 ні
3 Синхронізація порціями 1 3 1 3 ні
4 Коректна синхронізація порціями 1 3 1 3 ні
5 Синхронізація зі знанням того, що вже є на пристрої 2 5 2 5 так

Коректність даних на пристрої – це ймовірність того, що на пристрої є всі дані, які надсилалися сервером. У разі підходів №1 та №5 є 100% упевненість, що пристрій має всі дані, які потрібні. В інших випадках такої гарантії немає. Це не говорить про те, що решту підходів використовувати не можна. Просто якщо на пристрої частина даних пропаде, то виправити це з сервера (а тим більше дізнатися про це на сервері) не вийде.

Можливо, за наявності безлімітних тарифів на інтернет та безкоштовного wifi проблемаобмеження трафіку, що генерується мобільним додатком, стане менш актуальним. Але поки що доводиться йти на всякі хитрощі, вигадувати "розумніші" підходи, які дозволяють знизити мережеві витрати та збільшити продуктивність додатків. Не завжди це працює. Часом буває "що простіше - тим краще", залежить від ситуації. Сподіваюся, із цієї статті можна підібрати підхід, який стане в нагоді.

В інтернеті на диво мало описів синхронізації сервера та мобільних пристроїв. При цьому, що додатків, які працюють за такою схемою, багато. Для тих, хто цікавиться пара посилань.

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

Якщо Ви використовуєте складну програму, яка зберігає та/або обробляє дані на сервері, то за ним стоїть Back-end – програмний комплекс, розміщений на веб-сервері та працює з програмою, яка в цьому випадку називається Front-end. Розміщений на сервері додаток може працювати одночасно з великою кількістю клієнтів, що накладає вимоги на високу швидкістьта безпека його функціонування.

Часто серверна частина програми пишеться на мовою PHP, як найбільш популярним для подібних рішень. Для реалізації простих серверних задач можуть використовуватись стандартні системи, А ось для більш специфічних вже потрібно розробка свого рішення або надбудов над стандартними системами.

Принципи розробки сервера для мобільної програми

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

Організаційний контроль

Кожен проект створюється окремою групою фахівців, відповідальних за всі етапи розробки та здавання проекту вчасно.

Програмування

Проектування архітектури сервера – найважливіший крок, у якого створюються бази даних і формуються необхідні алгоритми.

Тестування

Програмна частинаповинна працювати без помилок та збоїв. Саме за це відповідають тестувальники, які здійснюють перевірку системи.

Технічна підтримка

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

Особливості розробки

Для того, щоб грамотно розробити серверну частину програми, потрібні певні навички та знання мови програмування, що використовується на сервері. Як показує практика, клієнт-серверні програми створюються мовою PHP. Він є безперечним лідером у цій галузі. На PHP написано більше половини сайтів у всьому світі, він зручний для розробки та підтримки.

Framework

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

Існують інші мови, які використовуються для розробки Back-end. Наприклад, популярні серверні програми, створені серед Delphi. За рахунок неї програма має покращену налагодження. Крім того, в ній простіше розробити унікальні програми, вона передбачає візуальне створення. Все це дозволяє зробити зрозумілий та зручний інтерфейс.

Не менш популярні серверні програми Java. Вони без проблем доповнюються, легко виконуються на різних платформах. високий рівеньбезпеки.

Ще одна мова, що часто використовується. З його допомогою серверні програми створюються легко, швидко і без зайвих витрат.

Практично все сучасні компаніїмають свої віртуальні офіси. Веб-сайт може бути або візитною карткоюабо порталом або онлайн-каталогом з можливістю оформлення замовлень.

Бізнес-процеси в даному випадку залежні від веб-серверів, а саме їх можливості протистояти атакам, спробам злому та зовнішнім негативним впливам, а також продуктивності, достатньої для безлічі запитів, що одночасно приймаються.

Етапи розробки веб-сервісу

Створюючи програми для різних сегментів ринку, свою роботу ми організуємо по єдиним принципом– розбиваємо весь процес на окремі кроки, про хід виконання та результати яких повідомляється замовникам. Таким чином, сервер для мобільного додатка розробляється аналогічно.

1. Розробка ідеї

До 2-х тижнів

На цьому етапі відбувається створення основи, що дає уявлення про те, що буде закладено і в якому напрямі розвиватиметься.

2. Оцінка проекту

2-3 неділі

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

3. Техзавдання та договір

До 2-х тижнів

Після обговорення із замовником усіх нюансів процесу та складання докладного ТЗ готується та підписується договір.

4. Розробка інтерфейсу

2-3 неділі

Створенням інтерфейсів, необхідних для написання програмних модулів, займаються дизайнери.

6. Тестування

2-3 неділі

Всебічна перевірка одержаного програмного рішення проводиться тестувальниками за допомогою набору відповідних інструментів.

7. Завершення проекту

До 2-х тижнів

У визначений термін готовий, ретельно протестований веб-сервіс здається замовнику.

Наша команда

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

Менеджери проектів

Ці співробітники взаємодіють і з клієнтами і з розробниками, забезпечуючи комунікацію між ними. Вони контролюють виконання як запланованих дій, і необхідних доопрацювань.

Дизайнери

У своїй роботі наші фахівці враховують вимоги побудови інтерфейсів для операційних систем iOSі Android, тому програми, що випускаються, коректно працюють на різних пристроях.

Розробники

З метою оптимізації продуктивності мобільних програм програмісти аналізують їх системні вимогита створюють спеціалізоване серверне ПЗ.

Тестувальники

Ретельне тестування – запорука якості готового продукту та гарантія безпеки даних, що зберігаються і оброблюються. Ці фахівці використовують різні інструменти та ефективну методику.

Які сервіси ми створюємо

Будучи вбудованим у сайт ПЗ або самостійною програмою, Веб-сервіс служить для виконання завдань, пов'язаних з рекламою, аналітикою, плануванням і просуванням бізнесу. У зв'язку з цим необхідно визначитися ресурс якого виду стане оптимальним рішенням.

Інформаційні проекти

Призначені розміщувати різнопланового контенту.

Тематичні сайти

Майже всі їхні сторінки присвячені одній тематиці. Попит на них, як і раніше, досить великий.

Новинки

Інформують про різні новини в рамках однієї або кількох тем, які відображають основні життєві сфери.

Блоги

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

Соціальні проекти

До них відносяться спеціалізовані соц. мережі, спільноти, форуми та ін.

Форуми

Створюються для обговорення різних новин, товарів/послуг та ін. Можуть бути як вузькоспрямованими, і різноплановими.

Соціальні мережі

Ці ресурси мають багатомільйонну аудиторію. Їхнє основне завдання – надати інтернет-користувачам можливість спілкуватися в режимі онлайн за допомогою текстових / голосових повідомленьта відеозв'язку.

Різні веб-сервіси

Отримавши сьогодні стала вельми поширеною, вони діляться кілька видів.

Каталоги

Поштові послуги

Надають користувачам всі можливості та переваги електронної пошти, Серед яких перегляд, відправка, редагування листів та документів та ін.

Пошукові системи

Служать для пошуку сайтів та різної інформаціїза певними запитами.

Дошки оголошень

Це веб-ресурси, де користувачі мережі розміщують свої оголошення про купівлю-продаж та послуги в рамках різних тематик.

Сайти-хостинги

Призначені для зберігання файлів. Деякі з них мають можливість ознайомитися з даними перед завантаженням.

Часто задавані питання

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

Скільки часу може зайняти створення програми та веб-сервера?

У середньому ця робота триває від 9 до 20 тижнів. Все залежить від складності завдання, що реалізується.

Розробка серверної частини клієнт-серверної програми починається з проектування архітектури. Від архітектури залежить багато чого: починаючи від розширюваності додатка і закінчуючи його продуктивністю та зручністю підтримки/супроводу.

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

Необхідно визначитися з протоколами обміну даними та форматами передачі даних.

API (application programming interface) – інтерфейс прикладного програмування. Якщо виражатися більш зрозумілою мовою, це набір запитів до серверу, який останній розуміє і може дати коректну відповідь. API визначає функціональність серверної логіки, при цьому API дозволяє абстрагуватися від того, як ця функціональність реалізована. Іншими словами, API – це необхідна частина загальної клієнт-серверної інфраструктури.

Порівняти JSON та XML. Навести приклад протоколів залежно від типу програми.

Багатопоточність

Одним із ключових аспектів у сучасному програмуванні є багатопоточність. За допомогою багатопоточності ми можемо виділити у додатку кілька потоків, які виконуватимуть різні завдання одночасно.

Багатопотоковість – властивість платформи (наприклад, операційної системи, віртуальної машиниі т. д.) або програми, що полягає в тому, що процес, породжений в операційній системі, може складатися з кількох потоків, що виконуються «паралельно», тобто без вказаного порядку в часі.

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

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

До переваг багатопоточності в програмуванні можна віднести наступне:

Спрощення програми у деяких випадках рахунок використання загального адресного простору.

Найменші щодо процесу тимчасові витрати на створення потоку.

Підвищення продуктивності процесу рахунок розпаралелювання процесорних обчислень та операцій вводу-вывода.

Потік(threаd) – це керована одиниця виконуваного коду. У багатозадачному середовищі, заснованої на потоках, у всіх процесів обов'язково є основний потік, але їх може бути і більше. Це означає, що в одній програмі може виконуватися кілька завдань асинхронно. Наприклад, редагування тексту в текстовому редакторіпід час друку, тому що ці завдання виконуються в різних потоках.

На звичайному процесорі керування потоками здійснюється операційною системою. Потік виконується до тих пір, поки не відбудеться апаратне переривання, системний виклик або поки не закінчиться відведений для нього операційною системою час. Після цього процесор перемикається на код операційної системи, який зберігає стан потоку (його контекст) або перемикається на стан іншого потоку, якому теж виділяється час виконання. При такій багатопоточності досить велика кількість тактів процесора витрачається на код операційної системи, що перемикає контексти. Якщо підтримку потоків реалізувати апаратно, процесор сам зможе перемикатися між потоками, а в ідеальному випадку - виконувати кілька потоків одночасно за кожен такт.

– Тимчасова багатопоточність (один потік)

– Одночасна багатопоточність (кілька потоків одночасно)

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

Ця перевага багатопотокової програми дозволяє їй працювати швидше на комп'ютерні системи, які мають кілька процесорів, процесор з кількома ядрами або на кластері машин - через те, що потоки виконання програм природно піддаються дійсно паралельному виконанню процесів. У цьому випадку програмісту потрібно бути дуже обережним, щоб уникнути стану гонки та іншої неінтуїтивної поведінки. Для того, щоб правильно маніпулювати даними, потоки виконання повинні часто проходити через рандеву процедуру, щоб обробляти дані в правильному порядку. Потокам виконання можуть також знадобитися м'ютекси (які часто реалізуються з використанням семафорів), щоб запобігти одночасній зміні загальних даних або їх читання під час процесу зміни. Необережне використання таких примітивів може спричинити тупикову ситуацію.

Іншим використанням багатопоточності, що застосовується навіть для однопроцесорних систем, є можливість застосування реагування на введення даних. В однопотокових програмах, якщо основний потік виконання заблокований виконанням тривалого завдання, вся програма може опинитися в замороженому стані. Переміщаючи такі тривалі завдання до робочого потоку, який виконується паралельно з основним потоком, стає можливим для додатків продовжувати реагувати на дії користувача під час виконання завдань фоновому режимі. З іншого боку, здебільшого багатопоточність – не єдиний спосіб зберегти чутливість програми. Те саме може бути досягнуто через асинхронне введення-виведення або сигнали в UNIX.

Усього розрізняють два різновиди багатозадачності: на основі процесіві на основі потоків. Відмінності багатозадачності з урахуванням процесів і потоків зводиться до такого: многозадачность з урахуванням процесів організується для паралельного виконання програм, а багатозадачність з урахуванням потоків – для паралельного виконання окремих частин однієї програми.

Усього розрізняють два типи потоків:

Потоки переднього плану (foreground threads) чи пріоритетний. За замовчуванням кожен потік, створюваний через Thread.Start(), автоматично стає потоком переднього плану. Цей типпотоків забезпечують запобігання поточної програми від завершення. Середовище CLR не зупинить програму доти, доки не будуть завершені всі пріоритетні потоки.

Фонові потоки (background threads). Цей видпотоків називається також потоками-демонами, що сприймаються середовищем CLR як розширювані шляхи виконання, які в будь-який момент часу можуть ігноруватися. Таким чином, якщо всі потоки переднього плану припиняються, всі фонові потоки автоматично знищуються при вивантаженні домену програми. Для створення фонових потоків необхідно надати властивості IsBackground значення true.

Розповісти про стан потоків: запущений, призупинений, запущений, але чекає чогось.

Проблема синхронізації потоків та загальні ресурси.

Взаємодія потоків

У багатопотоковому середовищі часто виникають проблеми, пов'язані з використанням паралельно виконуваними потоками тих самих даних або пристроїв. Для вирішення подібних проблем використовуються такі методи взаємодії потоків, як м'ютекси, семафори, критичні секції та події

М'ютекс- це об'єкт синхронізації, який встановлюється в особливий сигнальний стан, коли не зайнятий потоком. Тільки один потік володіє цим об'єктом у будь-який момент часу, звідси і назва таких об'єктів (від англійської mutually exclusive access - взаємно виключає доступ) - одночасний доступ до загального ресурсу виключається. Після всіх необхідних дій М'ютекс звільняється, надаючи іншим потокам доступ до спільного ресурсу. Об'єкт може підтримувати рекурсивне захоплення вдруге тим самим потоком, збільшуючи лічильник, не блокуючи потік, і вимагаючи потім багаторазового звільнення. Така, наприклад, критична секція Win32. Тим не менш, є й такі реалізації, які не підтримують таке та призводять до взаємного блокування потоку при спробі рекурсивного захоплення. Це FAST_MUTEX у ядрі Windows.

Семафориявляють собою доступні ресурси, які можуть бути придбані кількома потоками в той самий час, поки пул ресурсів не спорожніє. Тоді додаткові потоки повинні чекати, поки необхідна кількість ресурсів знову буде доступна. Семафори є дуже ефективними, оскільки вони дозволяють одночасний доступ до ресурсів.

Події. Об'єкт, що зберігає у собі 1 біт інформації «просигналізований чи ні», з якого визначені операції «просигналізувати», «скинути у непросигналізований стан» і «очікувати». Очікування на просигналізованому події є відсутність операції з негайним продовженням виконання потоку. Очікування на непросигналізованому події призводить до припинення виконання потоку до тих пір, поки інший потік (або друга фаза обробника переривання в ядрі ОС) не просигналізує подію. Можливе очікування кількох подій в режимах будь-якого або всіх. Можливе також створення події, що автоматично скидається в непросигналізований стан після пробудження першого ж і єдиного очікуваного потоку (такий об'єкт використовується як основа для реалізації об'єкта «критична секція»). Активно використовуються в MS Windows як в режимі користувача, так і в режимі ядра. Аналогічний об'єкт є і в ядрі Linuxпід назвою kwait_queue.

Критичні секціїзабезпечують синхронізацію подібно до мьютексам, за винятком того, що об'єкти, що представляють критичні секції, доступні в межах одного процесу. Події, м'ютекси і семафори також можна використовувати в однопроцесному додатку, проте реалізації критичних секцій в деяких ОС (наприклад, Windows NT) забезпечують швидший і ефективніший механізм взаємно-виключної синхронізації – операції «отримати» та «звільнити» на критичній секції оптимізовані для випадку єдиного потоку (відсутності конкуренції) з метою уникнути будь-яких системних викликів, що ведуть в ядро ​​ОС. Подібно до м'ютексу об'єкт, що представляє критичну секцію, може використовуватися тільки одним потоком в даний момент часу, що робить їх вкрай корисними при розмежуванні доступу до загальних ресурсів.

Умовні змінні(Condvars). Схожі з подіями, але не є об'єктами, що займають пам'ять – використовується тільки адреса змінної, поняття «вміст змінної» не існує, як умовна змінна може використовуватися адреса довільного об'єкта. На відміну від подій, встановлення умовної змінної в просигналізований стан не тягне за собою жодних наслідків у разі, якщо на даний момент немає потоків, які очікують змінної. Встановлення події в аналогічному випадку спричиняє запам'ятовування стану «просигналізовано» всередині самої події, після чого наступні потоки, які бажають очікувати на події, продовжують виконання негайно без зупинки. Для повноцінного використання такого об'єкта необхідна також операція «звільнити mutex і чекати на умовну змінну атомарно». Активно використовуються в UNIX-подібних ОС. Дискусії про переваги та недоліки подій та умовних змінних є помітною частиною дискусій про переваги та недоліки Windows та UNIX.

Порт завершення введення-виводу(IO completion port, IOCP). Реалізований в ядрі ОС і доступний через системні виклики об'єкт «черга» з операціями «помістити структуру у хвіст черги» та «взяти наступну структуру з голови черги» - останній виклик призупиняє виконання потоку у разі, якщо черга порожня, і доти, доки інший потік не здійснить виклик "помістити". Найважливішою особливістю IOCP є те, що структури в нього можуть бути не тільки явним системним викликом з режиму користувача, але й неявно всередині ядра ОС як результат завершення асинхронної операції введення-виведення на одному з дескрипторів файлів. Для досягнення такого ефекту необхідно використати системний виклик "зв'язати дескриптор файлу з IOCP". У цьому випадку вміщена в чергу структура містить код помилки операції введення-виведення, а також, для випадку успіху цієї операції - число реально введених або виведених байт. Реалізація порту завершення також обмежує кількість потоків, що виконуються одному процесорі/ядрі після отримання структури з черги. Об'єкт специфічний для MS Windows, і дозволяє обробку вхідних запитів з'єднання та порцій даних у серверному програмне забезпеченняв архітектурі, де кількість потоків може бути меншою за кількість клієнтів (немає вимоги створювати окремий потік з витратами ресурсів на нього для кожного нового клієнта).

Пул потоків

Розповісти про пул потоків