Много букв, мало кода)
Понадобилось срочно написать xml rpc server, выбор пал на питон из-за казавшейся простоты, а не писать все как обычно на с++)
За пару дней код был готов и показывал отличные результаты на тестовых серверах, выпустил на продакшн и как это часто бывает, пошли проблемы.
Суть проблемы. При выполнении данного ниже кода, каждый клиент, при подключении, работает в своем потоке, в “домашних/тестовых” условиях все работает отлично, но на просторах интернета на рабочем сервере, где кто-то сканирует порты, обрывается связь у клиента в самый неподходящий момент или по какой-либо другой не известной и не воспроизводимой причине, рожденный под это соединение поток не хочет завершаться и висит. Сколько не старался но не смог воспроизвести что бы подобное повторилось на тестовых серверах. Запустили на втором рабочем сервере - ситуация повторилась. Сами понимаете на рабочем сервере многое себе не позволишь, но нужно хотя бы направление в котором копать или еще лучше если это баян, решение которого знают все кроме меня)
Ниже сильно упрощенный псевдо код, дающий представление, все лишнее - перепроверено и убрано как не влияющее на ситуацию.
Выяснилось наверняка только одно, запрос порождающий повисший поток до вызова функции getMyData не доходит. Более того, не доходит до выполнения _dispatch(self, method, params).
Но выполняются shutdown_request, close_request. Так же было замечено что подобный запрос идет часто в одну и туже секунду с другим запросом, который обрабатывается в дальнейшем нормально.
python 3.5
Рабочие сервера работают на Ubuntu 16
Кол-во запросов - 20000-25000 в сутки на сервер (обрабатывается все в отдельных процессах=кол проц сервера)
Планируется десятикратное увеличение при полном запуске
За сутки таких мертворожденных потоков доходит до 20.
А теперь вопрос! В каком месте может поток уходить в бесконечный цикл и висит? И как это лечить, если такое место будет не найдено?)
class RequestHandler(SimpleXMLRPCRequestHandler): rpc_paths = ('/RPC2',) class ThreadedRPCServer(ThreadingMixIn, SimpleXMLRPCServer): pass def getMyData(myData): print("In getMyData") #обрабатываю данные return resData if __name__ == "__main__": server = ThreadedRPCServer(("", 9111), requestHandler=RequestHandler, allow_none=True) server.logRequests = True server.request_queue_size = 40 server.register_introspection_functions() server.register_function(getMyData, 'getMyData') try: server.serve_forever() except KeyboardInterrupt: print("\nKeyboard interrupt received, exiting.") exit(0)