Выдача нескольких запросов перед получением ответа

Мне сложно понять, как работает HTTP, когда несколько запросов отправляются параллельно (до получения ответа). Есть два случая:

1) С Connection: Keep-Alive.

В соответствии с спецификацией HTTP:

Клиент, поддерживающий постоянные соединения, МОЖЕТ "конвейерно" запросов (т.е. отправлять несколько запросов, не дожидаясь ответ). Сервер ДОЛЖЕН отправлять свои ответы на эти запросы в тот же порядок, в котором были получены запросы.

Этот способ представляется довольно сложным для реализации и поддержки. Сервер должен отслеживать порядок запросов и должен отвечать в правильном порядке. Не только это может быть нелегко реализовать, но есть производительность: быстрые запросы должны ждать обработки медленных запросов, если они были выпущены позже.

Также, если мы говорим о балансировщике нагрузки, тогда прокси должен отслеживать, какой запрос был отправлен на какой-либо сервер, поэтому, когда они вернутся, он может поставить их в очередь и ответить в порядке. Так почему бы не сделать этот путь в первую очередь? То есть более естественно и проще, что клиент ставит (например) ID заголовок, сервер обрабатывает запрос и отвечает тем же заголовком ID, чтобы клиент мог сопоставить запрос с ответом. Это намного проще реализовать и не создает проблем с запросами на очередность (клиент должен отслеживать порядок запросов, если это необходимо).

Итак, вопрос в том, какова причина указания конвейерной обработки в том виде, в каком она была указана?

2) Без Connection: Keep-Alive.

Я не мог найти информацию об этом случае. Скажем, что клиент выдает два запроса A и B. Без сохранения сервер закроет соединение после обработки запроса. Это, очевидно, вводит условие гонки. Так как же он должен себя вести? Должен ли он отказаться от второго запроса?

Ответ 1

1) С Keep-Alive:

В соответствии с этой статьей wikipedia (http://en.wikipedia.org/wiki/HTTP_pipelining) это противоположность: реализация на стороне сервера на самом деле очень проста. Я считаю, что это утверждение основано на предположении, что один поток используется для обработки всех запросов для одного соединения (что, безусловно, является общим случаем, когда этот механизм был разработан), и поэтому несколько запросов на одно и то же соединение обрабатываются последовательно этим потоком (и поскольку TCP гарантирует упорядоченную доставку, ответы естественно принимаются в том же порядке, в котором они обрабатываются). Сегодня это может быть иначе на неблокирующей реализации сервера.

2) Без Keep-alive:

Без поддержки, вы не связываете запросы, поэтому я не вижу условия гонки. У вас есть два отдельных соединения для запросов A и B, каждое соединение закрывается, когда запрос завершен.

Если клиент пытается запросить конвейер без сохранения работоспособности, я считаю, что применяется следующий раздел спецификации:

Клиенты, которые немедленно принимают постоянные соединения и конвейер после установления соединения ДОЛЖНЫ быть готовы повторить их если первая попытка конвейера не удалась. Если клиент делает это повторить попытку, он НЕ ДОЛЖЕН конвейер, пока не узнает, что соединение упорный. Клиенты ДОЛЖНЫ также быть готовы повторно отправить свои запросы, если сервер закрывает соединение, прежде чем отправлять все соответствующие ответы.

Моя интерпретация заключается в том, что сервер должен законно отказаться от второго запроса и отвечать только на один, так как ответы FIFO. Это клиент для повторной отправки второго запроса.

Имейте в виду: это в основном предположения на моей стороне, я надеюсь, что они имеют смысл для вас!