Конечно, гораздо лучше один раз открыть соединение Redis и попытаться использовать его как можно дольше.
Я подозреваю, что с помощью прилагаемой программы эталонный тест зависает, поскольку число свободных портов вэфемерный диапазон портов исчерпан.Каждый раз, когда новое соединение с Redis открывается и закрывается, соответствующий сокет проводит некоторое время в режиме TIME_WAIT (эту точку можно проверить с помощью команды netstat).Ядро не может перерабатывать их достаточно быстро.Когда их слишком много, дальнейшее клиентское соединение не может быть инициировано.
У вас также есть утечка памяти в программе: структура reqData выделяется для каждого запроса и никогда не освобождается.В get_cb отсутствует свободное место.
На самом деле существует 2 возможных источника сокетов TIME_WAIT: те, что используются для Redis, и те, которые открываются инструментом тестирования для подключения к серверу.Redis соединения должны быть учтены в программе.Инструмент для тестирования должен быть настроен на использование HTTP 1.1 и keepalived соединений.
Лично я предпочитаю использовать siege над ab для запуска такого типа теста.ab считается наивным инструментом для большинства людей, заинтересованных в тестировании HTTP-серверов.
На моем старом ПК с Linux первоначальная программа, работающая против осады в режиме тестирования с 50 поддерживающими соединениями, приводит к:
Transaction rate: 3412.44 trans/sec
Throughput: 0.02 MB/sec
Когда мы полностью удаляем вызов Redis, возвращая только фиктивный результат, мы получаем:
Transaction rate: 7417.17 trans/sec
Throughput: 0.04 MB/sec
Теперь давайте изменим программу, чтобы факторизовать соединение Redis и, естественно, извлечь выгоду из конвейеризации.Исходный код доступен здесь .Вот почему мы получаем:
Transaction rate: 7029.59 trans/sec
Throughput: 0.03 MB/sec
Другими словами, удаляя систематические события соединения / разъединения, мы можем достичь удвоенной пропускной способности.Производительность при вызове Redis не настолько низка, как при использовании вызова Redis.
Для дальнейшей оптимизации вы можете рассмотреть возможность использования доменного сокета unix между вашим сервером и Redis и / или динамически создавать пулвыделенные объекты для уменьшения потребления ЦП.
ОБНОВЛЕНИЕ:
Чтобы поэкспериментировать с сокетом домена unix, это просто: вам просто нужно активировать поддержку в самом Redis, обновив файл конфигурации:
# Specify the path for the unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
unixsocket /tmp/redis.sock
unixsocketperm 755
и затем замените функцию соединения:
c = redisAsyncConnect("0.0.0.0", 6379);
на:
c = redisAsyncConnectUnix("/tmp/redis.sock");
Примечание: здесь hiredis async хорошо выполняет работу по конвейеризации команд (при условии постоянного подключения), поэтому воздействие будет низким.