Tinkoff / invest-openapi-csharp-sdk

Apache License 2.0
100 stars 33 forks source link

Постоянные дисконекты streaming подключения #94

Closed Dazlonar closed 2 years ago

Dazlonar commented 2 years ago

Столкнулся с проблемой, что при любой подписке, неважно насколько инструментов, неважно в какое время, даже ночью, когда нет торгов. Рвется сокет соединение каждые 2-3 минуты с таким эксепшином:

System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SslStream'.
   at System.Net.Security.SslState.CheckThrow(Boolean authSuccessCheck, Boolean shutdownCheck)
   at System.Net.Security.SslState.get_SecureStream()
   at System.Net.TlsStream.EndRead(IAsyncResult asyncResult)
   at System.Net.PooledStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Net.WebSockets.WebSocketConnectionStream.<ReadAsync>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Net.WebSockets.WebSocketBase.WebSocketOperation.<Process>d__19.MoveNext()
   at System.Net.WebSockets.WebSocketBase.WebSocketOperation.<Process>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Net.WebSockets.WebSocketBase.<ReceiveAsyncCore>d__45.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Tinkoff.Trading.OpenApi.Network.Connection`1.<<EnsureWebSocketConnectionAsync>b__25_0>d.MoveNext()

Понимая что проблема скорей всего не в сдк, я писал в поддержку, спустя месяц ожиданий меня отфутболили с тем что якобы проблема с моим интернетом, но я проверял на 3х разных компьютерах, на 3х разных интернет провайдерах и результат везде одинаков, разрыв спустя пару минут, даже на сандбоксе. Проблема воспроизводится в 100% случаях на текущий момент, я уже не знаю куда писать что бы проблемой занялись, возможно что-то получится со стороны СДК, по крайней мере подтвердить что проблема не только у меня.

rus-art commented 2 years ago

Думаю, можно дописать на такие случаи reconnect в sdk

Dazlonar commented 2 years ago

Реконнект написать не проблема, проблема в том что за время дисконекта можно пропустить часть данных и не успеть отправить поручение вовремя. В алгоритмическом трейдинге люди сражаются за каждую нано секунду, размещают свои сервера в дата центрах биржи, меряют кабель линейкой до ядра биржи что бы все были в равных условиях. Понятно что Oepn Api не сможет посоревноваться по скорости работы со спонсируемым подключением к бирже, но жить с дисконектами каждые 2 минуты, тоже кажется не очень.

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

Возможно на серваке есть какая-то прослойка или балансер, которая рвет коннекты, если это было сделано намеренно в целях "производительности", то хочется услышать честный ответ, а если это проблема то хочется что бы ее починили.

Возможно стоит перевести задачу в общую репу, если кто-то подтвердит что тоже имеет такую проблему. Воспроизвести можно просто подписавшись на что угодно(свечи, инструмент инфо, стакан), любого инструмента, добавить коллбек для context.WebSocketException и подождать пару минут, когда прилетит эксепшин, стабильно 2-3 минуты и дисконнект. Повторять можно в любое время дня и ночи, все как по расписанию.

StenSmith777 commented 2 years ago

У меня такая же проблема. 2-3 минуты и разрывает соединение, реконнект есть, но и он через какое-то время перестаёт работать.

21.07.2021 22:25:24--Ошибка WEB-сокета 21.07.2021 22:25:24--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:25:24--Рестарт WEB-сокета 21.07.2021 22:29:06--Ошибка WEB-сокета 21.07.2021 22:29:06--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:29:06--Рестарт WEB-сокета 21.07.2021 22:30:46--Ошибка WEB-сокета 21.07.2021 22:30:46--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:30:46--Рестарт WEB-сокета 21.07.2021 22:32:27--Ошибка WEB-сокета 21.07.2021 22:32:27--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:32:27--Рестарт WEB-сокета 21.07.2021 22:34:07--Ошибка WEB-сокета 21.07.2021 22:34:07--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:34:07--Рестарт WEB-сокета 21.07.2021 22:35:47--Ошибка WEB-сокета 21.07.2021 22:35:47--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:35:47--Рестарт WEB-сокета 21.07.2021 22:37:28--Ошибка WEB-сокета 21.07.2021 22:37:28--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:37:28--Рестарт WEB-сокета 21.07.2021 22:39:08--Ошибка WEB-сокета 21.07.2021 22:39:08--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:39:08--Рестарт WEB-сокета 21.07.2021 22:40:49--Ошибка WEB-сокета 21.07.2021 22:40:49--Удаленная сторона закрыла подключение WebSocket, не выполнив подтверждение закрытия. 21.07.2021 22:40:49--Рестарт WEB-сокета

NoviProg commented 2 years ago

Возможно проблема заключается в таймауте (но это не точно :)). Насколько мне известно на стороне OpenApi стоит Nginx и скорее всего он настроен как прокси WebSocket https://nginx.org/ru/docs/http/websocket.html. И имеет таймаут:

_По умолчанию соединение будет закрыто, если с проксируемого сервера данные не передавались в течение 60 секунд. Этот таймаут можно увеличить при помощи директивы proxy_readtimeout. Кроме того, на проксируемом сервере можно настроить периодическую отправку WebSocket ping-фреймов для сброса таймаута и проверки работоспособности соединения.

Из этого следует, что если OpenApi не передает данные в течении указанного таймаута (в связи с их отсутствием или "тормазов") соединение будет закрыто.

Также в коде SDK будет хорошей практикой установить свойство ClientWebSocketOptions.KeepAliveInterval https://docs.microsoft.com/ru-ru/dotnet/api/system.net.websockets.clientwebsocketoptions.keepaliveinterval?view=net-5.0#System_Net_WebSockets_ClientWebSocketOptions_KeepAliveInterval

P.S: Посмотрите логи Nginx (timed out)

q00Dree commented 2 years ago

Думаю, можно дописать на такие случаи reconnect в sdk

Доброго времени суток, а когда по планам будет добавлен реконнект?

rus-art commented 2 years ago

Это open source библиотека, любой желающий может дописать функционал

Dazlonar commented 2 years ago

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