kshnkvn
@kshnkvn
yay ✌️ t.me/kshnkvn

Почему сбрасывается соединение с API?

На старте запускаются два потока:
Thread(target=self.input_event).start()
Thread(target=self.read_input).start()

Первый - читает поток от ВК и сохраняет некоторые данные при входящих сообщениях:
Код первого потока
for event in self.long_poll.listen():
                if event.type == VkBotEventType.MESSAGE_NEW:
                    if len(event.object.attachments) > 0:
                        user_id = event.object.from_id
                        for pos in range(len(event.object.attachments[0].get('photo').get('sizes'))):
                            if event.object.attachments[0].get('photo').get('sizes')[pos].get('type', None) == 'w':
                                img_source = event.object.attachments[0].get('photo').get('sizes')[pos].get('url')
                            elif event.object.attachments[0].get('photo').get('sizes')[pos].get('type', None) is 'z':
                                img_source = event.object.attachments[0].get('photo').get('sizes')[pos].get('url')
                        split_url = img_source
                        split_url = split_url.split("/")[-1:][0].split(".")[0]
                        attachments = {'user_id': user_id, 'img_source': img_source, 'split_url': split_url}
                        logging.info(self.send_message(user_id, 'Отлично! Что вы хотите сделать с изображением?'))
                        USER_ATTACHMENTS.append(attachments)
                        logging.info('Received image: ' + str(attachments))
                    else:
                        user_id = event.object.from_id
                        username = self.vk_api.users.get(user_id=user_id)[0]['first_name']
                        text = event.object.text
                        data = {'user_id': user_id, 'username': username, 'text': text}
                        INPUT_EVENTS.append(data)
                        logging.info('Received message: ' + str(data))

Второй поток ищет в этих данных ключевые слова и, в случае нахождения он создает для пользователя новый поток с нужной функцией:
Код второго потока
for main_loop in range(len(INPUT_EVENTS)):
                    if COMMANDS.get(INPUT_EVENTS[main_loop].get('text', None).lower(), None) is not None:
                        if COMMANDS.get(INPUT_EVENTS[main_loop].get('text', None).lower(), None) == 1:
                            index_list = main_loop
                            user_id = INPUT_EVENTS[main_loop].get('user_id', None)
                            Thread(target=self.command_start, args=(index_list, user_id)).start()
                            del INPUT_EVENTS[main_loop]

Логирование инициализировано:
logging.basicConfig(filename="log.log",
                    level=logging.DEBUG,
                    format="%(asctime)s:%(levelname)s:%(message)s")

В логах, помимо входящих сообщений и выполненных команд все время отображается примерно следующее:
Лог
08:28:53,954:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19492&wait=25 HTTP/1.1" 200 381
08:28:53,956:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19492&wait=25 HTTP/1.1" 200 381
08:29:18,966:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 29
08:29:18,969:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 29
08:29:18,972:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 29
08:29:18,974:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 29
08:29:38,768:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 148
08:29:38,769:DEBUG:https://lp.vk.com:443 "GET /wh119339221?act=a_check&key=KEY&ts=19494&wait=25 HTTP/1.1" 200 148

Очень часто (бывает раз в 15 минут, а бывает и каждые несколько минут) происходит следующее:
08:28:49,852:DEBUG:Resetting dropped connection: lp.vk.com

Практически перед каждым действием пользователя в логах:
08:24:27,128:DEBUG:Starting new HTTPS connection (1): pp.userapi.com

Иногда бот просто прекращает получать от ВК какие либо-сообщения, т.е. в логах абсолютно такие-же HTTP запросы, но при этом если писать боту, то он просто не принимает эти сообщения, т.е. строк типа logging.info('Received message: ' + str(data)) нет вообще. При этом никаких ошибок нет вообще. По всему коду утыканы logging.info, практически все функции обернуты блоком tr-except, к примеру вот блок, внутри которого работает первый поток:
try:
            ...
        except requests.exceptions.Timeout as e:
            logging.error(e)
            os.kill(os.getpid(), signal.SIGINT)
        except requests.exceptions.TooManyRedirects as e:
            logging.error(e)
            os.kill(os.getpid(), signal.SIGINT)
        except requests.exceptions.RequestException as e:
            Thread(target=self.read_input).join()
            logging.error(e)
            os.kill(os.getpid(), signal.SIGINT)

Но все-равно, бот просто "зависает" и ничего не делает, хотя в логах ни единой ошибки.
Так-же ночью был наплыв пользователей и в логах творилось примерно следующее:
2019-05-09 00:20:38,701:WARNING:Connection pool is full, discarding connection: lp.vk.com
2019-05-09 00:20:38,717:DEBUG:Starting new HTTPS connection (242): lp.vk.com

Хотя это было единожды и не думаю, что связано с "зависаниями" бота.
Сам бот работает как сервис через systemd, и в моменты "зависания" systemctl status говорит, что с сервисом все хорошо.
Перерыл уже все, что можно было, может у кого тут какие-то идеи найдутся.

UPD.
В рабочем состоянии systemctl status отображает 3 процесса, но иногда обращал внимание, что их 2, по всей видимости как раз когда отваливается поток input_event. Есть идея сделать все создаваемые потоки демонами, кроме input_event, тогда, по идеи, если этот поток отвалится приложение должно прекратить свою работу, а systemd сразу его перезапустить. Я-же ведь правильно понимаю логику, что если в программе остаются только потоки-демоны, то она прекращает свою работу?
  • Вопрос задан
  • 142 просмотра
Решения вопроса 1
tumbler
@tumbler Куратор тега Python
бекенд-разработчик на python
Правильно понимаете, демон-потоки завершаются вместе с основным потоком. Соединение сбрасывается, потому что долго не используется (это настройка серверов ВК)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы