Фатальная ошибка Asyncio на транспорте SSL - Индекс DequeError Deque вне диапазона - PullRequest
0 голосов
/ 10 июня 2019

Я продолжаю сталкиваться с нижеуказанной ошибкой и не могу понять, как ее исправить, или это ошибка в asyncio, о которой мне нужно сообщить. Моя программа работает нормально, она в основном такая же, как в примере docs , но она может отправлять множество сообщений со скоростью до 20 в секунду нескольким клиентам при небольшом количестве обновлений, она работает нормально, но когда число из-за увеличения записи я сталкиваюсь с этой ошибкой.

Я использую create_server из asyncio, чтобы сервер прослушивал новых клиентов, и я считаю, что это создает новое соединение для каждого соединения. Не все клиенты останавливают только одну остановку клиентов, а остальные продолжают работать, обычно это последний подключенный клиент, но не всегда. Я поиграл с файлом asyncio/sslproto.py, удалив ссылку на [0] и заменив их на popleft, из-за чего я получил не очень полезную ошибку SSL: BAD_LENGTH, которая у меня была раньше, и использование asyncio должно было исправить.

Когда я зарегистрировал значение self._write_backlog, он вернул деку, как и ожидалось, и до появления ошибки в ней явно были данные, и я считаю, что self._write_backlog[0] должен вернуть самый левый элемент в деке, который, как представляется, равен одному.

Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f267462e780>
transport: <_SelectorSocketTransport fd=38 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
    File "/usr/local/lib/python3.7/asyncio/sslproto.py", line 689, in 
    _process_write_backlog
  del self._write_backlog[0]
IndexError: deque index out of range

При дальнейшем исследовании та же ошибка, по-видимому, также возникает в другой точке кода, но это та же ошибка, что и при попытке получить доступ к пустой деке.

Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f45f802ec88>
transport: <_SelectorSocketTransport fd=29 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
    File "/usr/local/lib/python3.7/asyncio/sslproto.py", line 664, in _process_write_backlog
    data, offset = self._write_backlog[0]
IndexError: deque index out of range

EDIT

Версия python, на которой я работаю, - 3.7.1, но я также пробовал 3.7.3, которая выдает ту же ошибку.

UPDATE

Считается, что эта проблема вызвана несовместимостью между asyncio и OpenSSL https://bugs.python.org/issue37226

ОБНОВЛЕНИЕ 2

Минимальный пример доступен на GitHub

1 Ответ

0 голосов
/ 22 июля 2019

Проблема здесь связана с системными ресурсами, когда вы подключаете много клиентов, это может привести к исчерпанию ЦП или памяти, что приводит к этой ошибке при сбое записи.

Решение состоит в том, чтобы реализовать управление потоком дляограничьте объем данных, отправляемых за один раз, и остановите истощение ресурсов. В следующей статье article приведен хороший пример простого управления потоком данных, который блокирует, пока старые данные удаляются, а затем возобновляет работу с использованием меток верхнего и нижнего уровня.Когда данные превышают верхнюю отметку, это вызывает pause_writing, а затем, когда размер данных уменьшается ниже, чем возобновляется запись низкой отметки, это может вызвать заметное замедление в зависимости от нагрузки.

Как альтернатива добавлению вашей собственнойуправление потоком данных по протоколу примитивы asyncio Streams предлагают простой способ записи и чтения данных, который включает управление потоком по умолчанию, но для меня это усложнило реализацию, поэтому я решил включить свой собственный на уровне протокола, как показано в связанной статье.

...