DNS, IP, порти та мережа
Зміст
Коли автотест виконує page.goto('https://app.example.com/login'), за одним рядком стоїть кілька шарів, і кожен ламається окремо: імʼя треба перетворити на адресу, до адреси достукатися, на машині знайти потрібний сервіс, а поверх усього встановити зʼєднання. Якщо будь-яка ланка спрацьовує повільно або нестабільно, тест «мигає» (flaky) без жодної помилки в продуктовому коді.
Ця глава — повний виклад теми на сайті, інші глави посилаються сюди по мережеву механіку. Мета одна: називати шар, на якому впав прогін, замість «щось із мережею». Побічна — розібрати чотири перекази, що звучать переконливо й розсипаються при першій звірці: «рекурсивний резолвер зобовʼязаний відповісти», «TTL — це симетричний компроміс», «DNS ходить по UDP, а на TCP переходить», «проксі буває прямий і зворотний». Далі в тексті вони пронумеровані в цьому ж порядку.
IP-адреса: куди насправді йде запит
IP-адреса (IP address) — числовий ідентифікатор вузла в мережі: саме за нею пакети знаходять дорогу до потрібного компʼютера. Але адреса веде лише до машини — що робити далі, вирішує вже порт.
IPv4 використовує 32 біти, які записують як чотири десяткові октети від 0 до 255. IPv6 використовує 128 біт і записується як вісім груп по чотири шістнадцяткові цифри; провідні нулі в групі опускають, а один ланцюжок нульових груп згортають до :: — саме один, двічі в адресі він стояти не може.
93.184.216.34
2001:0db8:85a3:0000:0000:8a2e:0370:7334
2001:db8:85a3::8a2e:370:7334
Два класи адрес AQA бачить щодня:
| Адреса / діапазон | Що це |
|---|---|
127.0.0.1, ::1 | loopback — «ця сама машина»: трафік не виходить у мережу, а розвертається всередині |
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 | приватні мережі: у публічному інтернеті не маршрутизуються |
Запис /16 — це CIDR-нотація: число після скісної риски каже, скільки старших біт адреси фіксовані як префікс мережі, а решта відводиться під адреси вузлів. Назовні приватні адреси випускає NAT (Network Address Translation) — підміна приватної адреси на публічну адресу роутера.
Багато вузлів сьогодні двостекові (dual-stack): мають і IPv4-, і IPv6-адресу. Клієнт пробує спочатку IPv6, а наступну спробу запускає з паузою, і паузу зроблено навмисно — «connection attempts SHOULD NOT be made simultaneously»; щойно одна вдалася, решту SHOULD скасувати. Для тестів це джерело плаваючих таймингів: на кривій IPv6-мережі перше зʼєднання «думає» довше, доки клієнт зробить на другу адресу.
Чому localhost іноді підводить
Класична підозра — «localhost резолвиться то в IPv4, то в IPv6». Резолв тут якраз однозначний: користувачі «may assume that IPv4 and IPv6 address queries for localhost names will always resolve to the respective IP loopback address», а бібліотекам резолву приписано SHOULD завжди повертати адресу loopback. За іменем доступні обидві адреси — і 127.0.0.1, і ::1.
Пастка в іншому: яке сімейство адрес клієнт спробує першим. Двостековий клієнт шле обидва запити, причому AAAA першим, і якщо відповіді прийшли не в тому порядку, SHOULD перечекати паузу, щоб перевага лишилася за IPv6. Тому якщо застосунок слухає лише 127.0.0.1, а клієнт пішов на ::1, зʼєднання «незрозуміло чому» не встановлюється. Рятує явна адреса в конфігу — або прослуховування обох сімейств на сервері.
// явна адреса замість імені прибирає питання, яке сімейство клієнт вибере першим
export default defineConfig({
use: { baseURL: 'http://127.0.0.1:3000' },
});
Порти: багато сервісів на одній адресі
На машині одночасно працюють десятки програм, тож самої адреси мало. Порт (port) — 16-бітне число від 0 до 65535, яким TCP ідентифікує сервіси застосунків і веде кілька окремих потоків між тими самими хостами.
Пара «адреса + порт» називається сокетом (socket), і головне тут — що зʼєднання визначає пара сокетів, локальний і віддалений. Саме тому браузер тримає багато паралельних зʼєднань до одного сервера: кожне унікальне четвіркою «джерело-IP : джерело-порт → призначення-IP : призначення-порт», а тимчасовий (ефемерний) порт клієнту видає операційна система.
Порти прийнято ділити на діапазони:
| Діапазон | Назва за класифікацією IANA |
|---|---|
| 0–1023 | системні, вони ж well-known |
| 1024–49151 | користувацькі, вони ж registered |
| 49152–65535 | динамічні, вони ж private або ephemeral |
Фактичний ефемерний діапазон залежить від операційної системи, тож на цільовій машині його варто перевіряти, а не брати з таблиці. Типові порти, які AQA бачить постійно: 80 (HTTP), 443 (HTTPS), 22 (SSH), 53 (DNS), 3306 (MySQL), 5432 (PostgreSQL), 6379 (Redis), 27017 (MongoDB), 8080 (альтернативний HTTP і dev-сервери). Для стандартних схем порт можна не писати — мається на увазі типовий (80 для http, 443 для https), а нестандартний треба вказувати явно.
Порт як компонент адреси розбирає глава «URL і кодування», як частину (origin) — «CORS і політика одного походження», а скільки зʼєднань браузер відкриває насправді — «HTTP/2 і HTTP/3: еволюція протоколу».
Наша практика (не канон). Далі — те, як це виглядає в командах, з якими ми працювали; окремого стандарту під це немає. Сервіс, піднятий на 127.0.0.1:3000, видно лише всередині тієї самої машини чи , а піднятий на 0.0.0.0:3000 — на всіх інтерфейсах; плутанина між цими двома адресами і є типовою причиною «у мене працює, а в CI ні». Другий сюжет того ж класу: фіксований порт у тесті, зайнятий попереднім незавершеним прогоном, дає address already in use — тому фреймворки або підбирають вільний порт динамічно, або вимагають чистого стану між прогонами.
DNS: від імені до адреси
Люди мислять іменами, мережа маршрутизує за числами. DNS (Domain Name System) — розподілена ієрархічна система, що перекладає одне в інше; формально вона складається з простору імен із ресурсними записами, серверів імен і резолверів.
Простір імен — дерево, де доменне імʼя вузла є послідовністю міток від нього до кореня, яку читають зліва направо: від найконкретнішої до найзагальнішої. Сервер імен тримає повні дані лише про частину дерева — свою зону, для якої він авторитетний; решту може мати в кеші й у відповіді позначає, звідки вона взялася. Зберігає DNS не тільки адреси:
| Тип запису | Що зберігає |
|---|---|
A | IPv4-адресу для імені |
AAAA | IPv6-адресу для імені |
CNAME | канонічне імʼя для псевдоніма |
NS | авторитетні сервери зони |
MX | поштові сервери домену |
TXT | довільні текстові рядки |
Ланцюг резолюції
Бібліотека резолюції операційної системи — це stub-резолвер: сам ієрархію він не обходить, а перекладає тягар на рекурсивний сервер імен у своїй або сусідній мережі.
Тепер перший переказ. «Рекурсивний резолвер зобовʼязаний повернути кінцеву відповідь» — не так. Нерекурсивний режим must реалізувати кожен сервер імен, а рекурсивний названо optional: сервер may обмежити коло клієнтів і взагалі free to refuse надавати рекурсію. Та й серед допустимих рекурсивних відповідей джерело перелічує не лише відповідь чи name error, а й A temporary error indication. Справжня різниця режимів інша: рекурсивний сервер повертає помилку або відповідь, але ніколи не відсилання. Прикладний висновок — тимчасова помилка резолюції є легальною відповіддю, яку прогін має вміти пережити.
Кеш, TTL і файл hosts
Ходити щоразу по всьому ланцюжку дорого, тому відповіді кешуються: кеш відповідає з памʼяті попередніх результатів і так прибирає мережеву й навантаження на сервери імен, а для повносервісного резолвера локальний кеш із протуханням даних — нормативна вимога (MUST). Кешувати можна й негативні результати на кшталт «імені не існує».
TTL (Time To Live) — межа того, скільки запис дозволено тримати в кеші, перш ніж відкинути. І тут другий переказ: TTL часто подають як симетричний вибір «великий — менше навантаження, малий — швидше перемикання». Джерело асиметричне: короткий TTL мінімізує , нульовий його забороняє, але «реалії продуктивності інтернету» дають орієнтир should be on the order of days for the typical host. Виняток названо окремо — якщо зміну можна передбачити, TTL знижують перед нею, а після повертають до колишнього значення. Тобто малий TTL є інструментом запланованого переїзду, а не станом за замовчуванням.
Наслідок для AQA прямий: якщо стенд нещодавно змінив адресу, а десь у ланцюжку живе старий запис із довгим TTL, прогін стукає за застарілою адресою й падає без жодної причини в застосунку — і чекати доводиться саме TTL. Дрібніший наслідок теж коштує зелених прогонів: час резолвінгу першого запиту додається до часу відкриття сторінки, тож «холодний» DNS буває причиною випадкового перевищення .
Локальна таблиця хостів (файл hosts) виглядає як спосіб це обійти, але формулювання специфікації варте уваги: вузол може мати таку таблицю «as a backup or supplement to the DNS», а питання пріоритету джерело лишає питанням конфігурації, а не сталим правилом. Практично: «я прописав у hosts, отже точно піде туди» — припущення, а не гарантія.
Транспорт: UDP, TCP і 512 байтів
Третій переказ: «DNS ходить по UDP на порт 53, а на TCP переходить для великих відповідей». Тут майже кожне слово має джерело — але не те, на яке зазвичай посилаються. RFC 1034 переваги транспорту не віддає взагалі: запити «are carried in UDP datagrams or over TCP connections». Перевагу дають інші документи — RFC 1035 називає датаграми переважнішими «due to their lower overhead and better performance», RFC 1123 формулює це як «UDP is preferred over TCP for queries». Далі три уточнення, які й ламають переказ:
- Порт 53 — той самий для обох транспортів, а не «порт 53 — це UDP».
- Обрізання нормовано. Повідомлення через UDP обмежене 512 байтами; довше обрізають із виставленим бітом
TC, і якщо секція Answer обрізана, запитувач, який уміє TCP,SHOULDповторити запит по TCP. - Передача зони — вимога, а не «перехід». UDP «is not acceptable for zone transfers», а TCP «is always used for full zone transfers (using AXFR)».
Чинну ж модальність задає RFC 7766, який оновлює обидва старі документи: «All general-purpose DNS implementations MUST support both UDP and TCP transport», а вимогу «спершу UDP» послаблено — резолвер MAY обрати транспорт із локальних міркувань. Наслідок буквальний: якщо в мережі стенду DNS-over-TCP заблоковано (типова «оптимізація» фаєрвола), великі відповіді не доходять, і джерело прямо називає результат — «resolution failure and/or application-level timeouts». У звіті це виглядає як таймаут застосунку, а причина лежить у конфігурації мережі.
Домен і адреса: чому це не один до одного
до адреси не взаємно однозначна, і кожен бік цієї несиметричності має наслідок для тестів.
- Один домен → багато адрес. Вузол із кількома інтернет-адресами просто має кілька
A-записів. - Багато доменів → одна адреса. Заголовок
Hostнесе хост і порт із цільового URI й дає origin-серверу змогу розрізняти ресурси, обслуговуючи запити для кількох імен. Це і є віртуальний хостинг; користувацький агентMUSTзгенеруватиHost, якщо не передає ту саму інформацію псевдозаголовком:authority. - Той самий домен → різні вузли в різних місцях. CDN (Content Delivery Network) — мережа проміжних серверів ближче до користувача, які тримають копії даних і віддають їх із найближчого вузла; CDN як спільний кеш розбирає глава «Кешування».
Практичний висновок: звертання напряму за адресою замість домену може не потрапити на потрібний віртуальний хост і ламає перевірку сертифіката — клієнт MUST переконатися, що особа сервісу відповідає origin-серверу з URI. Сертифікати розбирає глава «HTTPS, TLS і безпека».
TCP: надійний потік і ціна рукостискання
Знайти адресу замало — дані треба ще й доставити. TCP (Transmission Control Protocol) дає застосункам надійний потік байтів зі збереженням порядку, і саме тому HTTP/1.1 та HTTP/2 працюють поверх нього: вебу потрібна впевненість, що HTML, JSON і зображення прийдуть цілими й у правильній послідовності.
За цими словами стоять механізми. Потік їде сегментами, кожен окремою IP-датаграмою; втрати виявляються за номерами послідовності, помилки — за контрольними сумами, а виправляє їх повторна передача. Кожен байт має номер, тож підтвердження накопичувальне: ACK на X означає, що отримано всі октети до X, не включаючи сам X. Понад це TCP керує потоком і перевантаженням, щоб не завалити ні , ні мережу.
| Властивість | TCP | UDP |
|---|---|---|
| Зʼєднання | встановлюється рукостисканням | немає |
| Надійність доставки | так, із повторною передачею | ні |
| Порядок | збережений | не гарантований |
| Накладні витрати | вищі | нижчі |
| Затримка на старті | більша | мінімальна |
Ціну видно на старті. Перш ніж передати хоч байт корисних даних, TCP встановлює зʼєднання тристороннім (handshake): одна сторона ініціює, інша відповідає, і кроків саме три, бо підтвердження й власний SYN сервера обʼєднані в одне повідомлення.
Клієнт ── SYN ─────────────▶ Сервер (хочу зʼєднатися)
Клієнт ◀───── SYN-ACK ────── Сервер (згоден, і я теж хочу)
Клієнт ── ACK ─────────────▶ Сервер (підтверджую, працюємо)
У цьому обміні сторони повідомляють одна одній початкові номери послідовності. Для HTTPS поверх нього накладається ще й рукостискання TLS, тож до першого корисного байта встигає пройти кілька обмінів «туди-назад»: механіку TLS розбирає глава «HTTPS, TLS і безпека», а рукостискання як стадію шляху запиту — «Життєвий цикл запиту». Виняток серед версій HTTP — HTTP/3: він побудований на QUIC поверх UDP, і надійність та впорядкування там реалізовані власними засобами QUIC.
Затримка проти пропускної здатності
Дві характеристики каналу, які постійно плутають, а вони про різне.
Затримка (latency) — час, за який пакет даних долає шлях від джерела до призначення; її ж рахують як час від запиту користувача до повернення відповіді. Міряють її зазвичай від машини-запитувача до машини-відповідача і назад, тобто як round-trip delay: формально це інтервал від відправлення джерелом першого біта пакета до отримання ним останнього біта відповіді. (bandwidth) — міра того, скільки інформації може пройти крізь зʼєднання за заданий проміжок часу; вимірюють кратними бітам за секунду.
Що це незалежні осі, видно з самого TCP: там існує добуток «пропускна здатність × затримка», і коли він великий, зʼявляються проблеми продуктивності — мережу з такими шляхами називають «long, fat network». Більшої пропускної здатності не досить: на таких шляхах вікно приймача обмежує обсяг непідтверджених даних, який TCP може відправити, щоб тримати «трубу» заповненою. Для тестів різниця прикладна:
- Дії з багатьма дрібними запитами страждають від затримки. Затримка одного ресурсу здається дрібницею, але сторінка — це багато запитів; що їх більше, то дужче вона бʼє по користувацькому досвіду.
- Завантаження великих файлів упирається в іншу характеристику. Фаза
Receivingвизначається сукупністю пропускної здатності мережі та розміру файла. - Перший запит платить більше. У його затримку входять DNS-пошук, TCP-рукостискання й узгодження TLS; наступні дешевші, бо зʼєднання вже встановлене — саме тому HTTP тримає його відкритим (keep-alive) і перевикористовує.
- Не плутай мережеву затримку з дисковою. Дискова — час від отримання запиту сервером до повернення відповіді, у панелі це фаза
Waiting; як на неї реагують очікування в тестах, розбирає глава «Практичні сценарії AQA: флак і синхронізація».
Посередники: проксі, шлюз, тунель
Четвертий переказ — «посередники бувають прямі й зворотні». HTTP називає три поширені форми (intermediary) — вузла, через який запити задовольняються «through a chain of connections», — і терміна forward proxy в специфікації немає взагалі.
| Форма | Визначальна ознака |
|---|---|
| Проксі (proxy) | агент пересилання, якого обирає клієнт — зазвичай локальними правилами конфігурації |
| Шлюз (gateway), він же reverse proxy | посередник, який поводиться як origin-сервер для вихідного зʼєднання, а всередину пересилає запити іншим серверам |
| Тунель (tunnel) | сліпий ретранслятор між двома зʼєднаннями, який повідомлень не змінює |
Різниця не в тому, «з якого боку стоїть» вузол, а в тому, хто його обрав і як він поводиться. обирає клієнт — типово, щоб звести запити організації через спільного посередника заради безпекових сервісів, сервісів анотації або спільного кешу. назовні виглядає як origin-сервер, тому за ним живуть кешування-прискорювач та розділення або балансування навантаження між машинами: балансувальник тут є окремим випадком шлюзу, а не «ще одним видом проксі». в HTTP-обміні не бере участі взагалі й зникає, коли обидва кінці ретрансльованого зʼєднання закрито. Той самий вузол може перемикатися між ролями — і навіть бути origin-сервером — залежно від конкретного запиту.
Окремий клас — вузли нижчих рівнів стека, що фільтрують або перенаправляють трафік без відома й дозволу відправника. Такий interception proxy відрізняється від звичайного проксі саме тим, що його не обирає клієнт, і специфікація оцінює його різко: на рівні протоколу він «indistinguishable (at a protocol level) from an on-path attacker». Уразливий він і сам — коли покладається на хост і порт як на ключ спільного кешу, не перевіривши, що перехоплене зʼєднання йде на валідну адресу цього хоста. Для AQA це робоча гіпотеза: якщо тест поводиться в офісній мережі інакше, ніж удома, між ним і сервером цілком може стояти вузол, якого ніхто не обирав.
Два практичні хвости. 502 і 504 за означенням віддає сервер, що діє «as a gateway or proxy», тобто зламалася ланка за посередником, а 503 каже про сам сервер — значення кодів розбирає глава «HTTP статус-коди». І оскільки проксі бачить увесь трафік, він може його не лише передавати, а й інспектувати та змінювати: на цьому будується , вбудоване й у фреймворки автотестів — глава «Перехоплення й мокання мережі».
Наостанок термін, який побутове означення зміщує. VPN (Virtual Private Network) — загальний термін для використання публічних або приватних мереж, щоб створити групи користувачів, відокремлені від решти й здатні спілкуватися між собою так, ніби вони в приватній мережі; наскрізне шифрування джерело називає посиленням цього відокремлення, а не визначальною ознакою. Тому корпоративний VPN дає доступ до внутрішніх стендів не тим, що «щось шифрує», а тим, що робить машину частиною такої групи.
Тротлінг і діагностика мережевого шару
Мережу можна не лише спостерігати, а й керовано псувати. (throttling) у панелі інструментів розробника емулює нижчий клас зʼєднання, задаючи швидкість завантаження, швидкість віддачі й мінімальну затримку. Пресети різняться між браузерами й змінюються між версіями Chrome, тож для відтворюваних умов надійніше задати власний профіль із фіксованими значеннями, ніж покладатися на назву пресета. Поруч живе режим Offline — дешева перевірка деградації: чи повідомляє застосунок про втрату мережі. Саму панель, її колонки й HAR розбирає глава «DevTools: вкладка Network і дебаг».
Коли ж треба зрозуміти, який шар гальмує, час запиту розкладають змінними --write-out у curl:
curl -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n" \
-o /dev/null -s https://app.example.com/login
time_namelookup — резолвінг імені, time_connect — встановлення TCP-зʼєднання, time_appconnect — завершення TLS, time_starttransfer — прихід першого байта. Усі значення відлічуються від старту запиту, тому кожне наступне включає попереднє: дивитися треба на різниці між сусідніми. Так «тест падає з таймауту» перетворюється на діагноз — імʼя не резолвиться, зʼєднання не встановлюється або сервер довго думає. конкретного інструмента розбирає розділ про автоматизацію.
Наша практика (не канон). Канону під це немає — далі досвід команд. Тротлінг оголює стани завантаження (чи є спінер, чи не «моргає» порожній екран) і відтворює гонки, яких на швидкому каналі просто не встигає статися — класика тут кнопка, що лишається активною, поки запит іще летить, і дає подвійне надсилання. Звідси й ставлення до падінь на повільному профілі: тест там не «флакне» — він просто ще не впав, бо очікування в ньому недостатньо привʼязані до подій.
Типові помилки
- Виглядає як «рекурсивний резолвер зобовʼязаний дати відповідь», а насправді рекурсія — сервіс
optional, серверfree to refuseїї надавати, а тимчасова помилка резолюції є легальною відповіддю. - Виглядає як «DNS ходить по UDP, а на TCP переходить», а насправді обидва транспорти обовʼязкові (
MUST support both), порт 53 у них спільний, а передача зони по TCP — вимога, а не запасний варіант. - Виглядає як «localhost — це просто 127.0.0.1», а насправді за іменем доступні обидві адреси loopback, і двостековий клієнт віддає перевагу IPv6: сервіс, що слухає лише IPv4, для нього мовчить.
- Виглядає як «проксі буває прямий і зворотний», а насправді форм три — проксі, шлюз і тунель, — і розрізняє їх не бік, а те, хто вузол обрав і як він поводиться.
- Виглядає як «канал широкий, отже швидкий», а насправді пропускна здатність і затримка незалежні: канал буває водночас «товстим» і «довгим».
- Виглядає як «прописав у hosts — отже точно піде туди», а насправді таблиця хостів є резервом або доповненням до DNS, а пріоритет джерела лишається питанням конфігурації вузла.
Підсумок
- Адреса веде до машини, порт — до сервісу на ній, а зʼєднання однозначно визначає пара сокетів, а не один бік.
- DNS — не миттєвий довідник, а система з кешем: TTL вирішує, чи побачить прогін новий стенд, і «холодна» резолюція входить у час першого відкриття сторінки.
- TCP платить рукостисканням за надійність і порядок, тож перший запит до хоста завжди дорожчий за наступні — і ця плата потрапляє в кожен таймаут.
- Затримка й пропускна здатність — різні осі: перша ламає сценарії з багатьма дрібними запитами, друга — завантаження великих файлів.
- Посередник визначається не боком, з якого стоїть, а тим, хто його обрав; вузол, якого клієнт не обирав, протокольно невідрізненний від на шляху.
Можливі питання
- «Що відбувається після того, як користувач увів адресу й натиснув Enter?» Питання-парасолька. Тут слухають, чи назвете шари по черзі — резолвінг імені, зʼєднання за адресою й портом, рукостискання, запит — і чи не поплутаєте їхній порядок.
- «Чим порт відрізняється від адреси і що таке сокет?» Перевіряють базу адресації. Сильна відповідь називає порт номером сервісу, сокет — парою «адреса + порт», а зʼєднання — парою сокетів.
- «Що таке TTL і чому тест може стукати не на той стенд?» Дивляться, чи звʼязуєте теорію з практикою: кеш резолвера, строк життя запису й висновок, що після зміни адреси доводиться чекати, а не «перезапустити тест».
- «Чим затримка відрізняється від пропускної здатності?» Класика на плутанину. Очікують не лише означення, а й приклад, де вони розходяться: багато дрібних запитів проти одного великого файла.
- «Тест падає з таймауту в CI, локально зелений. Ваші дії?» Міні-кейс, у якому слухають порядок: спершу шар (резолвінг, зʼєднання, очікування сервера), потім мережа середовища (посередник, заблокований транспорт, VPN), і лише тоді код тесту.
Джерела
IP-адреса: куди насправді йде запит
- RFC 791 — Internet Protocol — IPv4-адреса завдовжки чотири октети (32 біти) як ідентифікатор вузла.
- RFC 4291 — IP Version 6 Addressing Architecture — 128-бітні адреси, правила скорочення запису й
::1як loopback. - RFC 1122 — Requirements for Internet Hosts: Communication Layers — призначення loopback-адреси.
- RFC 1918 — Address Allocation for Private Internets — три приватні діапазони та їхня немаршрутизовність у публічному інтернеті.
- RFC 3022 — Traditional IP Network Address Translator (Traditional NAT) — трансляція приватної адреси в публічну.
- RFC 4632 — Classless Inter-domain Routing (CIDR) — значення числа після скісної риски в записі мережі.
- RFC 8305 — Happy Eyeballs Version 2 — порядок спроб зʼєднання у двостекового клієнта й скасування решти після успіху.
Чому localhost іноді підводить
- RFC 6761 — Special-Use Domain Names — §6.3: запити адрес для
localhost-імен завжди резолвляться у відповідну адресу loopback. - RFC 8305 — Happy Eyeballs Version 2 —
AAAAнадсилається першим і перевага прямо віддається IPv6.
Порти: багато сервісів на одній адресі
- RFC 9293 — Transmission Control Protocol (TCP) — порт як 16-бітний номер сервісу, сокет як конкатенація адреси з портом і зʼєднання як пара сокетів.
- RFC 6335 — IANA Procedures for Port Numbers — три діапазони портів і ефемерні порти клієнтських зʼєднань.
- IANA — Service Name and Transport Protocol Port Number Registry — закріплені номери типових сервісів.
- RFC 9110 — HTTP Semantics — типові порти схем
httpіhttps, які можна не писати в адресі.
- RFC 1034 — Domain Names: Concepts and Facilities — три складники DNS, дерево імен і зони, ланцюг резолюції, рекурсія як
optional-сервіс, TTL і орієнтир «порядок днів». - RFC 1035 — Domain Names: Implementation and Specification — типи ресурсних записів, перевага датаграм, порт 53 для обох транспортів, межа 512 байтів і біт
TC. - RFC 3596 — DNS Extensions to Support IP Version 6 — запис
AAAAдля IPv6-адрес. - RFC 1123 — Requirements for Internet Hosts -- Application and Support — stub-резолвер, кеш як нормативна вимога, файл
hostsяк резерв або доповнення до DNS, «UDP is preferred over TCP for queries». - RFC 7766 — DNS Transport over TCP - Implementation Requirements — чинна вимога підтримувати обидва транспорти й наслідки блокування DNS-over-TCP.
- curl — manual page (--write-out variables) — час резолвінгу як окрема складова часу запиту.
Домен і адреса: чому це не один до одного
- RFC 1035 — Domain Names: Implementation and Specification — вузол із кількома адресами має кілька
A-записів. - RFC 9110 — HTTP Semantics —
Hostі віртуальний хостинг, вимога перевірити відповідність особи сервісу origin-серверу з URI. - MDN Glossary — CDN — копії даних у багатьох локаціях і віддача з найближчого до користувача вузла.
TCP: надійний потік і ціна рукостискання
- RFC 9293 — Transmission Control Protocol (TCP) — надійний упорядкований потік, сегменти й повторна передача, накопичувальні підтвердження, тристороннє рукостискання.
- RFC 768 — User Datagram Protocol — датаграмний транспорт без встановлення зʼєднання й без гарантій.
- RFC 9000 — QUIC: A UDP-Based Multiplexed and Secure Transport — надійність і впорядкування засобами QUIC поверх UDP.
- RFC 9114 — HTTP/3 — HTTP/3 як версія протоколу поверх QUIC.
- RFC 8446 — TLS 1.3 — рукостискання TLS поверх надійного транспорту перед корисним трафіком.
Затримка проти пропускної здатності
- MDN — Understanding latency — означення затримки, вартість першого запиту, фаза
Receivingі різниця з дисковою затримкою. - MDN Glossary — Bandwidth — означення пропускної здатності й одиниці виміру.
- RFC 2681 — A Round-trip Delay Metric for IPPM — формальне означення round-trip delay.
- RFC 7323 — TCP Extensions for High Performance — добуток «пропускна здатність × затримка»,
long, fat networkі роль вікна приймача. - MDN — Connection management in HTTP/1.x — відкритого зʼєднання замість нового рукостискання.
Посередники: проксі, шлюз, тунель
- RFC 9110 — HTTP Semantics — три форми посередника та їхні визначальні ознаки, балансування як застосування шлюзу,
interception proxyі його , коди502/504проти503. - mitmproxy — How mitmproxy works — проксі бачить трафік і може його інспектувати та змінювати.
- Playwright — Network — той самий принцип перехоплення всередині браузера, без окремого інструмента.
- RFC 4026 — Provider Provisioned Virtual Private Network (VPN) Terminology — означення VPN через відокремлені групи користувачів.
Тротлінг і діагностика мережевого шару
- MDN — Understanding latency — що саме емулює перемикання на нижчий клас зʼєднання й що пресети різняться між браузерами.
- Chrome DevTools — Network features reference — пресети тротлінгу, власний профіль і режим Offline.
- curl — manual page (--write-out variables) — змінні розкладу часу запиту по шарах.
Що таке IP-адреса і чим IPv4 відрізняється від IPv6?
IP-адреса (IP address) — число, за яким мережа впізнає конкретну машину: маршрут пакета будується саме по ньому, а доменне імʼя лише зручна обгортка зверху. Стара версія протоколу відводить під адресу 32 біти й записує їх чотирма десятковими октетами через крапку, кожен у межах 0–255. Новіша бере 128 біт і пише їх вісьмома групами по чотири шістнадцяткові цифри через двокрапку. Запис прийнято скорочувати: провідні нулі всередині групи не пишуть, а суцільний ланцюжок нульових груп замінюють на :: — причому такий пропуск в адресі дозволений рівно один, бо інакше відновити довжину пропущеного було б неможливо. Для тестувальника наслідок простий: хоч би що стояло в baseURL, запит зрештою піде на конкретне число, і всі сюжети «потрапив не туди» живуть саме на цьому рівні.
Чим 127.0.0.1 відрізняється від 0.0.0.0 і чому «локально працює, а в CI ні»?
Перша адреса — loopback: трафік на неї не залишає машину, а замикається всередині неї (у IPv6 ту саму роль грає ::1). Друга при прослуховуванні означає не якийсь один інтерфейс, а всі одразу. Звідси прикладна різниця: сервер, привʼязаний до loopback, бачать лише процеси тієї самої машини чи того самого , а привʼязаний до 0.0.0.0 — будь-хто, хто дістає машину по мережі. Класичне падіння в CI саме таке: сервіс піднято на loopback, локально все зелене, а із сусіднього контейнера стукає ззовні й отримує зʼєднання. У звіті це виглядає як мережева проблема, хоча насправді питання лише в тому, який інтерфейс слухає сервер.
localhost резолвиться то в IPv4, то в IPv6 — це правда?
Ні, і плутанина тут не в резолві. Специфікація спеціальних імен якраз гарантує зворотне: запит адреси для localhost-імені дає відповідну loopback-адресу і для IPv4, і для IPv6, а бібліотекам резолву це приписано як SHOULD. Тобто обидві адреси доступні за іменем, ніякої лотереї немає. Лотерея — у тому, куди клієнт піде першим: двостековий (dual-stack) клієнт надсилає запит AAAA раніше й свідомо тримає перевагу за IPv6, а якщо відповіді повернулися не в тому порядку, SHOULD витримати паузу, щоб цю перевагу не втратити. Тому сервер, який слухає лише 127.0.0.1, для такого клієнта просто мовчить — рятує або явна адреса в конфігу замість імені, або прослуховування обох сімейств. Той самий механізм породжує плаваючі тайминги: спроби зʼєднання навмисно не запускають одночасно (SHOULD NOT be made simultaneously), тож на кривій IPv6-мережі перше зʼєднання довго «думає», доки клієнт зробить на другу адресу, а після першого успіху решту спроб SHOULD скасувати.
Що таке приватні діапазони, як читати CIDR і навіщо потрібен NAT?
Три блоки — 10.0.0.0/8, 172.16.0.0/12 і 192.168.0.0/16 — зарезервовані під внутрішні мережі й у публічному інтернеті не маршрутизуються. Число після скісної риски — це CIDR-нотація: воно каже, скільки старших біт адреси закріплено за префіксом мережі, а решта біт лишається під адреси самих вузлів. Тобто /8 фіксує чверть 32-бітної адреси, /16 — половину, /24 — три чверті. Оскільки внутрішню адресу назовні предʼявити не можна, роутер підміняє її на свою публічну — це і є NAT (Network Address Translation). Для AQA це щоденний фон: домашня, офісна, CI- і docker-мережі живуть саме в цих блоках, а тікети на доступи описують діапазони тією самою CIDR-мовою — «дозволити з 10.0.0.0/8».
Що таке порт, сокет і ефемерний порт?
Порт (port) — 16-бітний номер у межах 0–65535; ним транспортний рівень розрізняє сервіси, що працюють на одній машині: адреса доводить до компʼютера, порт — до конкретної програми на ньому. Пара «адреса + порт» називається сокетом (socket), і ключова деталь у тому, що TCP-зʼєднання визначає не один сокет, а їхня пара — локальний і віддалений. Саме тому браузер тримає багато одночасних зʼєднань до одного сервера: кожне унікальне четвіркою «адреса й порт джерела → адреса й порт призначення», а локальний порт клієнту щоразу видає операційна система з тимчасового, ефемерного набору. IANA ділить простір на три частини: 0–1023 системні (well-known), 1024–49151 користувацькі (registered), 49152–65535 динамічні (private, вони ж ephemeral). Тонкість, на якій ловляться: реальний ефемерний діапазон задає операційна система, і він часто не збігається з рекомендованим, тож на цільовій машині його краще подивитися, а не процитувати таблицю.
Чому 8080 треба писати в адресі явно, а 443 ні, і звідки береться address already in use?
Для стандартних схем порт мається на увазі: коли підкомпонент порту порожній, http іде на 80, а https — на 443. Схеми, яка за замовчуванням веде на 8080, не існує — це просто ще один зареєстрований порт (у реєстрі він записаний як HTTP Alternate), тому dev-сервер на ньому доводиться прописувати в baseURL повністю. Набір типових портів, які AQA бачить постійно, невеликий: 80, 443, 22, 53, 3306, 5432, 6379, 27017, 8080. Друга половина питання — про фіксовані порти в тестах: якщо піднімає сервер на жорстко заданому порту, а попередній прогін не прибрав за собою, старт валиться з address already in use. Власника порту показує lsof -i :3000, доступність порту на віддаленому хості — nc -zv host 443. Лікується це двома шляхами: фреймворк підбирає вільний порт динамічно або набір вимагає чистого стану між прогонами — зупиняє сервер у teardown, а не сподівається, що той «сам звільниться».
З чого складається DNS і які записи варто знати напамʼять?
Формально система має три частини: простір доменних імен разом із ресурсними записами, сервери імен і резолвери. Простір імен — дерево, і повне імʼя вузла складається з міток на шляху від нього до кореня, які читають зліва направо: від найвужчої до найширшої. База розрізана на зони; сервер тримає повні дані лише про свою зону — для неї він авторитетний, — а решту може мати в кеші, і у відповіді він позначає, з якого джерела вона взялася. Це поле напряму придатне для діагностики: воно відрізняє «сервер знає» від «сервер згадав». Записи, з якими AQA стикається: A тримає IPv4-адресу імені, AAAA — IPv6-адресу, CNAME вказує канонічне імʼя для псевдоніма, NS перелічує сервери, авторитетні для зони, MX — сервери, куди йде пошта домену, а TXT везе довільний рядок (через нього підтверджують володіння доменом і публікують поштові політики). Найчастіші в роботі — A та AAAA (куди насправді летить трафік) і CNAME (чому імʼя стенда раптом веде на чужу інфраструктуру).
Опиши ланцюг резолюції домену з нуля.
Застосунок звертається не в мережу, а до бібліотеки резолюції своєї операційної системи — це stub-резолвер, і дерево він не обходить: усю чорнову роботу віддає рекурсивному серверу імен — своєму мережевому або сусідньому. Далі рекурсивний сервер іде згори: питає кореневі сервери, ті відкривають доступ до всього простору імен, але кінцевої адреси не знають і відсилають до серверів зони верхнього рівня; ті — до авторитетних серверів домену; і вже авторитетний віддає A-запис. Відповідь повертається до застосунку, і лише тоді відкривається зʼєднання. На практиці повний обхід трапляється рідко, бо майже кожну ланку хтось уже закешував — саме тому перший запит у прогоні дорожчий за решту, а час резолвінгу входить у час відкриття сторінки нарівні з іншими шарами.
Чи зобовʼязаний рекурсивний резолвер повернути кінцеву відповідь?
Ні — це один із найстійкіших переказів, і джерело каже прямо протилежне. Рекурсивний режим названо optional: сервер може його взагалі не надавати, може обмежити коло клієнтів, яким його надає, і формально він free to refuse рекурсію будь-кому або всім. Нерекурсивний режим, навпаки, must реалізувати кожен сервер імен. Навіть коли рекурсію надано, «кінцева відповідь» не гарантована: серед допустимих рекурсивних відповідей поряд із результатом і name error стоїть A temporary error indication. Справжня різниця режимів пролягає в іншому місці: рекурсивний сервер повертає або відповідь, або помилку, але ніколи не відсилання до іншого сервера. Прикладний висновок для прогону: тимчасова помилка резолюції — легальна відповідь, а не аварія, тож набір має її пережити, а не падати з висновком «мережа зламалась».
Що таке TTL і як його правильно обирати?
TTL (Time To Live) — верхня межа того, скільки відповідь дозволено тримати в кеші, перш ніж викинути; побачити його можна прямо у виводі dig +noall +answer. тут не оптимізація «за бажанням»: повносервісному резолверу локальний кеш із протуханням даних приписано як MUST, і зберігати можна не тільки вдалі відповіді, а й негативні на кшталт «такого імені немає». Вибір величини часто подають як симетричний компроміс, і це помилка: джерело асиметричне — короткий TTL мінімізує кешування, нульовий забороняє його зовсім, але орієнтир для типового вузла названо як should be on the order of days. Виняток прописано окремо: коли переїзд заплановано заздалегідь, TTL опускають до нього, щоб зменшити неузгодженість, а щойно все влаштувалося — піднімають назад. Тобто малий TTL — інструмент запланованого переїзду, а не нормальний робочий стан. Для тестів наслідок буквальний: після зміни адреси стенда прогін ще якийсь час стукатиме за старою, і чекати доводиться саме TTL — перезапуск сюїти тут не допомагає.
Файл hosts завжди перебиває DNS?
Ні, і формулювання специфікації обережніше за побутове уявлення: вузол може мати локальну таблицю хостів як резерв або доповнення до DNS, а те, що з двох джерел має пріоритет, лишено питанням конфігурації конкретного вузла, а не сталою нормою. Практичних висновків із цього два. Перший: прописати домен у hosts — зручний спосіб детерміновано направити тести на потрібний стенд, і він кращий за похід напряму за IP, бо імʼя в запиті лишається правильним. Другий: «я прописав, отже точно піде туди» — припущення, а не гарантія. Якщо тест уперто йде не туди, порядок джерел на цій машині чи в цьому треба перевірити, а не вважати відомим.
DNS ходить по UDP чи по TCP?
По обох, і на тому самому порту 53 — «порт 53 — це UDP» вже неточність. Далі важливо не переплутати документи. Базовий документ переваги транспорту не роздає взагалі: він каже лише, що запити везуть у UDP-датаграмах або по TCP-зʼєднаннях. Перевагу датаграмам дають інші документи — через менші накладні витрати й кращу продуктивність, і саме там зʼявляється формулювання «UDP is preferred over TCP for queries». Чинну ж модальність задає пізніший документ, що оновлює обидва старі: All general-purpose DNS implementations MUST support both UDP and TCP transport. Безумовне «спершу UDP» він при цьому послабив: вибір транспорту віддано резолверу — той MAY вирішувати за власними експлуатаційними міркуваннями, — а TCP там прямо названо повноцінною альтернативою, а не суто варіантом . Практичний наслідок: ставлення до TCP як до «запасного» шляху й фільтрація його на фаєрволі — та сама помилка, що ламає резолюцію на стендах.
Що таке truncated-фолбек і чому він цікавий тестувальнику?
Повідомлення, яке їде по UDP, обмежене 512 байтами. Довше обрізають і виставляють у заголовку біт TC; якщо обрізаною виявилася секція Answer, а запитувач уміє TCP, він SHOULD повторити запит уже по TCP. Поруч живе сусідній сюжет, де модальність ще жорсткіша: передача зони — не «перехід на TCP за потреби», а вимога, бо UDP для неї is not acceptable, а повний трансфер через AXFR завжди йде по TCP. Різниця у формулюванні тут і є змістом: «переходить, коли треба» описує вибір, must описує обовʼязок. Тестувальнику цей блок потрібен заради однієї конкретної гіпотези: якщо в мережі стенда заблоковано DNS-over-TCP, великі відповіді просто не дійдуть, а наслідок джерело формулює буквально: «resolution failure and/or application-level timeouts». Тобто звіт покаже застосунку, тоді як зламано конфігурацію мережі.
Чому звʼязок «домен ↔ IP» не один до одного і чому не варто ходити в тестах напряму за IP?
Несиметрія тут із трьох боків одразу. Один вузол може мати кілька інтернет-адрес — тоді в нього просто кілька A-записів. Багато доменів можуть жити за однією адресою: сервер розрізняє їх за заголовком Host, який везе хост і порт із цільового URI й дозволяє origin-серверу обслуговувати кілька імен на одній машині; користувацький агент MUST цей заголовок згенерувати, якщо не передає ту саму інформацію псевдозаголовком :authority. І той самий домен може вести на різні машини в різних місцях — так працює CDN (Content Delivery Network), що тримає копії даних і віддає їх із найближчого до користувача вузла. Звідси й відповідь на другу половину: похід за адресою обходить рівно ті механізми, на яких стоїть продукт. Можна не потрапити на потрібний віртуальний хост, а перевірка сертифіката ламається за самою нормою: клієнту приписано MUST звірити особу сервісу з тим origin-сервером, який названо в URI. Коли треба детерміновано влучити в конкретний стенд, правильний інструмент — локальна таблиця хостів, а не IP в адресному рядку.
Які гарантії дає TCP, як влаштоване рукостискання і чому HTTP/3 — виняток?
TCP (Transmission Control Protocol) дає застосунку надійний потік байтів зі збереженим порядком, і саме заради цього HTTP/1.1 та HTTP/2 стоять на ньому: HTML, JSON і картинка мають прийти цілими й у правильній послідовності. Механіка за цими словами така: потік їде сегментами, кожен окремою IP-датаграмою; втрату видно за номерами послідовності, пошкодження — за контрольними сумами, а лікує обидва випадки повторна передача. Нумерація наскрізна побайтова, тому підтвердження накопичувальне: ACK зі значенням X означає «усе до X отримано», причому сам X іще ні. Зверху на це накладено керування потоком і перевантаженням: швидкість підлаштовується так, щоб не поховати ні , ні саму мережу. Ціна гарантій платиться на старті: перед першим корисним байтом іде тристороннє (handshake) SYN → SYN-ACK → ACK, і кроків саме три, бо сервер склеює підтвердження клієнтового SYN зі своїм власним SYN в одне повідомлення; заразом сторони обмінюються початковими номерами послідовності. Для HTTPS поверх цього лягає ще й рукостискання TLS, тож до першого байта відповіді встигає пройти кілька обмінів «туди-назад» — звідси й сенс тримати зʼєднання відкритим (keep-alive), щоб не платити за це щоразу. Серед версій протоколу випадає один: HTTP/3 стоїть не на TCP, а на QUIC, який працює поверх UDP і забезпечує впорядковану надійну доставку власними механізмами.
Чим затримка відрізняється від пропускної здатності?
Це різні осі, а не два імені одного. (latency) — час, за який дані долають шлях від відправника до одержувача; на практиці мережеву затримку міряють у обидва боки, як round-trip delay: від моменту, коли джерело відправило перший біт запиту, до моменту, коли воно отримало останній біт відповіді. (bandwidth) — скільки інформації канал пропускає за одиницю часу, і міряють її кратними бітам за секунду. Що осі незалежні, видно вже із самого TCP: там існує добуток «пропускна здатність × затримка», і шляхи з великим добутком мають власну назву — long, fat network, тобто канал буває водночас товстим і довгим. Більшої пропускної здатності на такому шляху не досить: обсяг непідтверджених даних «у дорозі» обмежує вікно приймача. Для тестів різниця цілком прикладна: сценарій із десятками дрібних запитів ріже саме затримка, бо кожен ресурс платить свій час і вони складаються, а завантаження великого файла впирається в іншу характеристику — тривалість фази Receiving визначає сукупність пропускної здатності й розміру файла.
Скільки форм посередника означує HTTP і що таке interception proxy?
Три, а не дві: proxy, gateway і tunnel, причому терміна forward proxy у специфікації немає взагалі. Розрізняє їх не бік, з якого стоїть вузол, а те, хто його обрав і як він поводиться. — агент пересилання, якого обирає клієнт, зазвичай локальними правилами конфігурації; організації зводять через нього запити заради безпекових сервісів, сервісів анотації або спільного кешу. (він же reverse proxy) визначається тим, що назовні поводиться як origin-сервер, а всередину транслює й пересилає запити далі; за ним і живуть кеш-прискорювач та розділення чи балансування навантаження між машинами — балансувальник тут окремий випадок шлюзу, а не «ще один вид проксі». — сліпий ретранслятор між двома зʼєднаннями: повідомлень він не змінює, учасником HTTP-обміну не вважається й зникає, щойно обидва кінці ретрансльованого зʼєднання закриють; типове застосування — протягнути TLS крізь спільний фаєрвольний проксі. Один і той самий вузол може перемикатися між цими ролями від запиту до запиту. Окремо стоїть interception proxy: його визначальна ознака протилежна до проксі — його не обирає клієнт, він фільтрує чи перенаправляє трафік на рівнях нижче застосунку, і специфікація оцінює його різко: на рівні протоколу такий вузол невідрізненний від на шляху. Уразливий він і сам — коли бере хост із портом за ключ спільного кешу, не перевіривши, що перехоплене зʼєднання взагалі йшло на валідну адресу цього хоста.
502, 503 і 504 — усі три від посередника?
Ні, і плутанина коштує часу на діагностиці. 502 за означенням віддає сервер, який діє як шлюз або проксі й отримав невалідну відповідь від сервера за собою. 504 — той самий сервер у тій самій ролі, тільки причина інша: він не дочекався своєчасної відповіді від вищого сервера. А 503 про не каже нічого: він означає, що сам сервер зараз не здатен обробити запит — тимчасове перевантаження або планові роботи. Читати їх тому треба по-різному: 502 і 504 показують пальцем на ланку за посередником, тож дивитися варто в бекенд і його доступність, а 503 — це сервер, який сам про себе сказав «зараз не можу», і перевіряти треба його стан та вікна релізів.
Що таке VPN за канонічним означенням і чого він не робить?
Канон визначає VPN (Virtual Private Network) широко: це загальна назва для практики, коли публічні чи приватні мережі використовують, щоб зібрати групу учасників, відрізану від решти мережі, усередині якої вони спілкуються між собою так, наче мають власну приватну мережу. Ключова деталь у продовженні означення: наскрізне шифрування там названо способом посилити це відокремлення, а не визначальною ознакою. Тобто побутове «VPN — це коли трафік шифрується» зміщує акцент: шифрування є підсиленням, а суть — членство в групі. Для AQA це не термінологічна прискіпливість, а пояснення механізму: корпоративний VPN відкриває внутрішні стенди не тому, що «щось зашифрував», а тому, що робить машину частиною відокремленої групи. Звідси й вимога до інфраструктури тестів: якщо ранер поза цією групою, до внутрішнього середовища він не достукається жодним підкручуванням таймаутів — доступ треба закладати в конфігурацію CI.
Тест періодично падає по таймауту на першому кроці. Як звузити причину?
Насамперед розкласти час запиту по шарах, а не гадати — це вміє curl через змінні --write-out: time_namelookup показує, скільки зайняв пошук імені, time_connect — доведення TCP-зʼєднання до кінця, time_appconnect — момент, коли добіг TLS, time_starttransfer — надходження першого байта відповіді. Головна пастка в читанні: усі чотири відлічуються від старту запиту, тому кожне наступне вже містить попереднє, і сенс мають різниці між сусідніми, а не абсолютні числа. connect − dns — це власне TCP-рукостискання, tls − connect — TLS, ttfb − tls — час, поки бекенд готував відповідь. Далі діагноз читається майже сам: великий перший доданок — «холодна» резолюція або застарілий запис із довгим TTL; обрив на connect — порт закритий чи недосяжний; великий приріст на TLS при швидкій відповіді після нього — проблема в рукостисканні, а не в застосунку. Оцінюють і порядок дій: спершу назвати шар, далі перевірити оточення, у якому живе прогін (чужий посередник, зарізаний транспорт, відсутній VPN), і тільки після цього чіпати код тесту. І окремо варто памʼятати, що фаза Waiting у мережевій панелі показує затримку самого сервера, а не мережі, тож ні більша пропускна здатність, ні зʼєднань її не скоротять.
Три кейси про мережевий шар у щоденній роботі AQA: як за одну команду перетворити «падає по таймауту» на назву шару, як не наступити на пару address already in use плюс 127.0.0.1 vs 0.0.0.0 при піднятті сервера під тест, і як свідомо відтворити повільну мережу замість того, щоб чекати на неї. Скрізь — що саме дивитися і чому це значить те, що значить.
Кейс 1. Перетворюєш таймаут на назву шару
Прогін у CI раз на десять запусків падає на першому кроці, у застосунку жодної помилки, а локально все зелене. Питання «чи це баг продукту» ще навіть не поставлене — спершу треба знати, яка ланка зʼїла час: резолвінг імені, встановлення зʼєднання, TLS чи вже сам бекенд. curl розкладає це на чотири числа:
curl -w "dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n" \
-o /dev/null -s https://app.example.com/login
dns=0.031 connect=0.052 tls=0.108 ttfb=0.216
Що дивитися і чому:
- Числа накопичувальні, а не окремі. Кожне відлічується від старту запиту, тому
connectуже міститьdns, аtlsміститьconnect. Абсолютні значення тут майже нічого не кажуть — сенс мають різниці між сусідніми:connect − dnsце TCP-,tls − connectце TLS,ttfb − tlsце час, поки бекенд готував відповідь. - Роздутий перший доданок. Резолвінг — це або «холодний» кеш, або застарілий запис. Перевір
dig +noall +answer app.example.com: у рядку відповіді видно і реальну адресу, і TTL, тобто скільки ще житиме стара версія, якщо стенд нещодавно переїхав. Чекати доводиться саме цей строк — перезапуск його не скорочує. - Обрив або довга пауза на
connect. Порт закритий чи недосяжний, і бекенд тут ні до чого. Найдешевша перевірка —nc -zv app.example.com 443. - Великий приріст на TLS при швидкій відповіді після нього. Тобто
tls − connectвелике, аttfb − tlsмале: винне рукостискання, а не застосунок — після встановлення каналу сервер відповів миттєво. - Останній шар узагалі не мережевий. Те, що панель показує фазою
Waiting, — це самого сервера: час від отримання запиту до початку відповіді. Її не лікують ні більшою , ні зʼєднань, і плутати її з мережевою затримкою — класична помилка в баг-репорті.
Висновок, який рятує години: якщо запас у менший за холодний резолвінг плюс два рукостискання, тест зрізає ще живий запит. Це не дефект застосунку, а занижений таймаут.
Окрема гіпотеза для корпоративних мереж: якщо гальмують не всі імена, а саме «важкі» відповіді, варто перевірити, чи не заблоковано DNS-over-TCP. Наслідок описаний у джерелі прямим текстом — «resolution failure and/or application-level timeouts», тобто симптомом буде таймаут застосунку, а причина лежатиме в конфігурації мережі.
Кейс 2. address already in use і 127.0.0.1 vs 0.0.0.0 у CI
Більшість e2e-наборів піднімає власний сервер під прогін, і саме тут живуть дві пастки з одного класу.
Перша — порт уже зайнято, найчастіше попереднім прогоном, який не прибрав за собою:
Error: listen EADDRINUSE: address already in use 127.0.0.1:3000
Власника порту видно локально однією командою:
lsof -i :3000
Друга пастка тонша й дає симптом, схожий на мережевий збій. Сервер на 127.0.0.1:3000 слухає loopback — трафік до нього не виходить за межі машини, тож із сусіднього він недосяжний узагалі. Сервер на 0.0.0.0:3000 слухає всі інтерфейси й доступний ззовні. Плутанина між ними і є найчастішою причиною «у мене працює, а в CI ні».
У Playwright обидві лікуються конфігурацією webServer:
// playwright.config.ts (фрагмент)
export default defineConfig({
use: { baseURL: 'http://127.0.0.1:3000' },
webServer: {
command: 'npm run start -- --host 0.0.0.0 --port 3000',
url: 'http://127.0.0.1:3000/health',
reuseExistingServer: !process.env.CI,
timeout: 60_000,
},
});
Що дивитися і чому:
urlзамість фіксованої паузи. опитує здоровʼя, поки той не відповість, і лише тоді стартує тести. Це очікування за умовою: на повільному CI сервер може прогріватися довше, і набір це переживе, аsleepна дві секунди — ні.--host 0.0.0.0у контейнері. Привʼязка до всіх інтерфейсів, щоб ранер узагалі достукався. Локально127.0.0.1цілком достатньо, і зайвого відкриття назовні краще не робити.reuseExistingServer: !process.env.CI. Локально перевикористовуєш уже піднятий сервер і не ловишEADDRINUSEміж прогонами, а в CI щоразу піднімаєш чистий. Це прямий вияв ізоляції стану: набір або сам звільняє порт у teardown, або підбирає вільний динамічно, але ніколи не сподівається, що «саме розсмокчеться».- Чому в
baseURLстоїть адреса, а не імʼя. З резолвомlocalhostусе гаразд: імʼя чесно віддає обидві loopback-адреси. Вибирає між ними клієнт, і перевага в нього за IPv6 — тож коли сервер слухає лише IPv4, зʼєднання «незрозуміло чому» не встановлюється. Явна адреса знімає це питання цілком. - Локальна таблиця хостів — не гарантія. Якщо ти направляєш прогін на стенд через
hosts, памʼятай: специфікація називає її резервом або доповненням до DNS, а пріоритет лишає питанням конфігурації вузла. Тобто це хороший інструмент, але перевіряти, куди насправді пішов запит, усе одно доведеться.
Кейс 3. Свідомо відтворюєш повільну мережу
Гонки на таймінгах на швидкій машині розробника не відтворюються — вони просто не встигають статися. Щоб зловити їх навмисно, мережу треба або сповільнити, або замінити керованою підробкою. Обидва інструменти вбудовані у Playwright, і перехоплення відбувається всередині браузера — окремий для цього не потрібен.
test('UI не розсипається, коли API повільний, а частина бекенду падає', async ({ page }) => {
// штучна пауза перед фейковою відповіддю — імітуємо високу затримку
await page.route('**/api/user', async (route) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, name: 'Some User Name' }),
});
});
// рідкісний стан, якого на живому стенді не дочекаєшся
await page.route('**/api/orders', (route) => route.fulfill({ status: 500 }));
await page.goto('/dashboard');
await expect(page.getByText('Some User Name')).toBeVisible();
await expect(page.getByText('Не вдалося завантажити')).toBeVisible();
});
Що дивитися і чому:
- Пауза імітує затримку, а не низьку пропускну здатність.
setTimeoutпередfulfillвідтворює саме час подорожі — те, від чого страждають екрани з десятком дрібних : кожен платить свій час, і разом вони помітні. Для важких файлів картина інша: там тривалість визначає сукупність пропускної здатності й розміру, тож імітувати треба обсяг, а не паузу. - Три різні дії на одному перехопленні.
route.fulfillвіддає підроблену відповідь (як тут — успіх і500),route.abortобриває запит і показує, як UI переживає повністю мертвий ендпоінт, аroute.continueпропускає запит далі, дозволивши підмінити лише сам запит — його URL, метод, заголовки чи тіло. Вибір між ними і є вибором того, який саме збій ти відтворюєш. - Патерн маршруту звіряй із реальним запитом. Якщо
**/api/userне збігається зі шляхом, який робить фронтенд, перехоплення мовчки не спрацює, а тест буде зелений із хибної причини. Дешева перевірка — подивитися фактичний URL у мережевій панелі. - Очікування за умовою, а не за годинником.
toBeVisible()чекає появу елемента. Двосекундна пауза тут — контрольований подразник на стороні , а не в тесті; фіксованіwaitForTimeoutу самому тесті першими зрізають перевірку на повільнішому ранері. - (throttling) як другий інструмент. Нижчий клас зʼєднання в девтулзах емулюють трьома параметрами: скільки даних іде до клієнта, скільки від нього, і яку мінімальну затримку додати кожному запиту. Готові пресети не збігаються від браузера до браузера, а в Chrome ще й переїжджають від версії до версії — тому «повільна мережа» в баг-репорті без конкретних чисел майже нічого не означає. Надійніше завести власний профіль із зафіксованими значеннями. Поруч живе режим Offline: найдешевша перевірка того, чи повідомляє застосунок про втрату мережі взагалі.
- Що саме шукати на повільному профілі. По-перше, стани завантаження: чи взагалі показано індикатор і чи не блимає порожній екран замість нього. По-друге, гонки, яким на швидкому каналі бракує часу проявитися — найвідоміша з них дає подвійне надсилання, коли кнопку не блокують на час польоту запиту. Падіння тесту на такому профілі — не : тест на швидкому каналі просто ще не встиг упасти, бо очікування в ньому привʼязані до часу, а не до подій.
- І окремо — «а чи не стоїть щось між нами». Якщо поведінка відрізняється саме в офісній мережі, згадай: вузол, якого клієнт не обирав, на рівні протоколу невідрізненний від на шляху й може фільтрувати чи перенаправляти трафік без відома відправника. Це перевіряють конфігурацією мережі, а не ще одним перезапуском прогону. Для повного контролю над трафіком поза браузером той самий принцип дає mitmproxy: показати справжні запити, підмінити відповідь, зімітувати помилку сервера.
Адреси й порти
- Знаю різницю IPv4 (32 біти, чотири октети
0–255) vs IPv6 (128 біт, вісім шістнадцяткових груп) і памʼятаю, що::в адресі дозволено рівно один раз. - Можу пояснити різницю loopback (
127.0.0.1,::1) vs0.0.0.0при прослуховуванні — і чому саме вона дає «локально працює, а в CI ні». - Знаю пастку
localhost: імʼя чесно дає обидві loopback-адреси, вибирає між ними клієнт, і перевага в нього за IPv6 — тож сервер лише на IPv4 для нього мовчить, а спроби зʼєднання навмисно не паралельні (звідси плаваючі тайминги). - Можу прочитати CIDR (
/16— скільки старших біт закріплено за префіксом мережі), назвати три приватні діапазони (10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) і пояснити роль NAT. - Розумію різницю сокет (адреса + порт) vs зʼєднання (пара сокетів) і знаю, що локальний ефемерний порт видає операційна система — вона ж задає його реальний діапазон, а не таблиця IANA (
0–1023well-known,1024–49151registered,49152–65535dynamic). - Памʼятаю типові порти (
80,443,22,53,3306,5432,6379,27017,8080), причину, чому443можна не писати, а8080треба, і звідки беретьсяaddress already in useу CI разом зі способами цього уникнути.
DNS: механіка й кеш
- Можу назвати три складники DNS (простір імен із записами, сервери імен, резолвери), пояснити зону й авторитетність і памʼятаю, що сервер позначає у відповіді, звідки вона — з власних даних чи з кешу.
- Знаю типи записів:
A,AAAA,CNAME,NS,MX,TXT. - Можу описати ланцюг резолюції (stub-резолвер ОС → рекурсивний сервер → кореневі → TLD → авторитетний) і знаю, що stub сам ієрархію не обходить, а кореневі сервери кінцевої адреси не знають.
- Знаю, що рекурсія — сервіс
optional: серверfree to refuse, може обмежити коло клієнтів, а серед допустимих рекурсивних відповідей єA temporary error indication. Відрізняє рекурсивний режим те, що він ніколи не віддає відсилань. - Можу пояснити TTL і асиметричну рекомендацію джерела (
on the order of daysдля типового вузла; знижувати перед запланованою зміною й повертати після), а також те, що локальний кеш із протуханням даних — цеMUST, і кешувати можна й негативні відповіді.
Транспорт DNS і джерела імен
- Можу сказати, хто саме віддає перевагу датаграмам, а хто просто перелічує обидва транспорти, памʼятаю, що порт
53спільний для UDP і TCP, і знаю чинну модальність:MUST support both UDP and TCP transport, а TCP — не «варіант ретраю». - Можу описати truncated- (512 байтів → біт
TC→SHOULDповторити по TCP), знаю, що AXFR по TCP — вимога, а не «перехід за потреби», і що заблокований DNS-over-TCP дає «resolution failure and/or application-level timeouts». - Знаю, що файл
hosts— це резерв або доповнення до DNS, а пріоритет між ним і DNS джерело лишає питанням конфігурації вузла.
TCP, затримка, посередники
- Можу пояснити, чому звʼязок «домен ↔ IP» не один до одного (кілька
A-записів, віртуальний хостинг заHostабо:authority, CDN із найближчим вузлом) і чому похід за IP ламає перевірку сертифіката. - Можу назвати гарантії TCP (надійність через номери послідовності й повторну передачу, порядок через накопичувальні ACK, контроль потоку й перевантаження), описати SYN → SYN-ACK → ACK і пояснити, чому кроків саме три; знаю, що HTTP/3 — виняток на QUIC поверх UDP.
- Можу розвести (час подорожі, міряють як round-trip delay) і (обсяг за час) і пояснити, чому її зростання затримки не скорочує (
bandwidth × delay,long, fat network); не плутаю фазуReceiving(пропускна здатність і розмір файла) з фазоюWaiting(затримка самого сервера) і памʼятаю, чому перший запит платить більше за наступні (резолвінг + TCP + TLS) і навіщо зʼєднання тримають відкритим. - Знаю три форми : (обирає клієнт), /reverse proxy (назовні поводиться як origin-сервер, за ним живе балансування), (сліпий ретранслятор). Терміна
forward proxyв специфікації немає, аinterception proxy— це вузол, якого клієнт не обирав, і на рівні протоколу він невідрізненний від на шляху; звідси й читання кодів —502/504вказують на ланку за посередником, а503на сам сервер. - Можу дати канонічне означення VPN (відокремлена група користувачів, що спілкується «ніби в приватній мережі») і памʼятаю, що шифрування там — посилення, а не визначальна ознака.
- Можу простежити відкриття
https://app.example.com/loginпо шарах (резолвінг → TCP на443→ TLS → HTTP ізHost), розкласти час черезcurl -wі назвати інструменти перехоплення та (page.routeу Playwright, mitmproxy, профіль мережі в девтулзах).
Квіз
Перед стартом
- Питань: 15
- Поріг «зараховано»: ≥70% правильних відповідей.
- Результат впливає на прогрес; завалені питання підуть у чергу повторення.
- Квіз впливає на компліт теми: тема стає «пройдено», лише коли прочитано теорію І квіз складено на ≥70%.
Питання
Скільки біт займає адреса в IPv4 і в IPv6 і як їх записують?