* С keep-alive, с pipelining: новый запрос может быть послан по
уже-существующему соединению. Побочный эффект: несколько запросов
можно послать в одном пакете - но не обязательно.
Утрированный пример.
На бэкенде апач с MaxClients 2
Фронтен держит две Keep-Alive коннекции до бэкенда.
На фронтенд приоходит почти одновременно три запроса A, B, C
Фронтент с A послает через одну коннекцию, а два запроса B и C
pipelin-ит через вторую коннекцию.
A запрос окзался "легким" и быстро освободил первый процесс.
Запрос B оказался "тяжелыми" и надолого занял 2-й процесс.
В результате запрос C ждет пока до него доберятся занятый второй
процесс. хотя 1-й в это время простаивает и мог бы его обработать,
если бы фонтенд не использовал pipelining.
Когда бэкенд имеет запас производительности то заметную часть времени
процессы апача спят в ожидании accept()
в этом случае отпрака двух запросов одному процессу через pipelining
только увеличит время ответа. Второй запрос лучше послать одному из
незанятых процессов.
Если же все процессы заняты (вообще это говорит о том, что сервер
перегружен), то выгоднее не послыать этот запрос через pipelining
(поскольку мы не знаем какому процессу его лучше послать), а немного
подождать и послать запрос тому, кто первый освободится.
Когда фронтенд для подключения к бэкенду не использует Keep-Alive то
падание запроса к первому освободившемуся процессу произойдет
атоматически (он сделает accept и заберет коннекцию из listen queue).
В случае если фонтенд использует Keep-Alive он сам должен
организровать очередь запросов и отпрвить запрос из очереди тому
процессу, который перым пришлет ответ и таким образом сообщит, что он
освободился.
А разве сервер обязан ждать пока запрос B обработается до того как
обработать C?