Клиент и сервер: кто спрашивает и кто отвечает
Настоящая система — это как минимум две программы, которые разговаривают друг с другом: одна показывает, другая решает и запоминает. Этот урок о таком разделении.
В уроке os:1 вы следили за одной программой на одной машине: она получает кусочек процессорного времени, ей принадлежат некоторые страницы памяти, её можно поставить на паузу и продолжить. В уроке networking:1 вы следили за одним запросом через всю планету: он находит хост, открывает TCP-соединение и возвращается ответом. Архитектура начинается там, где эти двое встречаются. Как только ваша программа начинает общаться с программой на другой машине, вы уже пишете не одну программу. Вы проводите границу между двумя программами, и почти каждое следующее решение зависит от того, где вы эту границу проведёте.
Клиент — это программа, которая начинает разговор. У неё есть экран, пользователь и полное незнание, каким будет правильный ответ. Сервер — это программа, которая ждёт разговоров, хранит данные и решает, что делать с каждым запросом. Это всё определение, и в нём нет ни слова про размер: телефон может быть клиентом, но тот же телефон может запускать и сервер; ноутбук становится сервером, пока раздаёт игру друзьям. Сервером что-то делает то, что он отвечает на запросы, которые начал не он, и запросы других людей приходят независимо от того, готов он или нет.
GET /orders/77 HTTP/1.1
Host: shop.example
Authorization: Bearer eyJhbGciOi...
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 77, "total": 12.90, "status": "paid"}Вот правило, которое решает почти всё: клиент тебе не принадлежит. Он работает на чужой машине, в сети, которую ты не контролируешь, а его код можно прочитать и изменить в инструментах разработчика браузера секунд за десять. Поэтому сервер никогда не должен верить клиенту. «Я пользователь 5» — это заявление, а не факт. Сервер обязан проверить его по чему-то, что клиент не может подделать, обычно по токену, подписанному на сервере. Цена, присланная из браузера, — это лишь предложение, которое надо пересчитать по базе данных, а не число, которое можно выставлять к оплате.
Сервер, который ничего не хранит между запросами, называется сервером без состояния. Он получает запрос, выдаёт ответ и забывает, что запрос вообще был. Звучит как ухудшение, но именно поэтому один сервер может обслуживать миллион человек: с тобой не связано ничего на этой конкретной машине, поэтому твой следующий запрос может уйти на любую из двадцати одинаковых. Всё, что должно сохраниться между запросами — корзина покупок, вход в аккаунт, — хранится где-то в общем месте: в базе данных, в кэше или внутри подписанного токена, который клиент носит с собой. Это та же идея, что была с HTTP в уроке про сети:1, только теперь это выбор архитектуры.
Практика
На странице магазина есть поле скидки: браузер его заполняет и отправляет на сервер. Где на самом деле нужно проверять скидку?
Подсказки
- Спроси, кому выгодна эта проверка, а не у кого экран красивее.
- Всё, что доехало до машины пользователя, можно там отредактировать, прежде чем оно вернётся обратно.
12 XP
Соедините каждую сторону разговора с тем, за что она на самом деле отвечает.
Подсказки
- Одна из двух сторон должна знать ответ ещё до того, как придёт запрос.
- Кэш ничего не знает: он только повторяет ответ, сохранённый раньше.
14 XP
Расставьте шаги одного запроса в том порядке, в котором они происходят на самом деле.
Подсказки
- Начни с запроса, который уходит из браузера, а закончи пикселем, который меняет цвет.
- Каждый шаг происходит ровно на одной стороне: клиент, потом сервер, потом снова клиент.
16 XP