Code-Sharp / WampSharp

A C# implementation of WAMP (The Web Application Messaging Protocol)
http://wampsharp.net
Other
385 stars 84 forks source link

Request to upgrade to .net 5.1 to fix Websocket issues #336

Closed BramVader closed 3 years ago

BramVader commented 3 years ago

We regularly experience the following exception (mostly under heavy load):

System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake.
 ---> System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake.
 ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
   at System.Net.WebSockets.ManagedWebSocket.WriteFrameToSendBuffer(MessageOpcode opcode, Boolean endOfMessage, ReadOnlySpan`1 payloadBuffer)
   at System.Net.WebSockets.ManagedWebSocket.SendFrameFallbackAsync(MessageOpcode opcode, Boolean endOfMessage, ReadOnlyMemory`1 payloadBuffer, CancellationToken cancellationToken)
   at System.Net.WebSockets.ManagedWebSocket.SendFrameFallbackAsync(MessageOpcode opcode, Boolean endOfMessage, ReadOnlyMemory`1 payloadBuffer, CancellationToken cancellationToken)
   at System.Net.WebSockets.ManagedWebSocket.HandleReceivedPingPongAsync(MessageHeader header, CancellationToken cancellationToken)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at WampSharp.WebSockets.WebSocketWrapperConnection`2.ReadMessage(ArraySegment`1 receivedDataBuffer, MemoryStream memoryStream)
   at WampSharp.WebSockets.WebSocketWrapperConnection`2.RunAsync()
   at WampSharp.V2.CalleeProxy.ClientInvocationHandler.AwaitForResult[T](AsyncOperationCallback`1 asyncOperationCallback, CancellationTokenRegistration registration)
   ::
   at WampSharp.V2.CalleeProxy.ClientInvocationHandler.AwaitForResult[T](AsyncOperationCallback`1 asyncOperationCallback, CancellationTokenRegistration registration)

I noticed the AwaitForResult lines at the end can be 100's of lines (sounds like recursion). I suspect that every AwaitForResult line stands for an ongoing WAMP-operation (we use a lot of long running, progressive RPCs).

When this error occurs, the ongoing WAMP-operations are cancelled and it takes a while before the clients have started their new long running progressive RPCs.

The cause of the exception seems to be known, see https://github.com/dotnet/runtime/issues/39198. It is fixed in .net 5.0.0 (see https://github.com/dotnet/runtime/pull/39199) and back ported to .net 3.1.18 (see https://github.com/dotnet/corefx/pull/42950).

I have no idea how this relates to .net standard but I know it versions slowly and might not have the fix in due time. Is it possible to have a separate .net 5 build so we can benefit from this fix?

darkl commented 3 years ago

From my understanding, you can use .NET 5.0 with .NET Standard 2.1 and there's no reason to add a target for .NET 5.0. See this awesome analogy made by David Fowler.

Elad

BramVader commented 3 years ago

Thanks for your response. It's indeed the target framework of the consuming application that matters. So if my consuming application is running under .net 5 (with the latest fixes) and because .net 5 exposes the .net standard 2.1. "interface" (as per the analogy), WampSharp will also benefit from the latest fixes. Makes sense...