проблема
Я использую другую программу, потому что я не хочу, чтобы обработка происходила в цикле http запрос-ответ.
Это распространенная ошибка (и, следовательно, ловушка). Строка рассуждений кажется разумной: вы пытаетесь обрабатывать запросы «где-то еще», пытаясь
обрабатывать входящие HTTP-запросы как можно быстрее.
Проблема в том, что это "где-то еще" - это еще какой-то код, который
запускается одновременно с остальной частью вашего оттока обработки запросов.
Следовательно, если этот код работает на медленнее , чем скорость входящих запросов,
ваши рабочие программы будут накапливаться, по существу, истощая один или
больше ресурсов. Что именно - зависит от фактической обработки:
если он связан с процессором, это создаст естественную конкуренцию для процессора
между всеми этими GOMAXPROCS
аппаратными потоками исполнения;
если он связан с сетевым вводом-выводом, он создаст нагрузку на Scheruler времени выполнения Go, который должен разделить доступные кванты исполнения, которые он имеет
на руках между всеми этими горутинами, которых хотели казнить;
если он связан с дисковым вводом / выводом или другими системными вызовами, у вас будет
создание потоков ОС, и так далее, и так далее ...
По сути, вы в очереди рабочие единицы , преобразованные из
входящие HTTP-запросы, но очереди не устраняют перегрузку.
Они могут быть использованы для поглощения коротких пиков перегрузки,
но это работает только тогда, когда такие пики "окружены" периодами
нагрузки, по крайней мере, немного ниже максимальной емкости, обеспечиваемой вашим
система.
То, что вы в очереди, прямо не видно в вашем случае, но это
там, и это демонстрируется нажатием вашей системы мимо ее естественного
емкость - ваша «очередь» начинает расти бесконечно.
Пожалуйста, прочитайте это классическое эссе внимательно, чтобы понять, почему ваш подход не идет
работать в реалистичных производственных условиях.
Обратите особое внимание на фотографии кухонных раковин.
Что с этим делать?
К сожалению, почти невозможно дать ваше простое решение.
так как мы не работаем с вашим кодом в ваших настройках с вашей рабочей нагрузкой.
Тем не менее, вот несколько направлений для изучения.
В самом широком масштабе, попробуйте посмотреть, есть ли у вас легко
заметное узкое место в вашей системе, которое вы в настоящее время не видите.
Например, если все эти параллельные рабочие программы в конечном итоге
общаться с экземпляром RDBM, его дисковый ввод / вывод может довольно легко serialize
все те goroutines, которые будут просто ждать своей очереди, чтобы иметь
их данные приняты.
Узкое место может быть проще - скажем, в каждой рабочей программы
вы небрежно выполняете какую-то длительную операцию, удерживая блокировку
утверждается всеми этими горутинами;
это, очевидно, сериализует их всех.
Следующим шагом будет на самом деле измерение (я имею в виду, написав тест)
сколько времени требуется одному работнику, чтобы завершить свою единицу работы.
Затем вам нужно измерить, как меняется это число при увеличении
фактор параллелизма.
После сбора этих данных вы сможете сделать
обоснованные прогнозы о том, как реалистично оценит вашу систему
умеет обрабатывать запросы.
Следующий шаг - продумать стратегию создания вашей системы.
выполнить эти рассчитанные ожидания. Обычно это означает ограничение скорости
входящих запросов. Существуют различные подходы для достижения этой цели.
Посмотрите на golang.org/x/time/rate
для ограничителя скорости на основе времени, но можно начать с более низких технологий
подходы, такие как использование буферизованного канала в качестве счетного семафора.
Запросы, которые могут превысить ваши возможности, могут быть отклонены
(обычно с кодом состояния HTTP 429, см. this ).
Вы могли бы также рассмотреть возможность их краткой очереди, но я бы попробовал это только
служить вишней на пироге, то есть, когда у вас есть отдых
разобрался полностью.
Вопрос о том, что делать с отклоненными запросами, зависит от вашего
установка. TКак правило, вы пытаетесь «масштабироваться горизонтально», развертывая более одной службы для обработки ваших запросов и обучения ваших клиентов переключению доступных служб.(Я бы подчеркнул, что это означает несколько независимых сервисов - если все они совместно используют какой-то целевой приемник, который собирает их данные, они могут быть ограничены конечной емкостью этого приемника, и добавление большего количества систем не принесет выгодывам что угодно.)
Позвольте мне повторить, что у общей проблемы нет волшебных решений: если ваша полная система (с помощью этой службы HTTP, которую вы пишете, является лишь ее внешним интерфейсом, шлюзом, частью), способна толькообрабатывать N
RPS нагрузки, никакой разброс go processRequest()
не заставит его обрабатывать запросы в более высоком темпе.Простое параллелизмное предложение Go - это не серебряная пуля , а пулемет.