SignalR freezing all subsequent http requests - c#

I am trying to use SignalR in my web application and it is hosted on IIS 7.5.
I am using Windows 7 X64 (without SP1) and .Net 4.5 with SignalR v2.0.3.0.
If I run the web application from the IIS express it works fine and nothing hangs up but as soon as I run it from IIS 7.5 it hangs up my app. I confirm that if I disable this piece of code:
$.connection.hub.start().done(function () {
});
everything works fine. Here is the screenshots which suggests the all request go in a indefinite block state after hub is started. Even hub takes around 8-9 seconds to respond but even after that if I request a simple JPG I get nothing and goes in indefinite block state.
Here is the screenshot of the application pool. I am running in Integrated mode.
This is the Hub class:
public class AppHub : Hub
{
public override Task OnConnected()
{
if (Context.User != null)
{
var email = Context.User.Identity.Name;
if (!string.IsNullOrEmpty(email))
{
UserRepository userRepository = new UserRepository();
userRepository.DoSomething(email, Context.ConnectionId);
}
}
return base.OnConnected();
}
public override Task OnDisconnected()
{
if (Context.User != null)
{
var email = Context.User.Identity.Name;
if (!string.IsNullOrEmpty(email))
{
UserRepository userRepository = new UserRepository();
userRepository.DoSomething1(email, Context.ConnectionId);
}
}
return base.OnDisconnected();
}
}

The documentation states that you should be using IIS express on your dev machine, because of the limit on the amount of concurrent requests
When SignalR is hosted in IIS, the following versions are supported.
Note that if a client operating system is used, such as for
development (Windows 8 or Windows 7), full versions of IIS or Cassini
should not be used, since there will be a limit of 10 simultaneous
connections imposed, which will be reached very quickly since
connections are transient, frequently re-established, and are not
disposed immediately upon no longer being used. IIS Express should be
used on client operating system
Same thing with Windows 10.
taken from SignalR documentation here :
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/supported-platforms

This is probably because of request execution limits on Windows 7 which limit how many concurrent requests there can be at a time before they get queued). According to this table here, IIS 7.5 has a request execution limit of 3 or even 1 depending on your OS, which is probably used up by the SignalR connection.

Related

Xamarin Android - VpnService is blocking all apps

An app I'm designing uses the VpnService, along with the VpnService.Builder, classes to generate a VPN in order to block traffic from specific apps. According to the documentation over at developer.android.com, all apps should be allowed through the VPN until Builder.AddAllowedApplication or Builder.AddDisallowedApplication is called.
When my VPN service starts up, for some reason, all apps are being disallowed which is strange. As soon as I disconnect from the VPN, all apps become available again. I need to to allow all, unless otherwise specified (which is what the documentation says should be happening). I start the VPN by calling the following:
private string _sTag = typeof(VpnService).Name;
private VpnServiceBinder _objBinder;
private ParcelFileDescriptor _objVpnInterface = null;
private PendingIntent _objPendingIntent = null;
...
if (_objVpnInterface == null)
{
Builder objVpnBuilder = new Builder(this);
objVpnBuilder.AddAddress("10.0.0.2", 32);
objVpnBuilder.AddRoute("0.0.0.0", 0);
// Form the interface
_objVpnInterface = objVpnBuilder.SetSession("Squelch").SetConfigureIntent(_objPendingIntent).Establish();
// Disallow instagram as a test
objVpnBuilder.AddDisallowedApplication("com.instagram.android");
// Set flag
_bVpnIsRunning = true;
}
So in the above instance, instagram should be the only blocked app, but all traffic appears to be blocked (can't use the chrome app, facebook, etc). Is there something I am missing in regards to this? Should I be specifying something before/after establishing the interface? Any help or direction would be greatly appreciated!
Note: In case it matters, I am targeting android 6.0 and higher. I can provide more source if required.
addDisallowedApplication:
By default, all applications are allowed access, except for those denied through this method. Denied applications will use networking as if the VPN wasn't running.
AddDisallowedApplication excludes the application from your VPNService and allows it to continue to use the "non-VPN" networking stack.
addAllowedApplication:
Adds an application that's allowed to access the VPN connection
Note: You can use an allowed or disallowed list, but not both at the same time.
So lets say we want to "block" any Chrome package from accessing the normal networking stack and redirect any Chrome apps from accessing the network via our "blocking" VPN, we can add all Chrome app package names to our VPNService implementation.
Note: there are 4(?) different Chrome apps, alpha, beta, etc.... so lets just block any package that has the name chrome in it, not really ideal, but for an example it works.
using (var pm = Application.Context.PackageManager)
{
var packageList = pm.GetInstalledPackages(0);
foreach (var package in packageList)
{
if (package.PackageName.Contains("chrome"))
{
Log.Debug(TAG, package.PackageName);
builder.AddAllowedApplication(package.PackageName);
}
}
}
After you .Establish() the VPN connection, all Chrome applications networking will be redirected to your VPNService and thus blocked.

Why will this code relying on RestSharp run fine in my application when run on Windows 1709 but not 1703

I had someone build an application that calls home to confirm the user is in good standing on start-up. When the application is installed on a machine running Windows 1709 I can see the call to the api endpoint when the application starts. However, when I install on Windows 1703 the application does not ever call home (that is the server shows no contact attempt from the ip address where the installation is occurring). I have tried to Install an older .Net (4.5.2) but I get a message in Windows that the installation is blocked because a newer version exists on the machine.
The application installs 106.2.1.1
Here is a block of code - I have anonymized the token and the API endpoint
class RestRoutines
{
public bool testToken(string token)
{
bool passed = false;
var client = new RestClient("https://api.myanonymousapi.com/v1/user-tasks/");
client.AddDefaultHeader("Authorization", token); // "Token validToken");
var response = client.Execute(new RestRequest());
if (response.StatusDescription == "OK")
passed = true;
return passed;
}
}
Is there a dependency we are missing or is something wrong with the code above that causes it to fail in the earlier version of Windows?

How should a GRPC Service be hosted?

I have created a GRPC Server in C# using the example given at Link. Now I want to figure out as how should I be hosting this server so that I achieve following:
Should I make this Server a Console application or a a Windows Service. If I make it a windows Service then updating the service will be cumbersome (which is a big negative) and if I make it a console app then updating will simply need shutting down exe. But that comes with the price of closing the same by mistake. Is there any other better way?
With IIS this issue won't b there as I can simply remove the site from LB and stop the website to perform the update but since GRPC won't be a part of IIS, I am not sure what's the way to get this working.
Any references for the better architecture are welcomed.
We can use Microsoft.Extensions.Hosting pacakge to host a .net core console application by using the HostBuilder API to start building gRPC host and setting it up.
In order to run the gRPC service, we first need to start/stop Grpc.Core.Server in a hosted service. A hosted service is basically a piece of code that is run by the host when the host itself is started and the same for when it is stopped. The following code implement a GrpcHostedService to override IHostedService interface:
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Microsoft.Extensions.Hosting;
namespace Grpc.Host
{
public class GrpcHostedService: IHostedService
{
private Server _server;
public GrpcHostedService(Server server)
{
_server = server;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_server.Start();
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken) => await _server.ShutdownAsync();
}
}
In the Program.cs, use HostBuilder API to start building our grpc host and setting it up:
public class Program
{
public static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder()
// Add configuration, logging, ...
.ConfigureServices((hostContext, services) =>
{
// Better to use Dependency Injection for GreeterImpl
Server server = new Server
{
Services = {Greeter.BindService(new GreeterImpl())},
Ports = {new ServerPort("localhost", 5000, ServerCredentials.Insecure)}
};
services.AddSingleton<Server>(server);
services.AddSingleton<IHostedService, GrpcHostedService>();
});
await hostBuilder.RunConsoleAsync();
}
}
By doing this, the generic host will automatically run StartAsync on our hosted service, which in turn will call StartAsync on the Server instance, essentially start the gRPC server.
When we shut down the host with Control-C, the generic host will automatically call StopAsync on our hosted service, which again will call StopAsync on the Server instance which will do some clean up.
For other configuration in HostBuilder, you can see this blog.
I'm going to add one more option.
With dot net core, you can run this as a Linux Daemon now.
Currently gRPC doesn't support integration with ASP.Net/IIS. You would need to host the server in a console or as a Windows service.
Likely you would want this to be a Windows service to make it easier to keep the server running across reboots or crashes. If you want to easily turn your console application into a Windows service I would recommend using the excellent TopShelf Nuget.
Updating the service can be done as you would a console app.
Stop the Windows service. net stop <service-name}>
Copy the updated assemblies.
Start the Windowsservice net start <service-name>
My company (Shortbar) is building the application server for a hotel management system called HOLMS on gRPC. Our setup is as follows:
HOLMS.Application is a .NET class library (assembly) that does the actual work of the server
HOLMS.Application.ConsoleRunner is a C# console application that hosts HOLMS.Application. The console runner is used by (1) developers for convenience (mentioned in the question) as well as (2) production scenarios running inside a Docker container, where the container runtime (e.g. Amazon ECS) implements job control/scaling. It follows "12 factor app" guidelines, including running itself as a single, standalone, stateless process, fast startup/shutdown, and environment-variable config injection. The system logs to stdout which gets drained however stdout is drained in the prod environment (e.g. Sumo, logstash, etc). This is how our SaaS multi-tenant solution will go into production.
HOLMS.Application.ServiceRunner packages HOLMS.Application into a Windows service, for more traditional, on-premise situations where a customer's IT group will run the service themselves. This package uses the Windows registry for configuration and relies on Windows service job control for startup/shutdown/restarts. It logs to the Windows Event Log.
The ConsoleRunner and ServiceRunner each are only about 200 lines of code; for the most part, they just wrap the Application package, and call into it.
Hope this helps.

Launching a stored-procedure with Task.Factory.StartNew

I am trying to develop a web service which calls a stored procedure. This stored procedure is quite long (around 1h30), and it does numerous "count" and "insert" in a database.
To launch this procedure I used a C# Class task ; here is the example :
[HttpPost]
[Route("updateData/{date:datetime?}")]
public JsonResult UpdateData(DateTime? date) {
try {
Task.Factory.StartNew(() => Data.UpdateData(date), TaskCreationOptions.LongRunning);
return Json("UpdateData successfully started !");
}
catch (Exception e) {
return Json("Error UpdateData: " + e);
}
}
When I test in local environment it works ; but when I work on Azure the process stops after roughly 30 minutes.
For launching the web service I use the Microsoft Azure scheduler.
The problem does not seem to be the stored procedure, but it seems to be in the use of the task (because without the task it works).
Is there something special to do ?
What you're experiencing is an IIS timeout. Once IIS detects inactivity, it will terminate the app pool:
Otherwise, when you have 20 minutes without any traffic then the app pool will terminate so that it can start up again on the next visit.
This happens because Task.Factory.StartNew doesn't register work with IIS, hence it doesn't know that you currently have active work going on.
To avoid this, If you're using .NET 4.5.2, you can use HostingEnvironment.QueueBackgroundWorkItem to register and queue work on a ASP.NET Threadpool thread.
If you're on previous versions, you can use BackgroundTaskManager by Stephan Cleary.
For more, read this post by the .NET Web Development team

Why does my .NET service start really slow on a XP boot

I have a .NET windows service which acts as a host for some wcf. In the OnStart method the service hosts are created and started. The service is configured to startup automatically. This works well on Windows 7 (32bit and 64bit) and it can be startet with "net start" on Windows XP Pro SP3. The service startup with "net start" command takes about 20 seconds.
But when Windows XP Pro SP3 is booting there's a timeout message in the event log. The service itself does not fail to startup, though do its dependencies. The problem can be reproduced on various XP machines. Core count and memory does not have an influence. The updates are up to date.
Now it's getting curious: I analyzed the trace and found out that the service is taking about 60 seconds for startup. Thus I've added a call to ReqestAdditionalTime(480000). But now the service takes slightly more than 480 seconds. The relation is obvious. The time is consumed in the following code section:
var asyncResults = new List<IAsyncResult>();
foreach (var host in myHosts)
asyncResults.Add(host.BeginOpen(null, host));
// wait until finished
while (asyncResults.Count != 0)
{
IAsyncResult ar = asyncResults[0];
if (!ar.IsCompleted) ar.AsyncWaitHandle.WaitOne(1000);
if (ar.IsCompleted)
{
asyncResults.Remove(ar);
var co = (ICommunicationObject)ar.AsyncState;
try
{
co.EndOpen(ar);
}
catch (Exception ex)
{
...
}
}
}
Do you have any idea what's happening here?
Hey, I found the resolution myself by doing some intensive Log-Research.
In the event log there were some services, which started AFTER the timeout of my service has been reached. As my service is running as a sepecial user, I could detect two services, which where acutally triggered by my own service. Thus I added those to the services dependencies and it works.
I wonder if there's a documentation, where the dependencies of wcf are listed.
As reference here are the services, my service is dependen on:
http
RPCSS
CryptSvc
HTTPFilter
RasMan
Latter two where those causing the deadlock.

Categories