Многопоточное использование ЦП сервера сокетов Python выходит из-под контроля - PullRequest
2 голосов
/ 11 сентября 2011

Моя ситуация:

У меня есть сервер Python, который выполняет следующие действия:

Прослушивает порт 500 (по соображениям брандмауэра), и каждый раз, когда он получает соединение, порождает поток для обработки соединения. Каждый запущенный поток будет отвечать на входные данные клиента несколькими методами, которые в основном взаимодействуют с базой данных (на самом деле я использую Django ORM, так как мое серверное приложение связано с веб-сайтом Django).

Я бы хотел использовать select в какой-то момент (и, в конечном итоге, Twisted), но сейчас я не могу, так что мне придется с этим согласиться.


Моя проблема:

По какой-то причине я не могу понять, что загрузка ЦП сервера иногда выходит из-под контроля и достигает 200% использования ЦП (мы работаем на двухъядерном процессоре), что делает его довольно трудным для ssh чтобы остановить это.

Что я не понимаю, так это то, что это обычно не происходит во время работы (если у меня подключен один или несколько клиентов, загрузка ЦП остается очень низкой), но как только все клиенты отключены, мой Сервер загружается до 200% загрузки процессора.

Это привело меня к мысли, что проблема не в рабочих потоках (если бы они не умирали должным образом, я бы скорее ожидал значительного использования ОЗУ, чем в ЦП), а в методе приема сервера.

До сих пор я использовал этот код:

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((host,port))
s.listen(5)
logger.warning('Started - listening on {0}:{1}'.format(host, port))

while True:
    (newsocket, clientaddr) = s.accept() 
    logger.info('Received connection from {0}:{1}'.format(clientaddr[0], clientaddr[1]))
    WorkerThread(newsocket, clientaddr, timeout).start()

Я не могу понять, что здесь может пойти не так, но я подумал, что, возможно, мне следует использовать следующий синтаксис:

while True:
    (newsocket, clientaddr) = s.accept() 
    logger.info('Received connection from {0}:{1}'.format(clientaddr[0], clientaddr[1]))
    wk = WorkerThread(newsocket, clientaddr, timeout)
    wk.start()

Я видел это написанное намного чаще, чем то, что я делал до сих пор.

Кто-нибудь из вас знает, может ли это вызвать такую ​​проблему, как та, которую я описываю?

Заранее спасибо,

...