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.
Related
I Have an Azure Cloud Function that pushes messages to a queue under a Azure Service Bus namespace. The receiver for this queue is a .NET Framework 4.6.1 application which has the Service Bus SDK[Azure.Messaging.ServiceBus] installed. Problem is that the code sample references online are mostly for console applications which has Program.cs. My application has a Global.asax file, i believe, as the startup file.
So I referred the code from here. Placed it in Global.asax but not able to receive messages.
What has been tried is, I've created a console application on the same VM as the one which has the application mentioned above. Installed the SDK and pasted the listener code. It was able to receive messages from Service bus, which strikes off any possibilities of network misconfiguration. So most likely its the setup at .net 4.6.1 application level
Can anyone help with a sample service bus receiver/listener code?
Create a Service Bus in Azure.
And create a Queue.
And pushed some messages to the queue as per the link given.
For Queue_AccessKey string, copy the string from azure as shown below.
Use the Console application and use the below code in .Net 4.6.1 framework.
For this the NuGet "Microsoft.Azure.ServiceBus" version="5.2.0" targetFramework="net461” has to be installed in the project.
And the below namespace has to be used in the code.
using Microsoft.Azure.ServiceBus;
connectionString = new ServiceBusConnectionStringBuilder(Queue_AccessKey);
qClient = new QueueClient(connectionString, ReceiveMode.ReceiveAndDelete, RetryPolicy.Default);
var msgHandler = new MessageHandlerOptions(ListenerExceptionHandler)
{
MaxConcurrentCalls = 1,
AutoComplete = false
};
qClient.RegisterMessageHandler(ReceiveMessageFromQueue, msgHandler);
I am working with some sort a small RESTful layer to expose (to the internet) the local application data in a host machine.
It behaves like a typical web service that listens incoming request to a port. I wrote it with ASP .NET Core 3.1 with a tiny layer wrapper called Carter, it has also a DLL / COM Reference (used for querying the data).
I followed the following guides to configure it as a windows service, publish the service, and then to create it.
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-5.0&tabs=visual-studio
https://dotnetcoretutorials.com/2019/12/21/hosting-an-asp-net-core-web-app-as-a-windows-service-in-net-core-3/
I did successfully created a service but it won't start and windows is showing this error dialog.
I am relatively new to .NET development and I am not sure what's wrong here or how to fix this.
Program.cs
namespace Adapter
{
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>())
.Build();
host.Run();
}
}
}
Startup.cs
namespace Adapter
{
public class Startup
{
public Startup()
{
// load the env values during start up
new Env().Load();
}
public void ConfigureServices(IServiceCollection services)
{
// interface binding for dependency injection
services.AddSingleTonServices();
// carter and routing services
services.AddCarter();
services.AddRouting();
services.AddHostedService<Worker>();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(builder => builder.MapCarter());
}
}
}
BTW My project is running correctly when you run or debug it in visual studio.
Any help or idea will be much appreciated.
Error 1053: The service did not respond to the start or control request in a timely fashion is the problem caused by the timeout after the particular request.
This error has many variants.You can read this article to try to solve:
[Fix] Error 1053: The service did not respond to the start or control request in a timely fashion
Alternatively, to resolve this issue, you can download the following registry fix for your operating system:
Windows Search “Error 1053” Fix for Windows 7
Windows Search “Error 1053” Fix for Windows 8.1
Windows Search “Error 1053” Fix for Windows 10
I am trying to digest a Xamarin.Forms app (developed by James Montemagno) on which the Generic Host Builder is applied.
The following is the Init method extracted from this line:
public static App Init(Action<HostBuilderContext, IServiceCollection> nativeConfigureServices)
{
// others are removed for simplicity
var host = new HostBuilder()
.ConfigureServices((c, x) =>
{
nativeConfigureServices(c, x);
ConfigureServices(c, x);
})
.ConfigureLogging(l => l.AddConsole(o =>
{
o.DisableColors = true;
}))
.Build();
App.ServiceProvider = host.Services;
return App.ServiceProvider.GetService<App>();
}
Note: Init have not run the host but it will be invoked from Android project as follows:
protected override void OnCreate(Bundle savedInstanceState)
{
// others are removed for simplicity.
LoadApplication(Startup.Init(ConfigureServices));
}
Question
Now if I compare with Asp.net Core, we know that IHost.Run() is invoked in Program.Main. The question is:
Who invokes IHost.Run() in the Xamarin.Forms app above?
From the way I understand it, this setup does not make use of actually running the host. Instead, it just relies to building it to make sure that DI and all the other related services are available and can be used by Xamarin.
Starting a host actually doesn’t do that much with the generic host. It will mostly just start the host lifetime and run hosted services (like the ASP.NET Core application would be).
But in Xamarin, starting the XAML application is something that already works on its own. So it doesn’t need to be “hosted” (although I rather think that we simply cannot have it owned by the host yet).
So this setup just makes use of the host environment to enable DI, configuration and logging, instead of using the host capabilities to actually run things. This also means that with this setup you probably won’t be able to run other hosted services within the application (unless you manage a way to properly start and stop the host within the App).
Even though there are similar questions, I couldn't find any that solves mine. I have a simple program that runs as a service and I want to start it programatically. It's as simple as this:
private static void StartService()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
As expected, I can't just start my service without installing it. Windows gives me the following error message:
Cannot start service from command line or debugger. A windows service must first be installed using installutil.exe and then started with service explorer, Windows services administrative tool or NET start.
So far so good. So I went there and did just as the docs says:
installutil <my_project>.exe
The installation was successful and I can even start my service from Service Manager or net start. The only problem is: when I debug my application (via F5), Windows keeps showing me the exact same message: Cannot start service (...).
I've found a solution here that uses this:
public void onDebug()
{
OnStart(null);
}
Which allows me to run and debug my application normally, but I actually need it to run as a service and Windows refuses to start that way. Is there anything I'm missing?
It is not in your power to just start a Service like a normal programm. The Service must be registered with and started by the Service manager. That is one of the (many) rules of Windows services. And you have to repeat that for every new build.
As this and other Service related rules (no interactive sessions) can make developing them a Pain, a common approach is to develop them using a console application. I could not find my ideal example, but I found something like it:
https://alastaircrabtree.com/how-to-run-a-dotnet-windows-service-as-a-console-app/
Of course a better longterm plan might be to stop using Services alltogether and switch over to the Windows Task Scheduler. It depends heavily on what exactly you need this code to be able to do in practice.
I'm building a Windows Service that uses FileSystemWatcher, and runs in the background.
I don't want to keep on uninstalling and installing the service every time I want to debug, so would like to do most of my development in a normal program before moving it into a service. But I'm quite new to this, and when I run it, it just runs through the block and exits.
What would be a good way to keep the program running?
http://einaregilsson.com/run-windows-service-as-a-console-program/
I've used this before to debug my service as a Console application based on whether its running in an interactive user environment.
public partial class DemoService : ServiceBase
{
static void Main(string[] args)
{
DemoService service = new DemoService();
if (Environment.UserInteractive)
{
service.OnStart(args);
Console.WriteLine("Press any key to stop program");
Console.Read();
service.OnStop();
}
else
{
ServiceBase.Run(service);
}
}
while (true)
{
// Execute your program's functionality here.
}
I wrote a 7 part series a while ago titled: Building a Windows Service. It covers all the intricacies of building services, making them friendly to debug, and self-installing.
The basic feature set I was looking for was as follows:
Building a service that can also be used from the console
Proper event logging of service startup/shutdown and other activities
Allowing multiple instances by using command-line arguments
Self installation of service and event log
Proper event logging of service exceptions and errors
Controlling of start-up, shutdown and restart options
Handling custom service commands, power, and session events
Customizing service security and access control
The final result was a Visual Studio project template that creates a working service, complete with all of the above, in a single step. It's been a great time saver for me.
see Building a Windows Service – Part 7: Finishing touches for a link to the project template and install instructions.
Here’s documentation from MSDN # http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx?ppud=4 . I have tried it before and it works under .NET Framework 3.x. I could not find my descriptive notes on it, at the moment.
Use the pragma #If DEBUG for debugging purposes like console outputs. Another is using the Debug object.
If you have any trouble with this, say so. I may be able to find my notes or make a Windows Service app myself, just to see if the steps on MSDN still work.