Грамотна клієнт-серверна архітектура: як правильно проектувати та розробляти web API. Як працює веб-сервер На чому працюють сервери

Привіт, Хабре! Я Андрій Фролов, провідний програміст, працюю в Mail.Ru над Next-Gen MMORPG Skyforge. Ви могли прочитати мою статтю про архітектуру баз даних в онлайн-іграх. Сьогодні я розкриватиму секрети, що стосуються пристрою сервера Skyforge. Намагатимуся розповісти максимально докладно, з прикладами, а також поясню, чому було прийнято те чи інше архітектурне рішення. На нашому сервері без перебільшення можна написати цілу книгу, тому для того, щоб укластися в статтю, мені доведеться пройтися тільки за основними моментами.

Огляд

  • Сервер - це майже два мільйони рядків коду Java. Для з'єднання із сервером та відображення красивої картинки використовується клієнт, написаний на C++.
  • Свій внесок у серверний код зробили півсотні програмістів. Код писався протягом багатьох років найкращими фахівцями російського «православного» геймдева. У ньому зібрані всі найвдаліші ідеї з усього світу.
  • На даний момент у нас написано близько 5200 автоматичних тестів, налагоджено continuous integration та навантажувальне тестування за допомогою ботів.
  • Сервер вміє запускатися та працювати на десятках та сотнях серверів, підтримувати гру сотень тисяч людей одночасно. Ми вирішили відмовитися від традиційної для MMO техніки шардування та запустити всіх гравців у один великий світ.

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

Сервісна архітектура

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

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

Третя велика проблема – це багатопоточність. Як відомо, найкращий спосіб порозумітися з багатопоточністю - це уникнути її. Deadlock, livelock, lock contention та інші милі серцю програміста проблеми можна обійти, якщо архітектура сервера буде позбавляти вас необхідності синхронізувати потоки вручну. В ідеалі програміст взагалі повинен писати простий однопоточний код і не замислюватися про такі речі.

Звідси народилася наша універсальна структура сервера, яка використовується в Skyforge:

  • Існує пул фізичних серверів, на яких запускатиметься гра. Цей набір серверів і наш серверний додаток, який на них запущено, називається Realm.
  • На кожному сервері запускається серверна програма (JVM), яка називається роллю. Ролі бувають різні: обліковий запис-сервер, ігрова механіка, чат і т.д. Кожна роль перебирає великий шматок функціоналу. Деякі ролі існують в однині, деякі запускаються в кількох примірниках.
  • Роль складається з набору послуг. Сервіс - це звичайний потік (thread), який займається своїм, специфічним для нього завданням. Прикладом сервісу може бути обслуговування авторизації, обслуговування резервування імен, балансувальник навантаження тощо. Кожен сервіс нічого не знає про фізичне розташування інших сервісів. Вони можуть бути поруч, а можуть бути на іншій фізичній машині. Сервіси взаємодіють через систему повідомлень, яка приховує від них такі подробиці.
  • Кожен сервіс складається із набору модулів. Модуль - це «шматок функціональності», який має один метод tick(). Прикладом модуля може бути модуль статистики, виконання транзакцій, модуль синхронізації часу. Вся робота сервісу полягає в тому, щоб у нескінченному циклі викликати по черзі метод tick() у своїх модулів. Один такий цикл називається "кадр сервера". Ми вважаємо показник хорошим, якщо кадр сервера коливається не більше від 3 до 20 мс.
  • Вся ця структура описується у файлах XML. Системі запуску треба просто «годувати» назву ролі. Вона знайде відповідний файл, запустить усі необхідні послуги та віддасть їм списки модулів. Самі модулі створяться за допомогою java reflection.

Таким чином, ми можемо запустити роль «локальний сервер», де буде все необхідне, а можемо розбити сервер на кілька десятків ролей – аккаунт-сервер, ітем-сервер, ігрова механіка тощо. - та запускати його на десятках різних фізичних серверів. Структура виявилася надзвичайно гнучкою та зручною, раджу серйозно до неї придивитися.

Основні послуги

Є певний набір сервісів, що несе основне ігрове навантаження. Кожен із серверів повинен вміти масштабуватися. В ідеалі – до нескінченності. На жаль, писати сервери так, щоб вони масштабувалися, це непросте завдання. Тому ми почали з того, що зробили основні послуги масштабованими, а будь-яку додаткову дрібницю, яка не несе основного навантаження, залишили на потім. Якщо у нас буде дуже багато користувачів, то їх нам доведеться покращувати для забезпечення можливості масштабування.
  • Акаунт-сервіс. Відповідає за авторизацію та підключення нових клієнтів.
  • Сервер ігрової механіки. Тут відбувається, власне, гра. Після проходження авторизації клієнт підключається сюди, і тут грає. З іншими сервісами клієнт безпосередньо не взаємодіє. Таких сервісів можна і потрібно запускати кілька десятків, а то й сотень. Саме ці послуги несуть основне навантаження.
  • Сервіси бази даних. Ці послуги виконують операції над даними ігрових персонажів, їх предметами, грошима, прогресом розвитку. Їх зазвичай запускається кілька штук. Докладніше про архітектуру баз даних можна прочитати в моїй минулій доповіді. (habrahabr.ru/company/mailru/blog/182088)
  • Чат. Займається роутингом чат-повідомлень між користувачами.
  • Всі інші послуги. Їх кілька десятків і вони зазвичай не створюють сильного навантаження, тому не вимагають відокремлених серверів.

Мережа

Під словом «мережа» я маю на увазі систему доставки повідомлень від одного сервісу до іншого або від одного об'єкта до іншого. Історично так склалося, що ми маємо відразу дві такі системи. Одна ґрунтується на повідомленнях. Друга система полягає в віддаленому виклику процедур (RPC). У Skyforge система повідомлень застосовується всередині сервісу ігрової механіки, щоб надіслати якесь повідомлення від аватара до моба, а також для спілкування клієнта та сервера. RPC використовується спілкування між сервісами.

Повідомлення
Усі об'єкти, які хочуть надсилати або приймати повідомлення, називаються абонентами. Кожен абонент реєструється у спільній директорії та отримує унікальний ідентифікатор - адресу. Будь-хто, хто хоче надіслати повідомлення якомусь абоненту, повинен вказати адреси «звідки» та «куди». Мережевий движок знає, де знаходиться абонент, і доставляє йому повідомлення. Повідомлення - це Java-об'єкт, який має метод run(). Під час відправлення цей об'єкт серіалізується, прилітає до цільового абонента, десеріалізується, а потім викликається метод run() над цільовим абонентом.

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

RPC
Видалений виклик процедур або RPC з'явився, щоб вирішити проблему ланцюжків повідомлень.
Основна ідея полягає у використанні кооперативної багатозадачності (Coroutine, Fibers). Тому, хто не знайомий із це концепцією, для розуміння теми раджу зазирнути у «Вікіпедію». en.wikipedia.org/wiki/Coroutine .
Сервіс, який хоче, щоб його могли викликати через віддалений виклик процедур, має реалізовувати спеціальний інтерфейс та зареєструвати у спеціальній директорії. Тоді будь-хто може попросити директорію дати йому інтерфейс цього сервісу, і директорія поверне спеціальний враппер над сервісом. Викликати послуги з RPC можна лише усередині файбера (coroutin), тобто. спеціального контексту виконання, який можна переривати та відновлювати у точках розриву. При викликі методів враппера він надсилатиме RPC виклики на віддалений сервіс, перериватиме поточний файбер в очікуванні відповіді і повертатиме результат, коли віддалений сервер відповість.

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

Серіалізація
Щоб у нас працювала система надсилання повідомлень та віддалений виклик процедур, нам потрібен клієнт-серверний протокол та спосіб серіалізації/десеріалізації об'єктів. Нагадаю, що ми маємо необхідність пересилати команди та дані з клієнта на сервер, тобто. з C++ Java і назад. Для цього ми Java-класами генеруємо їх копії в C++, а також генеруємо методи для серіалізації та десеріалізації об'єктів в байтовий потік. Код для серіалізації вбудовується прямо всередину класів і звертається безпосередньо до полів класу. Таким чином сервер не витрачає процесорний час на обхід класів за допомогою reflection. Все це ми генеруємо за допомогою самописного плагіну для IntelliJ IDEA. Внутрішньосерверний протокол для спілкування між сервісами повністю аналогічний клієнт-серверному протоколу.

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

Ігрова механіка

Основний сервіс, який би вам цікавий, це сервіс ігрової механіки. Саме там виконується весь код, безпосередньо пов'язаний із грою, саме там моделюється весь ігровий світ, літають фаєрболи та «грабуються коровані».
Карти та балансування навантаження
На серверах ігрової механіки створюються карти, на яких, власне, знаходяться гравці, моби і відбуваються всі веселощі. Кожна картка має ліміт на кількість гравців, які можуть на ній перебувати. Наприклад, ліміт може дорівнювати одиниці для персональних пригод, 10-30 для групових активностей і 250 для великих карт. Що відбувається, якщо на карту захоче потрапити ще один гравець, коли ліміт вичерпано? Тоді буде створено ще одну копію тієї самої карти. Гравці з цих карт не бачитимуть один одного, не заважатимуть один одному. Тобто. у якомусь ігровому місті можуть бути тисячі людей, але там не буде тісно. Такий спосіб організації гравців називається "канали".

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

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

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

Так як серверна програма дуже складна, неминуче виникнення помилок. Потрібно зробити так, щоб виникнення помилки, навіть необробленого NullPointerException, не призводило до падіння сервера. Можна помилку просто залогувати і піти далі, але якщо помилка виникне посеред якоїсь довгої дії над аватаром, то аватар може опинитися в зламаному та неконсистентному стані. Тут нам допоможе приходить концепція під назвою «локаль». Локаль - це контекст, у якому об'єкти можуть посилатися друг на друга. Об'єкти з однієї локалі не можуть посилатися на об'єкти з іншої. Якщо з локалі вилітає необроблений виняток, то локаль видаляється повністю. Аватари, моби та інші сутності є локалями, видаляються цілком і не можуть тримати посилань на інших аватарів та мобів. Тому вся взаємодія між аватарами та мобами йде через систему повідомлень, хоча вони знаходяться разом на одній машині і теоретично могли б тримати один на одного пряме посилання.

Реплікація
Моделювати ігровий світ потрібно не лише на сервері, а й частково на клієнті. Наприклад, клієнту потрібно бачити інших гравців та мобів, які знаходяться поряд з ним. Для цього використовується механізм клієнт-серверної реплікації, коли з сервера клієнтам надсилаються оновлення навколишнього ігрового світу. Робиться це за допомогою генератора коду, який вбудовує відсилання оновлень у сеттери серверних Java-об'єктів. Навколо гравця створюється коло певного радіусу, і якщо хтось, наприклад, інший аватар, потрапляє в це коло, він починає реплікуватися на клієнт. Із реплікацією є фундаментальна проблема. Якщо одному місці стовпиться N аватарів, то кожного з них потрібно буде посилати N реплік. Таким чином, виникає квадратична залежність, що обмежує кількість аватарів, які можуть зібратися в одному місці. Саме через цю фундаментальну квадратичність клієнти всіх ММО гальмують у столицях. Ми уникаємо цієї проблеми, обмежуючи кількість гравців на карті та розподіляючи їх по каналах.
Ресурсна система
У грі існують сотні та тисячі заклинань, предметів, квестів та інших подібних сутностей. Як ви, напевно, здогадуєтеся, програмісти не пишуть усі сотні квестів, це геймдизайнери. Програміст розробляє один Java-клас квесту, а описи всіх квестів з їхньою логікою, завданнями та текстами містяться в XML-файлах, які називаються ресурсами. При старті сервера ми завантажуємо ці ресурси та на їх основі збираємо Java-класи з описом світу. Цими класами вже може скористатися сервер. Приблизно така ж система існує і на стороні клієнта, тільки там ресурси не вантажаться з XML-файлів, а просто завантажується заздалегідь створений «шматок пам'яті», що містить всі необхідні об'єкти та посилання між ними. Ресурсних файлів ми маємо кілька сотень тисяч, але їх завантаження на сервері займає близько двох хвилин. На клієнті все вантажиться за секунди. Система дуже наворочена, підтримує такі фічі, як прототипи та успадкування, вкладені описувачі тощо. Поверх ресурсної системи ми створено спеціалізовані програми для редагування карт та інших ігрових сутностей.

Сервер у дії

Давайте на прикладах розглянемо кілька сценаріїв того, як працює вся ця система в дії.
Вбити собачку
Класичний тест, який ми завжди проводимо, якщо сильно змінили інфраструктуру та хочемо перевірити, що все працює, називається «Вбити собачку». Потрібно зайти клієнтом на сервер і вбити там якогось моба. Цей тест покриває практично всі основні моменти сервера і є чудовим прикладом для того, щоб скласти все вищесказане разом. Давайте по пунктах розберемо, що і як відбувається при вбиванні нещасного песика. Звичайно, деякі кроки спрощені, але це не є критичним для розуміння.
  • Клієнт посилає на обліковий запис сервер: «Хочу увійти в гру».
  • Акаунт-сервер запитує базу даних, проводить авторизацію та запитує у балансувальника карту, на якій гравець був востаннє.
  • Балансувальник вибирає карту з уже завантажених або створює нову на найменш завантаженому сервері ігрової механіки.
  • Клієнт підключається до тієї механіки, де йому була створена карта. Поки він підключається, йому завантажується його аватар.
  • Сервер починає реплікувати об'єкти навколо аватара на клієнт. Клієнт малює шикарну картинку та посилає на сервер команди, які посилає гравець.
  • Гравець починає бігати по карті, а сервер переміщає його світом і реплікує зміни навколишньої дійсності. Гравець знаходить будь-якого моба і натискає кнопку «вдарити».
  • Команда «удар» прилітає на сервер, на сервері виконується перевірка, чи удар можливий, і мобу відправляється повідомлення про завдання пошкоджень.
  • Команда «завдати ушкодження» відпрацьовується на мобі, прораховує всі резисти та інші подібні речі, потім бере функціональність «здоров'я» та списує якусь кількість.
  • Клієнту надсилається відповідь з підтвердженням нанесення шкоди, клієнт малює удар.
Масштабування
Давайте зайдемо з іншого боку і подивимося, як сервер поводиться під навантаженням.
  • 0 клієнтів. Якщо на сервері нікого немає, його можна запускати одним додатком із мінімальними налаштуваннями та без карт. На сервері немає жодної активності, і більшу частину часу він простоює.
  • 1 клієнт. Для одного клієнта доводиться створювати карту, мобів, серверні об'єкти, які починають споживати пам'ять та процесорний час для свого життя.
  • 500 клієнтів. 500 клієнтів зазвичай досить багато, щоб процесорного часу однієї персоналки не вистачало для роботи сервера. Доводиться запускати realm на кількох машинах чи потужніших серверах.
  • 10 000 клієнтів. 10 000 клієнтів вимагають вже декількох серверів. Так як більша частина навантаження посідає ігрові механіки, потрібно запускати realm з додатковими сервісами ігрової механіки.
  • 100 000 клієнтів. При 100000 одночасних гравців більше половини серверів зайняті ігровою механікою.
  • Клієнтів більше заліза. Якщо раптом гравців стане ще більше, а залізо в нас раптом скінчиться, доведеться обмежувати вхід людей у ​​гру, поки підвозять нові сервери. Для цього існує черга на вхід, що змушує гравців чекати, коли сервер буде готовий їх прийняти. Ця черга гарантує, що одночасно один realm не може містити гравців більше, ніж ми готові прийняти. У чергу гравців можуть почати ставити і в тому випадку, якщо через баг або ще з якихось причин сервер раптом почав працювати повільніше за певний поріг. Краще зробити прийнятний сервіс для обмеженої кількості клієнтів, ніж впасти всім.

Висновок

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

Якщо ви надрукуєте в адресному рядку вашого браузера http://www.сайт/how-web-server-work/ і натисніть клавішу Enter - ця сторінка нашого веб-сайту з'явиться на екрані.

На базовому рівні відбулося таке: Ваш браузер сформував підключення до Веб-сервера, надіслав запит на отримання Веб-сторінки сторінки та отримав її.

Тепер трохи докладніше:

URL складається з трьох частин:

1. Протоколу (http)

2. Ім'я сервера (www.сайт)

3. Адреси сторінки (how-web-server-work)

Браузер звертається до сервера доменних імен, щоб перекласти ім'я сайту www. IP-адреса, який він використовує для підключення до серверної машини. Браузер потім утворює з'єднання з Веб-сервером за вказаною IP-адресою на порт 80 або будь-який інший, якщо так задумано (Ми обговоримо порти пізніше в цій статті).

Дотримуючись протоколу HTTP, браузер надіслав запит на сервер, запитуючи файл http://www.сайт/how-web-server-work/

Зверніть увагу, що файли cookieтакож можуть бути відправлені від браузера до сервера.

У відповідь сервер згенерував динамічну Веб-сторінкуі надіслав назад HTML текст для відображення цієї сторінки у Вашому браузері. Файли cookie також можуть бути надіслані від сервера до браузера у заголовку сторінки. Браузер читає HTML-теги та формує виведення веб-сторінки на екрані.

Інтернет

То що таке «Інтернет»? Інтернет є сотні мільйонів комп'ютерів, пов'язані разом у комп'ютерну мережу. Мережа дозволяє всім комп'ютерам взаємодіяти один з одним. Домашній комп'ютер може бути пов'язаний з мережею Інтернет за допомогою різних способів і пристроїв - починаючи з примітивного модему для телефонної лінії, закачуючи з'єднанням по локальній мережі ( LAN) з Інтернет-провайдером ( ISP).

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

Клієнти та Сервери

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

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

IP-адреси

Щоб з'єднати всі ці машини в мережу, кожен комп'ютер в Інтернеті має унікальну адресу, звану IP-адреса. Типова IP-адреса виглядає так:

Чотири числа в IP-адресі називаються октетитому що вони можуть набувати значення між 0 і 255 або 2 8 варіантів значень.

Кожен комп'ютер в Інтернет має свою унікальну IP-адресу. Сервер має статичну IP-адресу, яка змінюється рідко. Домашній комп'ютер часто має IP-адресу, призначену провайдером, коли машина з'єднується з ним. Ця IP-адреса є унікальною для цієї сесії, але може виявитися іншою наступного разу. Таким чином, ISP, потрібна лише одна IP адреса для кожного маршрутизатора, які він підтримує, а не для кожного клієнта.

Якщо ви працюєте на Windows машині, ви можете переглянути безліч інформації про Інтернет на вашому комп'ютері, включаючи вашу поточну IP-адресу та ім'я хоста, за допомогою команди ipconfig. На UNIX-машині, треба набрати nslookupу командному рядку для відображення IP-адреси машини.

Доменні імена

Оскільки більшість людей мають труднощі із запам'ятовуванням послідовності цифр, які становлять IP-адреси, і тому, що IP-адреси іноді потрібно міняти, всі сервери і сайти в Інтернеті також мають і імена, що зчитуються, звані доменними іменами. Наприклад, www.. Це простіше для більшості з нас. www.сайтчим запам'ятовувати 5.9.205.233

Ім'я www.сайт насправді складається із трьох частин:

1. Ім'я World Wide Web (www). Насправді можна обходитися і без явної вказівки «www», хоча формально це буде інша мережа.

2. Доменне ім'я (qriosity)

3. У зоні домену верхнього рівня (ua)

Доменними іменамикерують Реєстратори доменних імен. Реєстратори створюють доменні імена верхнього рівня та гарантують, що всі імена у зоні верхнього рівня домену є унікальним. Реєстратор також надає контактну інформацію для кожного доменного імені та запускає сервіс whois, що вказує на власника домену. Ім'я хоста створюється власником домену.

Сервери доменних імен

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

При введенні URL-адреси http://www..сайт, передає її на сервер доменних імен, сервер повертає правильну IP-адресу для www.сайт. Цілий ряд серверів імен може бути залучений до того, щоб отримати правильну IP-адресу.

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

Порти

Будь-який сервер робить свої послуги доступними через Інтернет за допомогою пронумерованих портівпо одному для кожної служби, доступної на сервері. Наприклад, є комп'ютер-сервер, на якому запущено Веб-сервер та FTP-сервер. Веб-сервер, як правило, буде доступний на порту 80, а FTP-сервер буде доступний на порту 21. Клієнти підключаються до сервісу на певну адресу IP і на певний порт.

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

Якщо сервер приймає з'єднання на порту від зовнішнього світу, і якщо брандмауер не захищає порти, можна підключитися до заздалегідь обумовленого порту з будь-якого комп'ютера в Інтернет і скористатися послугою. Зверніть увагу, що немає нічого, що змушує Вас, наприклад, тримати Веб-сервер на порту 80. Якщо ви встановили свій сервер і завантажили програмне забезпечення Веб-сервера на ньому, ви могли б поставити Веб-сервер на порту 999 або будь-кому іншому порту, що не використовується. Потім, якщо, наприклад, Ваша машина буде відома як xxx.yyy.com, то до неї можуть підключатися з URL http://xxx.yyy.com:999 -":999" явно вказує номер порту, яким можна дістатися до вашого Веб-сервера. Якщо порт не вказано, то браузер просто передбачає, що веб-сервер доступний за допомогою добре відомого порту 80.

Протоколи

Як тільки клієнт підключений до служби на даному порту, він звертається до сервісу за допомогою спеціального протоколу. Протокол- Це набір угод логічного рівня, що дозволяє програмам обмінюватися даними. Для спільної роботи комп'ютерів у мережі Інтернет використовується сімейство протоколів TCP/IP. Веб-сервер використовує протокол HTTP.

Додатково: Безпека

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

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

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

Додатково: Динамічні сторінки

Що таке динамічні Веб-сторінки? Наприклад:

1. Будь-яка гостьова книга дозволяє ввести повідомлення в HTML-формі, і автоматично виводить нові та старі записи.

2. Будь-яка пошукова система дозволяє ввести ключові слова в HTML-формі запиту, і тоді він динамічно створює сторінку, на основі пошуку інформації за цими ключовими словами.

У всіх цих випадках, Веб-сервер здійснює не просто пошук файлу. Він обробляє інформацію та генерує сторінки залежно від специфіки запитів. Майже завжди, Веб-сервер, використовує так звані скрипти- програмний код, написаний на PHP, Perl, Java та інших мовах програмування, щоб здійснити цей процес.

Сторінки нашого сайту також є динамічними, створеними за допомогою PHP з використанням баз даних MySQL.

Навіщо потрібен сервер і коли варто купувати його для свого бізнесу?

Для початку уточнимо, що сервер – це обладнання, яке використовує серверне програмне забезпечення. Він оптимізований до роботи з іншими комп'ютерами (клієнтами). Клієнтами сервера можуть бути комп'ютери, телефони, факси, принтери та інші пристрої, які підключаються до інтернету. Чим більше інформації Ви плануєте зберігати на серверному устаткуванні, тим потужнішим повинен бути сервер. З якою метою орендують сервер? Докладніше у матеріалі на блозі ГіперХост.

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

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

Якщо Ваш бізнес працює на перспективне майбутнє, слід подумати про вибір сервера.

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

Поштовий сервербере безпосередню участь у прийнятті та надсиланні електронної пошти. Ви надсилаєте листа на електронну адресу, але він спочатку потрапляє на поштовий сервер, де відбувається його обробка. Індексується адреса одержувача та лист надсилається. У цьому процесі беруть участь кілька поштових серверів, які обмінюються необхідною інформацією. Про популярні поштові сервери Exim, Postfix, Sendmail можна прочитати у статті.

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

Веб-сервер– сервер підключений до Інтернету та приймає запити користувачів за протоколом HTTP. Усі сайти, які є в мережі, розміщені на веб-серверах. Такий вид сервера – безпосередній провідник між сайтом та клієнтами. Веб-сервер отримує запит, далі обробляє його та видає результат (файловий чи гіпертекстовий). За своєю суттю веб-хостинг та веб-сервер поняття ідентичні. Веб сервер Nginx і apache - що це і як працює ця зв'язка? Відповідь на це питання.

Сервер бази даних.У більшості програм використовують бази даних. Даний вид серверів забезпечує доступ до даних за допомогою системи клієнт-сервер. Найпопулярнішими серверами баз даних є SQL Server (Microsoft), SQL Base Server, Oracle Server (Oracle Corporation), IBM DB2, Informix. Вони працюють на платформі різних операційних систем, таких як MSDOS, OS/2, Xenix, Unix.

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

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

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

Причини, через які можна визначити, чи потрібно для вашої фірми?

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

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

Фахівці компанії HyperHostіз задоволенням підберуть найбільш оптимальний фізичний або за всіма параметрами сервер і забезпечать стабільність Ваших проектів. Порівняння також допоможе зробити правильний вибір і правильно підібрати послугу в залежності від поставленої мети.

Чи потрібно вибрати операційну систему для роботи сервера? Дана допоможе вам зробити правильний вибір та оцінити всі можливості кожної ОС. Про панелі керування для серверів з Linux.

42788 раз(и) 18 Сьогодні переглянуто раз(и)

Дедалі більше підприємств малого бізнесу можуть оцінити переваги наявності мережі

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

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

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

"Я бачу все більше невеликих організацій, в яких працюють сервери, навіть в офісах з одним співробітником", - говорить Лора ДіДіо (Laura DiDio), аналітик малого бізнесу в консалтинговій компанії The Yankee Group з Бостона. - "Вони дозволяють отримати більше прибутку на долар, вкладений у технології".

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

Візьмемо вже знайому нам Лору ДіДіо. Частину часу вона працює у своєму заміському будинку та хоче отримати максимальну користь від своїх витрат на технології. «У мене вдома два переносні комп'ютери, два швидкісні підключення, три телефонні лінії та сервер, що працює під управлінням Microsoft Small Business Server», - каже Лора.

Сервер – двигун її системи. Він дозволяє ДіДіо централізувати та захистити дані на ПК, контролювати файли, легко створювати резервні копії та ефективно працювати з клієнтами – клієнти отримують таке ж обслуговування, якби вона знаходилася не вдома, а у своєму бостонському офісі.

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

Ще один прихильник серверів - Гаррі Брелсфорд (Harry Brelsford), консультант-реселер з технологій та технічний письменник з Бейнбрідж Айленд, штат Вашингтон. У нього в офісі працюють три клієнтські ПК та сервер. Тут він надає консалтингові послуги з технологій приблизно 20 компаніям, а також пише книги на цю тематику (він вже написав 10 таких книг).

"Сервер і мережа дуже допомагають мені в роботі", - каже Брелсфорд. - «Якщо мені потрібний якийсь файл, я точно знаю, де його шукати. У мене також більша впевненість у стабільності системи, незалежно від того, що я роблю. Просто ви виконуєте роботу краще та без переробок. Ви можете забути про брак місця на диску, безладдя у файлах, недостатню потужність процесора і втрати даних».

ДіДіо і Брелсфорд говорять про сервери Dell та Hewlett-Packard, які коштують не більше 1,000 дол. На них працює нове програмне забезпечення Microsoft Windows Small Business Server 2003 (599 дол. за Standard Edition). Такий комплекс дуже привабливий для менеджерів, які вміють рахувати свої гроші. Версія Standard Edition також включає Microsoft Exchange Server 2003.

З цим погоджується Рей Боггс (Ray Boggs), віце-президент з розвитку малого бізнесу та домашніх офісів в IDC, компанії технічного консалтингу з Фремінгхема, штат Массачусетс. Він каже, що хоча перевагами від переходу на технології клієнт/сервер можуть користуватися всі малі організації, найбільші вигоди отримують ті з них, у яких 15 ПК або більше. Це досягається за рахунок нових апаратних засобів та програмного забезпечення, призначених спеціально для цього ринку, та різко зростаючої кількості угод.

"Ціни на сервери продовжують падати, а їх функціональні можливості продовжують покращуватися", - каже Боггс.

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

  1. Ви наведете лад у хаосі. Централізуючи дані на сервері, краще керувати важливою діловою інформацією. Загальний доступ до файлів та інших даних з усіх ПК значно спрощується в порівнянні з переміщенням даних з одного ПК на інший. І, як зазначає ДіДіо, більш старі ПК можуть знайти нове життя, якщо їх файли та дані завантажити на сервер. «Багато хто купує сервери і не поспішає позбуватися своїх старих ПК і переносних комп'ютерів», - каже вона.
  2. Найкращий захист даних. Windows Small Business Server 2003 має дві функції, які дозволяють користувачам краще захистити інформаційні активи, спрощуючи архівацію та відновлення критичних даних. Це майстер налаштування архівації та тіньове копіювання тому.
  3. Найкраща співпраця при веденні бізнесу. Мережа, підтримувана сервером - це полегшення загального доступу до даних. Windows, Small Business Server 2003 поставляється зі службами Windows SharePoint Services, програмним забезпеченням, яке дозволить вашим співробітникам та іншим членам команди організувати спільну роботу через Інтернет. Встановивши SharePoint, ви отримуєте портал внутрішньої мережі компанії з дружнім інтерфейсом, що забезпечує спільний доступ до даних та їх організацію. Служби постачаються з довідковими документами та ресурсами. Сервер також є обов'язковим, якщо потрібна підтримка на кількох ПК життєво важливих для діяльності підприємства додатків, таких як фінансові рішення Microsoft Business Solutions.
  4. Підвищення мобільності персоналу. Сервери дозволяють отримувати віддалений доступ до мережі та даним уповноваженим співробітникам, які знаходяться поза офісом, у дорозі або працюють у локальних підрозділах. За допомогою функції робочого місця в Інтернеті користувачі Windows Small Business Server 2003 можуть отримати доступ до даних на сервері через Інтернет. Співробітники поза офісом можуть також підключатися до внутрішньої мережі компанії через SharePoint
  5. Спільне використання високошвидкісного доступу. "Справжній каталізатор збуту серверів у середовищі малого бізнесу - це високошвидкісний доступ до Інтернету для всіх комп'ютерів мережі", - говорить Боггс з IDC. - «Якщо в бізнесі використовується три і більше облікових записів віддаленого доступу, - саме час купити сервер і перейти на швидкісний доступ. Повернення вкладень буде дуже швидким за рахунок зростання продуктивності праці».
  6. Швидке налаштування нових комп'ютерів, додавання користувачів та розгортання нових програм. Чи плануєте розвиток своєї справи? Керуючи даними із загального центру, легше координувати додавання нових ПК, програм та ліцензій на них. Можна також краще управляти брандмауерами та контролювати загрози даним, розгортати антивірусний захист та виявляти вторгнення.
  7. Збільшення обчислювальної потужності. Сервер розширює можливості мережі, дозволяючи зберігати великі масиви даних, звільняючи пам'ять та підвищуючи ефективність використання окремих ПК. «Малий бізнес сьогодні потребує додаткових обчислювальних потужностей для використання веб-служб, управління веб-вузлами, виконання розсилок інформації електронною поштою та застосування досконаліших інструментальних засобів та додатків», - каже ДіДіо. (Боггс додає, що недалекий той день, коли у багатьох вдома працюватимуть сервери, допомагаючи студентам за допомогою ПК виконувати навчальні завдання, а підліткам – купувати в Інтернеті ігри та інші складні програми.)
  8. Створіть професійний імідж свого бізнесу та розширте взаємодію з клієнтами. Серверне програмне забезпечення, таке як Windows Small Business Server 2003, дозволяє об'єднувати облікові записи електронної пошти (AOL, Yahoo!, Hotmail і т.д.) в один обліковий запис компанії, посилюючи ваш імідж серед клієнтів та партнерів. "Ви можете мати кілька псевдонімів однієї кореневої адреси електронної пошти", - говорить Брелсфорд. - «Сервер може надавати вагу вашому бізнесу». ДіДіо: "Це не тільки приносить вам більше прибутку на вкладений долар, але й робить ваш імідж професійнішим в очах тих, з ким ви хочете мати справу".
Як дізнатися, що час купувати сервер?
  • У вашому бізнесі використовується два або більше облікових записів віддаленого доступу.
  • Ви хочете централізувати та організувати дані (не завжди можете знайти те, що вам потрібно).
  • Ви хочете створити спільний доступ до апаратних засобів, таких як принтери та факси для двох або більше ПК (при використанні цієї мети однорангових мереж потрібна велика кількість шнурів і проводів).
  • Ви бажаєте спростити резервне копіювання, щоб забезпечити найкращий захист даних.
  • Багатьом вашим співробітникам, які часто перебувають у дорозі, поза офісом або працюють у локальних підрозділах, потрібно підключатися до мережі.
  • Ви хочете весь свій бізнес охопити внутрішньою мережею (співробітники, які знаходяться поза офісом, не завжди пам'ятають, що час від часу потрібно з вами зв'язуватися).
  • Вам потрібно багато місця для зберігання даних (і ваші перевантажені ПК здригаються і стогнуть при додаванні нових даних).
  • Ви хотіли б запускати фінансове програмне забезпечення або інші важливі для вашого бізнесу програми на кількох ПК.
  • Ваша компанія росте, і ви плануєте прийняти нових співробітників та додати комп'ютери (вітаємо!).
  • У вас скромний бізнес, і ви хотіли б виглядати професійно (і більше, ніж є насправді).
  • Ваші ПК дуже старі, і ви хотіли б позбутися їх. Сервер зробить процедуру переходу безболісною.
  • Ваші ПК дуже старі, але ви хотіли б зберегти їх. Сервер прийме навантаження із ПК на себе.

Грамотна клієнт-серверна архітектура: як правильно проектувати та розробляти web API

Розповідає Володимир, веб-розробник Noveo

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

Наближення перше: Чинні особи

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

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

Клієнт та сервер

Серверомв даному випадку ми вважаємо абстрактну машину в мережі, здатну отримати HTTP-запит, обробити його та повернути коректну відповідь. У контексті цієї статті зовсім не важливі його фізична суть і внутрішня архітектура, чи то студентський ноутбук, чи величезний кластер із промислових серверів, розкиданих по всьому світу. Нам так само неважливо, що у нього під капотом, хто зустрічає запит біля дверей, Apache або Nginx, який невідомий звір, PHP, Python або Ruby виконує його обробку і формує відповідь, яке сховище даних використовується: Postgresql, MySQL або MongoDB . Головне, щоб сервер відповідав головному правилу – почути, зрозуміти та пробачити відповісти.

Клієнтомтеж може бути все, що завгодно, що здатне сформувати та відправити HTTP-запит. До певного моменту в цій статті нам також не будуть цікаві цілі, які ставить перед собою клієнт, відправляючи цей запит, як і те, що він робитиме з відповіддю. Клієнтом може бути JavaScript-сценарій, що працює в браузері, мобільний додаток, злий (або не дуже) демон, запущений на сервері, або занадто порозумнілі холодильники (вже є і такі).

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

Філософія REST

REST (Representational state transfer) спочатку був задуманий як простий і однозначний інтерфейс для управління даними, що передбачав лише кілька базових операцій з безпосереднім мережевим сховищем (сервером): вилучення даних (GET), збереження (POST), зміна (PUT/PATCH) та видалення (DELETE). Зрозуміло, цей перелік завжди супроводжувався такими опціями, як обробка помилок у запиті (чи коректно складено запит), розмежування доступу до даних (раптом цього знати не слід) і валідація вхідних даних (раптом ви написали нісенітницю), загалом, усіма можливими перевірками , які сервер виконує перед тим, як виконати бажання клієнта.

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

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

Приклад: GET /api/v1/users/25/name

Незалежність формату зберігання даних від формату їх передачі- сервер може підтримувати кілька різних форматів для передачі тих самих даних (JSON, XML і т.д.), але зберігає дані у своєму внутрішньому форматі, незалежно від підтримуваних.

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

Чого нам не вистачає

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

Виклики функцій

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

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

Ще варіант- Створення та розрив зв'язків між даними. Наприклад, додавання користувача до групи. Викликаємо по суті групафункцію addUser, як параметр передаємо об'єкт користувач, Отримуємо результат.

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

Множинні операції

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

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

Статистичні запити, агрегатори, форматування даних

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

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

Різновиди даних

Об'єкти

Ключовим типом даних у спілкуванні між клієнтом та сервером виступає об'єкт. По суті, об'єкт – це перелік властивостей та відповідних їм значень. Ми можемо надіслати об'єкт на сервер у запиті та отримати результат запиту у вигляді об'єкта. При цьому об'єкт не обов'язково буде реальною сутністю, що зберігається в базі даних, принаймні у тому вигляді, в якому він відправлений або отриманий. Наприклад, облікові дані для авторизації передаються як об'єкта, але є самостійної сутністю. Навіть об'єкти, що зберігаються в БД, схильні обростати додатковими властивостями внутрішньосистемного характеру, наприклад, датами створення і редагування, різними системними мітками і прапорами. Властивості об'єктів можуть бути як власними скалярними значеннями, так і містити пов'язані об'єктиі колекції об'єктів, які є частиною об'єкта. Частина властивостей об'єктів може бути редагованою, частиною системною, доступною тільки для читання, а частина може мати статистичний характер і обчислюватися на льоту (наприклад, кількість лайків). Деякі властивості об'єкта можуть бути приховані залежно від прав користувача.

Колекції об'єктів

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

Скалярні значення

У чистому вигляді скалярні значення як окрема сутність моєї пам'яті зустрічалися вкрай рідко. Зазвичай вони фігурували як властивості об'єктів або колекцій, і в цій якості можуть бути доступні як для читання, так і для запису. Наприклад, ім'я користувача може бути отримано та змінено в індивідуальному порядку GET /users/1/name . На практиці ця можливість трапляється рідко, але в разі потреби хотілося б, щоб вона була під рукою. Особливо це стосується властивостей колекції, наприклад, числа записів (з фільтрацією або без неї): GET /news/count .

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

Наближення друге: Правильний шлях

У цьому наближенні я хотів би окремо поговорити про підходи до побудови унікальних шляхів до ресурсів та методів вашого web API та про ті архітектурні особливості програми, які впливають на зовнішній вигляд цього шляху та його компоненти.

Про що варто подумати, стоячи на березі

Версійність

Рано чи пізно будь-яка діюча система починає еволюціонувати: розвиватись, ускладнюватись, масштабуватись, усучаснюватись. Для розробників REST API це загрожує в першу чергу тим, що необхідно запускати нові версії API при старих старих. Тут я говорю більше не про архітектурні зміни під капотом вашої системи, а про те, що змінюється формат даних і набір операцій з ними. У будь-якому випадку версійність необхідно передбачити як в початковій організації вихідного коду, так і в принципі створення URL. Що стосується URL, тут існує два найбільш популярні способи вказівки версії API, якій адресовано запит. Префіксація шляху example-api.com/v1/ та розведення версій на рівні субдомену v1.example-api.com. Використовувати можна будь-який із них, залежно від потреби та необхідності.

Автономність компонентів

Web API складних систем, що підтримують кілька ролей користувача, часто вимагає поділу на частини, кожна з яких обслуговує свій спектр завдань. По суті кожна частина може бути самостійним додатком, працювати на різних фізичних машинах і платформах. У контексті опису API нам не важливо, як сервер обробляє запит і які сили та технології в цьому замішані. Для клієнта API – система інкапсульована. Проте різні частини системи можуть мати зовсім різну функціональність, наприклад, адміністративна і користувальницька частина. І методологія роботи з тими самими, начебто, ресурсами може істотно відрізнятися. Тому такі частини необхідно розділяти на рівні домену admin.v1.example-api.com або префіксу шляху example-api.com/v1/admin/. Ця вимога не є обов'язковою, і багато залежить від складності системи та її призначення.

Формат обміну даними

Найзручнішим і функціональнішим, на мою думку, форматом обміну даними є JSON, але ніхто не забороняє використовувати XML, YAML або будь-який інший формат, що дозволяє зберігати серіалізовані об'єкти без втрати типу даних. За бажанням можна зробити API підтримку кількох форматів вводу/вывода. Достатньо використовувати HTTP заголовок запиту для вказівки бажаного формату відповіді Accept і Content-Type для вказівки формату переданих у запиті даних. Іншим популярним способом є додавання розширення до URL ресурсу, наприклад, GET /users.xml , але такий спосіб здається менш гнучким і красивим, хоча б тому, що обважнює URL-адресу і вірний швидше для GET-запитів, ніж для всіх можливих операцій.

Локалізація та багатомовність

На практиці багатомовність API найчастіше зводиться до перекладу сервісних повідомлень та повідомлень про помилки необхідною мовою для прямого відображення кінцевому користувачеві. Багатомовний контент теж має місце бути, але збереження та видача контенту різними мовами, на мій погляд, повинна розмежовуватися більш явно, наприклад, якщо у вас одна і та ж стаття існує різними мовами, то за фактом це дві різні сутності, згруповані за ознакою єдності змісту. Для ідентифікації мови можна використовувати різні способи. Найпростішим можна вважати стандартний HTTP-заголовок Accept-Language. Я зустрічав інші способи, такі як додавання GET-параметра language="en" , використання префіксу шляху example-api.com/en/ або навіть на рівні доменного імені en.example-api.com . Мені здається, що вибір способу вказівки локалі залежить від конкретної програми та завдань, що стоять перед ним.

Внутрішня маршрутизація

Отже, ми дісталися кореневого вузла нашого API (або одного з його компонентів). Всі подальші маршрути будуть проходити вже безпосередньо всередині вашої серверної програми, відповідно до підтримуваного ним набору ресурсів.

Шляхи до колекцій

Для вказівки шляху до колекції ми просто використовуємо назву відповідної сутності, наприклад якщо це список користувачів, то шлях буде таким /users . До колекції застосовні два методи: GET (отримання лімітованого списку сутностей) і POST (створення нового елемента). У запитах отримання списків ми можемо використовувати безліч додаткових GET параметрів, застосовуваних для постраничного виведення, сортування, фільтрації, пошуку etc, але вони мають бути опціональними, тобто. ці параметри не повинні передаватися як частина шляху!

Елементи колекції

Для звернення до конкретного елемента колекції ми використовуємо у маршруті унікальний ідентифікатор /users/25 . Це і є унікальна дорога до нього. Для роботи з об'єктом застосовні методи GET (отримання об'єкта), PUT/PATCH (зміна) та DELETE (видалення).

Унікальні об'єкти

Багато сервісів існують унікальні для поточного користувача об'єкти, наприклад профіль поточного користувача /profile , або персональні налаштування /settings . Зрозуміло, з одного боку, це елементи однієї з колекцій, але вони є відправною точкою використання нашого Web API клієнтським додатком, і до того ж дозволяють набагато ширший спектр операцій над даними. При цьому колекція, що зберігає налаштування користувача може бути взагалі недоступна з міркувань безпеки і конфіденційності даних.

Властивості об'єктів та колекцій

Для того, щоб дістатися до будь-якої з властивостей об'єкта безпосередньо, достатньо додати до шляху до об'єкта ім'я властивості, наприклад, отримати ім'я користувача /users/25/name . До властивості застосовні методи GET (отримання значення) та PUT/PATCH (зміна значення). Метод DELETE не можна застосувати, т.к. властивість є структурною частиною об'єкта як формалізованої одиниці даних.

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

Колекції пов'язаних об'єктів

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

Функції об'єктів та колекцій

Для побудови шляху до інтерфейсу виклику функції у колекції чи об'єкта ми використовуємо той самий підхід, що й звернення до властивості. Наприклад, для об'єкта /users/25/sendPasswordReminder або для колекції /users/disableUnconfirmed . Для викликів функцій ми у будь-якому випадку використовуємо метод POST. Чому? Нагадаю, що в класичному REST немає спеціального дієслова для виклику функцій, а тому нам доведеться використовувати один з існуючих. На мій погляд, для цього найбільш підходить метод POST т.к. він дозволяє передавати на сервер необхідні аргументи, не є ідемпотентним (що повертає той самий результат при багаторазовому зверненні) і найбільш абстрактний по семантиці.

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

Наближення третє: Запити та відповіді

У попередніх наближеннях я розповів про те, як прийшла ідея зібрати та узагальнити досвід розробки Web API. У першій частині я постарався описати, з якими видами ресурсів та операцій над ними ми маємо справу з проектуванням web API. У другій частині були порушені питання побудови унікальних URL-адрес для звернення до цих ресурсів. А в цьому наближенні я спробую описати можливі варіанти запитів та відповідей.

Універсальна відповідь

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

Success – маркер успішності виконання запиту

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

POST /api/v1/articles/22/publish ( "success": true )

Error - відомості про помилку

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

GET /api/v1/user ( "success": false, "error": ( "code" : 401, "message" : "Authorization failed" ) )

Data - дані, що повертаються сервером

Більшість відповідей сервера мають повертати дані. Залежно від типу запиту та його успіху очікуваний набір даних буде різним, проте атрибут «data» буде у переважній більшості відповідей.

Приклад даних, що повертаються у разі успіху. У разі відповідь містить запитуваний об'єкт user.

GET /api/v1/user ( "success": true, "data": ( "id" : 125, "email" : "john.smit [email protected]", "name" : "John", "surname" : "Smith", ) )

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

PUT /api/v1/user ( "success": false, "error": ( "code" : 422, "message" : "Validation failed" ) "data": ( "email" : " Email could not be blank. ", ))

Pagination - відомості, необхідні організації посторінкової навігації

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

Мінімальний набір значень для пагінації складається з:

  • загальної кількості записів;
  • числа сторінок;
  • номери поточної сторінки;
  • числа записів на сторінці;
  • максимального числа записів на сторінці, яку підтримує серверна сторона.

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

GET /api/v1/articles Response: ( "success": true, "data": [ ( "id" : 1, "title" : "Interesting thing", ), ( "id" : 2, "title" : "Boring text", ) ], "pagination": ( "totalRecords" : 2, "totalPages" : 1, "currentPage" : 1, "perPage" : 20, "maxPerPage" : 100, ) )

Робота над помилками

Як уже згадувалося вище, не всі запити до web API завершуються успіхом, але це також частина гри. Система інформування про помилки є потужним інструментом, що полегшує роботу клієнта і направляє клієнтський додаток правильним шляхом. Слово «помилка» у цьому контексті не зовсім доречне. Тут більше підійде слово виняток, тому що насправді запит успішно отримано, проаналізовано, і на нього повертається адекватна відповідь, яка пояснює, чому запит не може бути виконаний.

Які ж потенційні причини одержуваних винятків?

500 Internal server error - все зламалося, але ми скоро полагодимо

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

400 Bad request - а тепер у вас все зламалося

Відповідь прямо протилежна попередньому. Повертається у тих випадках, коли клієнтська програма відправляє запит, який в принципі не може бути коректно оброблений, не містить обов'язкових параметрів або має синтаксичні помилки. Зазвичай це лікується повторним прочитанням документації web API.

401 Unauthorized - незнайомець, назви себе

Для доступу до цього ресурсу потрібна авторизація. Зрозуміло, наявність авторизації не гарантує того, що ресурс стане доступним, але не авторизувавшись, ви точно цього не дізнаєтесь. Виникає, наприклад, при спробі звернутися до закритої частини API або після закінчення терміну дії поточного токена.

403 Forbidden – вам сюди не можна

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

404 Not found - за цією адресою ніхто не живе

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

405 Method not allowed - не можна таке робити

Цей різновид виключення безпосередньо пов'язаний із використаним дієсловом (GET, PUT, POST, DELETE), який, у свою чергу, свідчить про дію, яку ми намагаємося зробити з ресурсом. Якщо запитаний ресурс не підтримує цю дію, сервер говорить про це прямо.

422 Unprocessable entity - виправте та надішліть знову

Один із найкорисніших винятків. Повертається щоразу, коли у даних запиту є логічні помилки. Під даними запиту ми маємо на увазі або набір параметрів і відповідних значень, переданих методом GET, або поля об'єкта, що передається в тілі запиту методами POST, PUT і DELETE. Якщо дані не пройшли валідацію, сервер у секції data повертає звіт про те, які саме параметри невалідні і чому.

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

Запити

Отримання елементів колекції

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

Посторінкова навігація

page- параметр вказує на те, яка сторінка має бути відображена. Якщо цей параметр не передано, то з'явиться перша сторінка. З першої ж успішної відповіді сервера буде зрозуміло, скільки сторінок має колекція за поточних параметрів фільтрації. Якщо значення перевищує максимальну кількість сторінок, то найрозумніше повернути помилку 404 Not found.

GET /api/v1/news?page=1

perPage- Вказує на бажану кількість елементів на сторінці. Як правило, API має власне значення за умовчанням, яке повертає як поле perPage у секції pagination, але в ряді випадків дозволяє збільшувати це значення до розумних меж, надавши максимальне значення maxPerPage:

GET /api/v1/news?perPage=100

Сортування результатів

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

sortBy- Існує кілька підходів до передачі даних про складне сортування в GET параметрах. Тут необхідно чітко вказати порядок сортування та напрямок.

У деяких API це пропонується зробити у вигляді рядка:

GET /api/v1/products?sortBy=name.desc,price.asc

В інших варіантах пропонується використовувати масив:

GET /api/v1/products? sortBy=name& sortBy=desc& sortBy=price& sortBy=asc

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

Проста фільтрація за значенням

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

GET /api/v1/articles?authorId=25

Ускладнені варіанти фільтрації

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

Фільтрування по верхній і нижній межі з використанням операторів порівняння from (більше або одно), higher (більше), to (менше або одно), lower (менше). Застосовується до полів, значення яких піддаються ранжування.

GET /api/v1/products?price=500&price=1000

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

GET /api/v1/products?status=1&status=2

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

GET /api/v1/users?name=John GET /api/v1/products?code=123

Іменовані фільтри

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

GET /api/v1/products?filters=recommended

Іменовані фільтри можуть мати свої параметри.

GET /api/v1/products?filters=kidds

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

Сподобалася стаття? Поділіться з друзями!