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 сразу его перезапустить. Я-же ведь правильно понимаю логику, что если в программе остаются только потоки-демоны, то она прекращает свою работу?
  • Вопрос задан
  • 148 просмотров
Решения вопроса 1
tumbler
@tumbler Куратор тега Python
бекенд-разработчик на python
Правильно понимаете, демон-потоки завершаются вместе с основным потоком. Соединение сбрасывается, потому что долго не используется (это настройка серверов ВК)
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы