Після того, як ви освоїли net/rpc з попередньої статті (From net/rpc to gRPC in Go Applications), варто почати вивчення HTTP/2, який є основою протоколу gRPC.

Як працює HTTP/2 та як працювати з ним в Golang

Як працює HTTP/2 та як працювати з ним в Golang

Ця стаття більше зосереджена на теоретичній частині, тому попереджаю - тут багато тексту. Ми зосередимось на розумінні HTTP/2, а потім коротко розглянемо його налаштування в Go. Тож беріть каву, влаштовуйтесь зручніше, і давайте розбиратися.

Чому HTTP/2?

HTTP/2 - це значне оновлення порівняно з HTTP/1.1, і сьогодні він став фактично стандартом всюди. Якщо ви коли-небудь відкривали Chrome DevTools для перегляду мережевих запитів, ви, ймовірно, вже бачили з'єднання HTTP/2 в дії.

Перевірка з’єднань HTTP/2 за допомогою Chrome

Перевірка з’єднань HTTP/2 за допомогою Chrome

Але чому HTTP/2 такий важливий? Що не так з HTTP/1.1?

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

HTTP/1.1 Pipelining: послідовна обробка запитів

HTTP/1.1 Pipelining: послідовна обробка запитів

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

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

Блокування головного рядка в HTTP/1.1

Блокування головного рядка в HTTP/1.1

Ця проблема називається блокуванням Head-of-Line (HoL).

Щоб обійти це обмеження, HTTP/1.1 клієнти (як ваш браузер) почали відкривати кілька TCP-з'єднань з одним і тим же сервером, дозволяючи запитам проходити більш вільно та паралельно.

І хоча це працювало, це не було особливо ефективним:

"То HTTP/2 вирішує цю проблему?"

Так... ну, здебільшого.

HTTP/2 бере одне з'єднання і розділяє його на кілька незалежних потоків. Кожен потік має свій унікальний ідентифікатор, який називається ID потоку, і ці потоки можуть працювати паралельно. Така структура вирішує проблему блокування Head-of-Line (HoL) на рівні додатку (де працює HTTP). Якщо один потік затримується, це не зупиняє рух інших.