SignalR initial connection very slow on page refresh (delay on OnDisconnected) - ninject

I've been using SignalR for a while in my MVC5 project, but only in the recent weeks I encountered this problem.
Every time I refresh a page or navigate to a different page within my project, it takes a long time (between 3-8 seconds) to establish new connection.
[09:18:12 GMT+0100 (GMT Daylight Time)] SignalR: Attempting to connect to SSE endpoint 'http://localhost:53516/signalr/connect?transport=serverSentEvents&connectio…3A%22notehub%22%7D%2C%7B%22name%22%3A%22retailpriceindexhub%22%7D%5D&tid=6'. jquery.signalR-2.0.3.min.js:8
[09:18:18 GMT+0100 (GMT Daylight Time)] SignalR: EventSource connected.
Although normally I don't use them, I created those override methods for one of my hubs on the server just to see when breakpoints are being hit:
public override Task OnConnected()
{
var connectionId = Context.ConnectionId;
return base.OnConnected();
}
public override Task OnReconnected()
{
var connectionId = Context.ConnectionId;
return base.OnReconnected();
}
public override Task OnDisconnected()
{
var connectionId = Context.ConnectionId;
return base.OnDisconnected();
}
This confirmed that on page refresh OnDisconnected method doesn't get called immediately, but after the delay mentioned above. Once it gets hit, it's followed by OnConnected straight away and everything goes smoothly from that point.
Initially I thought it was similar to: https://github.com/SignalR/SignalR/issues/2719, but:
that was an issue with Chrome (Version 31.0.1650.57); I am on Version
34.0.1847.116 m. my issue affects all browsers (IE being slightly quicker than Chrome or Firefox) according to that issue OnDisconnected was delayed only when navigating to another page in the project - in my case OnDisconnected is not called immediately even when I close the tab or navigate to an external page
When I open a new tab, connection is established immedietaly:
[09:31:26 GMT+0100 (GMT Daylight Time)] SignalR: Attempting to connect to SSE endpoint 'http://localhost:53516/signalr/connect?transport=serverSentEvents&connectio…3A%22notehub%22%7D%2C%7B%22name%22%3A%22retailpriceindexhub%22%7D%5D&tid=6'. jquery.signalR-2.0.3.min.js:8
[09:31:26 GMT+0100 (GMT Daylight Time)] SignalR: EventSource connected.
This proves to me that the delay happens somewhere between $.connection.hub.start() and hitting OnDisconnected method on the server, but I don't know how to trace it down.
I have enabled server side logging by modifying Web.config file, but I can't see anything obvious in the logs.
Also, I have tried changing the transport method to longPolling, but the issue still exists.
Similar issued raised on SignalR github page mentioned AVG or proxy, but none of these are relevant in my case.
I have updated signalR packages (server and client) as well as NewtonSoft.Json to the latest versions to no avail.

The issue has been resolved by changing Ninject scoping for my DbFactory and UnitOfWork bindings. I didn't include that part of code in my question, as I had no idea that's where the issue was.
Originally I was using InRequestScope. After changing to InThreadScope, the issue with slow connection disappeared, however I run into more problems then with DbContext lifecycles.
InCallScope from Ninject.Extensions.NamedScope seems to be ideal for my needs.
Bind<IDbFactory>().To<DbFactory>().InCallScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InCallScope();
If someone can explain why InRequestScope or default InTransientScope had such impact on SignalR performance (initial connection) in my project, I will be happy to accept it as an answer.

Related

Check conditions on startup

I would like to test certain conditions on Startup of my ASP.Net Core 2.0 application. For example if my database server or other is running correctly. This is especially helpful for things that will only be instantiated after a request (like my repository).
Currently I have to do this request manually, but I would like to have my application fail early. At what moment and in what place is such a test recommended?
The Startup class is responsible for setting up your server, making it the perfect candidate for setting up one-time initialization stuff for your application.
You usually have two main methods in Startup: ConfigureServices and Configure. The former runs very early and is responsible for setting up the application services, dependencies and configuration. So you cannot use it to actually perform real work, especially since the dependency injection container is not ready yet.
However, the Configure method is different: While its main purpose is to set up the application middleware pipeline, the components that will later serve requests, you are able to fully use your dependencies here, making it possible to already do more extensive things here. So you could make your calls directly here.
It’s important to understand that Configure still runs rather early, way before your server is actually ready to serve requests. So if your initialization depends on the actual server being around already, you should probably further delay the execution.
The proper solution is likely to hook into the application lifecycle using IApplicationLifetime. This type basically offers you a way to register callbacks that are executed during the application lifecycle. In your case, you would be interested in the ApplicationStarted event which runs when the server just completed its setup phase and is now ready to serve requests. So basically the perfect idle moment to run some additional initialization.
In order to respond to a lifetime event, you need to register your handler inside the Configure method:
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime)
{
// other…
// register lifetime event
applicationLifetime.ApplicationStarted.Register(InitializeApplication);
}
public void InitializeApplication()
{
// do stuff
}
One final note: Apparently, there is currently an open bug that prevents lifetime events from firing when hosting on IIS. In that case, executing your code directly in Configure is probably the best alternative.

Topshelf Windows Service times out Error 7000 7009

I have a windows service programmed in vb.NET, using Topshelf as Service Host.
Once in a while the service doesn't start. On the event log, the SCM writes errors 7000 and 7009 (service did not respond in a timely fashion). I know this is a common issue, but I (think) I have tried everything with no result.
The service only relies in WMI, and has no time-consuming operations.
I read this question (Error 1053: the service did not respond to the start or control request in a timely fashion), but none of the answers worked for me.
I Tried:
Set topshelf's start timeout.
Request additional time in the first line of "OnStart" method.
Set a periodic timer wich request additional time to the SCM.
Remove TopShelf and make the service with the Visual Studio Service Template.
Move the initialization code and "OnStart" code to a new thread to return inmediately.
Build in RELEASE mode.
Set GeneratePublisherEvidence = false in the app.config file (per application).
Unchecked "Check for publisher’s certificate revocation" in the internet settings (per machine).
Deleted all Alternate Streams (in case some dll was marked as web and blocked).
Removed any "Debug code"
Increased Window's general service timeout to 120000ms.
Also:
The service doesn't try to communicate with the user's desktop in any way.
The UAC is disabled.
The Service Runs on LOCAL SYSTEM ACCOUNT.
I believe that the code of the service itself is not the problem because:
It has been on production for over two years.
Usually the service starts fine.
There is no exception logged in the Event Log.
The "On Error" options for the service dosn't get called (since the service doesn't actually fails, just doesn't respond to the SCM)
I've commented out almost everything on it, pursuing this error! ;-)
Any help is welcome since i'm completely out of ideas, and i've been strugling with this for over 15 days...
For me the 7009 error was produced by my NET core app because I was using this construct:
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
and appsettings.json file obviously couldn't be found in C:\WINDOWS\system32.. anyway, changing it to Path.Combine(AppContext.BaseDirectory, "appsettings.json") solved the issue.
More general help - for Topshelf you can add custom exception handling where I finally found some meaningfull error info, unlike event viewer:
HostFactory.Run(x => {
...
x.OnException(e =>
{
using (var fs = new StreamWriter(#"C:\log.txt"))
{
fs.WriteLine(e.ToString());
}
});
});
I've hit the 7000 and 7009 issue, which fails straight away (even though the error message says A timeout was reached (30000 milliseconds)) because of misconfiguration between TopShelf and what the service gets installed as.
The bottom line - what you pass in HostConfigurator.SetServiceName(name) needs to match exactly the SERVICE_NAME of the Windows service which gets installed.
If they don't match it'll fail straight away and you get the two event log messages.
I had this start happening to a service after Windows Creator's Edition update installed. Basically it made the whole computer slower, which is what I think triggered the problem. Even one of the Windows services had a timeout issue.
What I learned online is that the constructor for the service needs to be fast, but OnStart has more leeway with the SCM. My service had a C# wrapper and it included an InitializeComponent() that was called in the constructor. I moved that call to OnStart and the problem went away.

Spring boot 1.3.1 with Tyrus websocket causes Authentication Exception

We recently migrated to Spring boot 1.3.1 from the traditional spring project.
Our existing clients use Tyrus 1.12 as a websocket client.
After the upgrade, we found that the clients no longer connect and throws AuthenticationException. Strangely, they are able to connect for the first time since server restart and soon after throws AuthenticationException.
Digging a bit more, I found that Tyrus receives a 401 initially and passes on credentials subsequently. The server logs indicate the same behaviour, by first assigning ROLE_ANONYMOUS and then the correct role, ROLE_GUEST there after.
It seems like after the negotiation, the server closes connection and disconnects.
I observed the same behaviour when using spring stomp websocket client with Tyrus.
ClientManager container = ClientManager.createClient();
container.getProperties().put("org.glassfish.tyrus.client.sharedContainer", true);
container.getProperties().put(ClientProperties.CREDENTIALS, new Credentials("guest", "guest"));
StandardWebSocketClient webSocketClient = new StandardWebSocketClient(container);
final CountDownLatch messageLatch = new CountDownLatch(10);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
This same server setup works fine when the credentials are sent in the header.
stompClient.connect(url, getHandshakeHeaders("guest", "guest"), handler);
And this will NOT work since the credentials are not in the header
ListenableFuture<StompSession>session = stompClient.connect(url, handler, "localhost", "8080");
I am not understanding why it is working one way and not the other.
After upgrading to spring-boot, our software is no longer backwards compatible and will have to ask all our external clients to inject the authorization in the header before receiving a 401.
Can someone please help?
My earlier post with stacktrace

Task Persistence C#

I'm having a hard time trying to get my task to stay persistent and run indefinitely from a WCF service. I may be doing this the wrong way and am willing to take suggestions.
I have a task that starts to process any incoming requests that are dropped into a BlockingCollection. From what I understand, the GetConsumingEnumerable() method is supposed to allow me to persistently pull data as it arrives. It works with no problem by itself. I was able to process dozens of requests without a single error or flaw using a windows form to fill out the request and submit them. Once I was confident in this process I wired it up to my site via an asmx web service and used jQuery ajax calls to submit request.
The site submits request based on a url that is submitted, the Web Service downloads the html content from the url and looks for other urls within the content. It then proceeds to create a request for each url it finds and submits it to the BlockingCollection. Within the WCF service, if the application is Online (i.e. Task has started) - it pulls the request using the GetConsumingEnumerable via a Parallel.ForEach and Processes the request.
This works for the first few submissions, but then the task just stops unexpectedly. Of course, this is doing 10x more request than I could simulate in testing - but I expected it to just throttle. I believe the issue is in my method that starts the task:
public void Start()
{
Online = true;
Task.Factory.StartNew(() =>
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 20;
options.CancellationToken = token;
try
{
Parallel.ForEach(FixedWidthQueue.GetConsumingEnumerable(token), options, (request) =>
{
Process(request);
options.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (OperationCanceledException e)
{
Console.WriteLine(e.Message);
return;
}
}, TaskCreationOptions.LongRunning);
}
I've thought about moving this into a WF4 Service and just wire it up in a Workflow and use Workflow Persistence, but am not willing to learn WF4 unless necessary. Please let me know if more information is needed.
The code you have shown is correct by itself.
However there are a few things that can go wrong:
If an exception occurs, your task stops (of course). Try adding a try-catch and log the exception.
If you start worker threads in a hosted environment (ASP.NET, WCF, SQL Server) the host can decide arbitrarily (without reason) to shut down any worker process. For example, if your ASP.NET site is inactive for some time the app is shut down. The hosts that I just mentioned are not made to have custom threads running. Probably, you will have more success using a dedicated application (.exe) or even a Windows Service.
It turns out the cause of this issue was with the WCF Binding Configuration. The task suddenly stopped becasue the WCF killed the connection due to a open timeout. The open timeout setting is the time that a request will wait for the service to open a connection before timing out. In certain situations, it reached the limit of 10 max connection and caused the incomming connections to get backed up waiting for a connection. I made sure that I closed all connections to the host after the transactions were complete - so I gave in to upping the max connections and the open timeout period. After this - it ran flawlessly.

ChannelFactory.CreateChannel and proxy instantiation is slow in WCF

I have a client-server application, in which the client communicates with the server using WCF (WCF is used both in the client and the server).
My problem is, that instantiating the auto-generated proxy in the client, in the following way:
new Service1Client() takes constantly 15.xxx seconds.
I tried to solve this problem, and came to the following results:
1) Compiling and running the same code on other computers, ends up in the same way (always 15.xxx seconds).
2) Instantiating the proxy using ChannelFactory.CreateChannel< IService1 >()
doesn't help (it gives the same result).
My guess, is that whenever the channel factory creates a channel, it tries to do something with a 15 seconds timeout, and when it fails, it continues with creation.
By the way, I use .Net 3.5 without SP1, and cannot upgrade to SP1 :(
Thanks ahead
Even though it is already outdated, it may be useful for somebody else searching for the same. Problem could be with DNS resolution problem, that might be solved in SP1. So you can check if it happens only when you use host name or also with specified IP address.
I've seen this before, where the time was being taken in looking for a proxy server. Check your WinINET (Internet Explorer) proxy settings.
My specific reason for thinking "proxy server" is that it takes 15s. 15s sounds like a nice round number for a network timeout.
Even though this is very old information I just found this issue too although I was experiencing a 7second delay on the First call to a method on the Service Client, I tracked it (in my environment) to Internet Explorer settings as stated above, but in my circumstances it wasn't a Proxy enabled, but the Automatically Detect Settings.
Connections -> Lan Settings and Automatically Detect settings was enabled.
I played with the machine.config and app.config and set
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
Which also made no difference.
I found this answer here and thought I'd contribute a little more information in case someone else in the future experiences something like this.
(This with a .Net 4 WCF service)