В HTTP/2 мультиплексирование устроено за счёт стримов и фреймов. Фрейм - фиксированный заголовок из 9 октетов (24 бита длина, 8 бит тип, 8 бит флаги, 1 бит зарезервирован и 31 бит идентификатор стрима). Каждый стрим - это ровно один запрос и один ответ (за исключением стримов, инициированных сервером - которые PUSH_PROMISE). Когда мы хотим сделать запрос, мы просто шлём заголовки на стрим, ид которого ранее не использовался, неявно переводя его из состояния idle в reserved. Как только ответ полностью передан, стрим считается closed и больше не может быть заново использован.
Стримы, инициированные клиентом, обязаны быть нечётными, а инициированные сервером - чётными. Таким образом, пространство идентификаторов для запросов составляет 2^31 / 2 = 30 бит, миллиард с копейками. Когда истощается, следует открыть новое подключение.
(PUSH_PROMISE это, кстати, обещание отправить клиенту по указанному стриму ответ без предварительного запроса. По-умолчанию фича, правда, отключена, и клиент также может её со своей стороны отключить, и тогда сервер не имеет права её использовать.)
Новый запрос может быть отправлен на стрим, чей идентификатор перескакивает через сразу несколько ранее неиспользованных. Тогда все эти стримы автоматически считаются закрытыми и тоже использоваться больше не могут.
Таким образом, мы имеем строго растущие идентификаторы стримов. Обрабатывать их следует конкурентно, поэтому на каждый выделяется своя горутина.
А теперь проблема: имея динамическое расстояние между двумя активными стримами с наибольшим и наименьшим идентификаторами (т.е. разница между идентификаторами самого старого и самого нового активно обрабатываемого запросов), какая ассоциативная структура данных покажет себя эффективнее всего для соотношения стрима к обрабатывающей его горутине?
Хэшмапа как стартовая точка, но я пока не пробовал и не сильно уверен в её эффективности по памяти. По скорости, в принципе, должна быть около-оптимальной.
Post #600
150
- 👍 5
- ❤ 1