tdesc
[
"Почти всегда, при разговоре о производительности веб-сайта, мы говорим о времени ожидания пользователем какого-то события (\"First Meaningful Paint\" и тд). Мы часто обсуждаем оптимизации фронтенда и бэкенда. И это круто, но остается корень всех бед - ",
{
"type": "bold",
"text": "скорость света"
},
". Часто JavaScript разработчики упускают это проблему из виду ??\n\nМожет ли случится такое, что через 30 лет Интернет будет настолько быстрым, что сайт с сервера в Сан-Франциско будет моментально открываться в Киеве? Физики говорит, что нет. \n\nДопустим: \n1. Твой бекенд рендерит страницу (или формирует JSON) за 20мс.\n2. Не существует никакого WiFi, провайдеров, маршрутизации и тд. Есть просто оптоволоконный кабель, который одним концом вставлен в твой ноутбук, а вторым напрямую в сервер в Сан-Франциско. Растояние по прямой от Киева до Сан-Франциско - 9,848км (возьмем 10 тыс км для простоты счета). \n3. Скорость света в вакуме 300 тыс км в секунду, скорость света в оптоволокне будет ниже - 200 тыс км в секунду.\n\nЕсли мы посчитаем время, которое проведет наш запрос в пути, то мы получим 100 мс (10 тыс / 200 тыс * 2). Быстрее получить ответ не позволит скорость света. Добавляем время оработки запроса и мы получим 120мс - в 6 раз дольше, чем наш запрос обрабатывает наш бэкенд.\n\n",
{
"type": "pre",
"text": "========= Запрос к бэкенду ======\n50ms: Kyiv -------запрос-----> SF \n20ms: работа бэкенда \n50ms: Kyiv <------ответ------- SF\n\n",
"language": ""
},
"Хорошо, мы уже выяснили, что никогда не поиграем в CS:GO с ребятами с Сан-Франциско с пингом ниже 100м. Давайте дальше :)\n\nПеред тем как запросить данные с сервера мы должны установить сетевое соединение. Протокол HTTP работает поверх TCP, следовательно нам нужно TCP соединение с сервером. \n\nДля установки TCP соедения используется так называемое \"тройное рукопожатие\" (\"TCP 3-way handshake\") и теперь наш запрос выглядит:\n\n",
{
"type": "pre",
"text": "========= TCP соединение ========\n50ms: Kyiv -------syn--------> SF\n50ms: Kyiv <------syn/ack----- SF\n50ms: Kyiv -------ack--------> SF\n========= Запрос к бэкенду ======\n Kyiv -------запрос-----> SF \n20ms: работа бэкенда \n50ms: Kyiv <------ответ------- SF\n\n",
"language": ""
},
"Мы не тратим дополнительные 50ms после TCP хендшейка, поскольку мы можем сразу начать отправлять запрос после отправки ack, нам не нужно ждать ответ от сервера. Сервер, как примет ack, посчитает соединение открытым и сразу начнет обрабатывать наш запрос.\n\nТо есть ответ пользователь получит через 220ms, в 11 раз дольше, чем отрабатывал наш бэкенд.\n\nНо мы используем HTTPS и нам нужно SSL/TLS соединение и оно устанавливается поверх TCP, и у него есть свой механизм рукопожатия для обменя ключами шифрования, и это нужно сделать до момента, как мы отправим наш запрос на сервер.\n\nНаша схема превращается в:\n \n",
{
"type": "pre",
"text": "========= TCP соединение ========\n50ms: Kyiv -------syn--------> SF\n50ms: Kyiv <------syn/ack----- SF\n50ms: Kyiv -------ack--------> SF\n========= TLS соединение ========\n Kyiv ---представление--> SF\n50ms: Kyiv <--сертификаты----- SF\n50ms: Kyiv ---обмен ключами--> SF\n50ms: Kyiv <--обмен ключами--- SF\n========= Запрос к бэкенду ======\n50ms: Kyiv -------запрос-----> SF\n20ms: работа бэкенда \n50ms: Kyiv <------ответ------- SF\n\n",
"language": ""
},
"То есть в условиях, которые не могут даже существовать, когда пользователь имеет оптоволоконный кабель длинной в 10тыс км от своего ноутбука к серверу, он получит ответ через 420мс, в 21 раз дольше чем отрабатывает наш бэкенд. Это без учета того, что нам нужно еще вначале сбегать к DNS, чтобы получить ip-адрес сервера.\n\nЕсли мы разрабатываем веб-приложения (не важно фронтенд или бекэнд), то обязаны понимать азы работы веба. \n\nПродолжение следует..."
]