НГ
Отлаживаю работу ktor server websocket в краевых ситуациях, когда сеть себя плохо ведёт, когда происходит некий race condition с закрытием сокета, (клиент закрывает сокет [FIN,ACK] а сервер пытается написать[будет RST] и тд.
Столкнулся с непониманием:
suspend outgoing.send функция имеет очень вероятностное описание:
/** Enqueue frame, may suspend if outgoing queue is full. May throw an exception if outgoing channel is already closed so it is impossible to transfer any message. Frames that were sent after close frame could be silently ignored. Please note that close frame could be sent automatically in reply to a peer close frame unless it is raw websocket session.
*/
есть еще метод suspend flush()/** Flush all outstanding messages and suspend until all earlier sent messages will be written. Could be called at any time even after close. May return immediately if the connection is already terminated. However it may also fail with an exception (or cancellation) at any point due to session failure. Please note that [flush] doesn't guarantee that frames were actually delivered.
*/
Но по моим наблюдениям метод send засыпает и ждет подтверждения ACK от клиента. (тестовый стенд - простой сервер который в цикле раз в секунду шлет сообщение клиенту - delay + send)По поведению не видно, что send делает enqueue в какую-то очередь абстрагированную от TCP слоя. При таком поведении не понятно предназначение метода flush, ведь send делает все за него.
При таком поведении становится невозможным пользоваться вот таким кодом для рассылки данных между подключенными клиентами:
// Iterate over all the connections
for (conn in wsConnections) {
conn.outgoing.send(Frame.Text(text))
}
ps Код приведен из документации по websocket с сайта ktor
смысл: broadcast неких данных всем "подписчикам"
В итоге из-за нескольких очень медленных клиентов этот for будет очень медленно работать, так как каждый outgoing.send будет дожидаться ответа. а в некоторых ситуациях и вовсе будет suspend почти на вечно (но это рассказ для отдельного issue, пока не берем это в расчет)
заворачивать каждый send в async это не вариант.
Вообщем не хватает матчасти, нужно больше тестов, больше чтения кода и понимания. Может кто-то сможет дать дельные советы.