Experiencias con HangFire

710 views
Skip to first unread message

Carlos Admirador

unread,
Sep 5, 2017, 6:03:34 PM9/5/17
to AltNet-Hispano
Buenas a toda la comunidad.

Quería preguntar vuestras experiencias con Hangfire (herramienta para background processing) en ASP.NET, y también como Windows Service (para el Hangfire server):

https://improveandrepeat.com/2017/09/a-quick-overview-on-hangfire-io


Es un tema delicado, atención al Background en ASP.NET y sus problemas como ya comentan Haacked o Ayende

Phil Haack wrote a great article on the dangers of recurring background tasks in ASP.NET
http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/

http://ayende.com/blog/155489/rotten-scheduling-dont-roll-your-own#comments


Y si se sigue adelante considerar todo estos frameworks y tools antes de reinventar la rueda

Un montón de alternativas como HangFire (por la que pregunto en este caso), Quarz.net y muchas más
http://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
http://blog.koalite.com/2012/05/programacion-de-tareas-con-quarz-net/

Me g ustaría saber en detalle vuestras experiencias.

Saludos
Carlos

Modesto San Juan

unread,
Sep 5, 2017, 7:06:35 PM9/5/17
to altnet-...@googlegroups.com
Hola,

He usado Hangfire en varios proyectos y estoy encantado. Normalmente lo he preferido utilizar como servicio de Windows, pero para tareas cortas o que no me importaba si se interrupían y luego se volvían a lanzar, me he conformado con utilizarlo desde ASP.Net.

Sólo con el dashboard que te proporcionan ya ha ganado muchos puntos frente a Quarz.Net. Además su API es bastante sencillo y recurrir a procesamiento de tareas de forma distribuida, chaining, etc es muy sencillo.

Si estás dudando entre Quarz.Net y Hangfire, yo me decantaría por Hangfire por su facilidad de uso y la potencia que proporciona.

Un saludo

--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispano+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-hispano@googlegroups.com.
Visita este grupo en https://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Mauro Decima

unread,
Sep 6, 2017, 11:35:08 AM9/6/17
to altnet-...@googlegroups.com
Carlos, en mi caso llevamos una un año utilizando quartz.net, claro que lo utilizamos como un reemplazo de tareas programadas.
Las ejecuciones no son iniciadas desde un sistema sino desde una programacion de tiempo en un servicio de windows.
Para este escenario es imbatible, admite expresiones cron lo que permite temporizar casi cualquier escenario, multiples host de ejecucion, control de concurrencia, agrupar instancias.
Posee un modelo de programación que permite para aportar codigo e inteligencia a cada etapa de la ejecucion.

Su punto debil, la interfaz hay proyectos como QuartzNetWebConsole y crystal-quartz pero no son tan amigables como Hangfire.

Para publicar en este grupo, envía un correo electrónico a altnet-...@googlegroups.com.

Visita este grupo en https://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Carlos Admirador

unread,
Sep 7, 2017, 5:41:39 PM9/7/17
to AltNet-Hispano
Muchas gracias por las aportaciones.

Una curiosidad, en vuestras experiencias reales, podéis comentar qué tipo de tareas ? Pienso en tareas como reporting (generación de informes), envío de correos, procesos para actualizar una base de datos, llamadas a web services...

Con ejemplos reales se tiene otra dimensión, lo que he visto -hasta ahora- el job es un Writeline en pantalla:


RecurringJob.AddOrUpdate(
                () => Debug.WriteLine("Minutely Job"), Cron.Minutely);



Entiendo que el Servicio Windows es el Hangfire Server, y desde ASP.NET se utiliza el HangFire Client para crear la tarea (job). Job Storagees una bd Sql Server ?


Mauro, algún ejemplo de código concreto, cuando te refieres a "una programacion de tiempo en un servicio de windows" ?


Encontré estas referencias de interés, aunque el job no sea de proyecto real, sino el típico Console.WriteLine.
 
https://github.com/HangfireIO/Hangfire.Samples/tree/master/Hangfire.WindowsServiceApplication

http://www.talkingdotnet.com/integrate-hangfire-with-asp-net-core-web-api/


Saludos
Carlos
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.

Para publicar en este grupo, envía un correo electrónico a altnet-...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/altnet-hispano.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.

Modesto San Juan

unread,
Sep 7, 2017, 8:12:05 PM9/7/17
to altnet-...@googlegroups.com
He usado Hangfire sobre todo para tareas relacionadas con procesos ETL, envíos de peticiones a servidores externos en batch y envíos de correos.

Por cierto, el servicio de Windows lo montábamos con Topshelf

Un saludo

Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispano+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a altnet-hispano@googlegroups.com.

Carlos Admirador

unread,
Dec 24, 2017, 6:04:30 AM12/24/17
to AltNet-Hispano
NO es ejemplo real world, pero puede dar ideas. En este caso, alojar un WCF en Windows Service utilizando TopShelf.

Lo importante del WCF windows service  hosting es que se cierre bien el WCF (atención al Abort, Close, dispose).

Interesante la clase WcfServiceWrapper

No se entra en este caso en throlling ni escalabilidad para un número de peticiones amplio.



’ve chosen to encapsulate that process so I can easily apply it to any service I want to expose.

public class WcfServiceWrapper<TServiceImplementation, TServiceContract>
    : ServiceBase
    where TServiceImplementation : TServiceContract
{
    private readonly string _serviceUri;
    private ServiceHost _serviceHost;
 
    public WcfServiceWrapper(string serviceName, string serviceUri)
    {
        _serviceUri = serviceUri;
        ServiceName = serviceName;
    }
 
protected override void OnStart(string[] args)
    {
        Start();
    }
 
    protected override void OnStop()
    {
        Stop();
    }
 
... omitido ...



Con TopShelf:
private static void Main(string[] args)
    {
        const string serviceUri = "http://localhost:10000/calc";
        var host = HostFactory.New(c =>
            {
                c.Service<WcfServiceWrapper<Calculator, ICalculator>>(s =>
                    {
                        s.SetServiceName("CalculatorService");
                        s.ConstructUsing(x =>
                            new WcfServiceWrapper<Calculator, ICalculator>("Calculator", serviceUri));
                        s.WhenStarted(service => service.Start());
                        s.WhenStopped(service => service.Stop());
                    });
                c.RunAsLocalSystem();
 
                c.SetDescription("Runs CalculatorService.");
                c.SetDisplayName("CalculatorService");
                c.SetServiceName("CalculatorService");
            });
 
        Console.WriteLine("Hosting ...");
        host.Run();
        Console.WriteLine("Done hosting ...");
    }



First run it as a console application

>Calculator.exe
Hosting ...
Calculator starting...
Calculator started at http://localhost:10000/calc


install the calculator as a Windows Service.

>Calculator.exe install
Hosting ...
 
Running a transacted installation.
 
Beginning the Install phase of the installation.
Installing service CalculatorService...
Service CalculatorService has been successfully installed.
Creating EventLog source CalculatorService in log Application...
 
The Install phase completed successfully, and the Commit phase is beginning.
 
The Commit phase completed successfully.
 
The transacted install has completed.
Done hosting ...



To uninstall the CalculatorService run it again from a command window with the uninstall argument. You don’t even have to stop the server first as TopShelf will do that for you.

>Calculator.exe uninstall
Hosting ...
 
 
The uninstall is beginning.
Removing EventLog source CalculatorService.
Service CalculatorService is being removed from the system...
Service CalculatorService was successfully removed from the system.
Attempt to stop service CalculatorService.
 
The uninstall has completed.
Done hosting ...


Felices Fiestas. Happy coding!

Carlos Admirador

unread,
Mar 9, 2018, 1:57:59 PM3/9/18
to AltNet-Hispano
Dónde encajaría  Hangfire para tenerlo "alojado" en un Windows Service utilizando TopShelf? Se queda esperando peticiones...?
Salu2

Modesto San Juan

unread,
Mar 9, 2018, 5:15:30 PM3/9/18
to altnet-...@googlegroups.com
En efecto, puedes tenerlo perfectamente en un servicio Windows con topshelf, yo lo tengo así en producción desde hace tiempo y funciona a las mil maravillas.

Pero también puedes desplegarlo en un sitio web con asp.net sin problemas. Vamos, que lo que más conveniente te resulte para resolver el problema que tengas.

Y recuerda que el Dashboard lo puedes desplegar de forma independiente en un IIS si lo prefieres.


El 9 mar. 2018 7:58 p. m., "Carlos Admirador" <admirado...@gmail.com> escribió:
Dónde encajaría  Hangfire para tenerlo "alojado" en un Windows Service utilizando TopShelf? Se queda esperando peticiones...?
Salu2

--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispano+unsubscribe@googlegroups.com.

Carlos Admirador

unread,
Mar 11, 2018, 11:27:21 AM3/11/18
to AltNet-Hispano
Tengo 3 App Domains como "cliente": ASP.NET Web Forms, Windows Forms App y Unit Testing.

Como Servidor el Windows Service.


Configuración en cliente ????





En el Windows Service (Hangfire Server)

  public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseHangfireDashboard();
}
}



// Storage is the only thing required for basic configuration.         // Just discover what configuration options do you have.
        GlobalConfiguration.Configuration.UseSqlServerStorage("<name or connection string>");
            //.UseActivator(...)
            //.UseLogProvider(...)

GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire");
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:9095");
options.Urls.Add("http://127.0.0.1:9095");
options.Urls.Add($"http://{Environment.MachineName}:9095");

WebApp.Start<Startup>(options);

veo otras configuraciones de servidor:

app.UseHangfireServer(new BackgroundJobServerOptions
{
HeartbeatInterval = new System.TimeSpan(0, 1, 0),
ServerCheckInterval = new System.TimeSpan(0, 1, 0),
SchedulePollingInterval = new System.TimeSpan(0, 1, 0)
});





El viernes, 9 de marzo de 2018, 23:15:30 (UTC+1), Modesto San Juan escribió:

Carlos Admirador

unread,
Mar 25, 2018, 6:01:58 AM3/25/18
to AltNet-Hispano

Notas.

Teniendo Client y Server separados, un cliente añade un job a la base de datos, mientras el server consulta la base de datos y ejecuta los Jobs en background.

Cliente y Server acceden a la base de datos y comparten ASSEMBLIES
Hangfire no puede trabajar sin base de datos (en este caso).

Desde el cliente se trabaja con el principio "Fire and Forget".

Ejecutar MethodToRun en un proceso separado:

BackgroundJob.Enqueue(() => MethodToRun(42, "foo"));


Hangfire serializa este job con valores de entrada y lo almacena en la base de datos:

{
    "Type": "HangClient.BackgroundJobClient_Tests, HangClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
    "Method": "MethodToRun",
    "ParameterTypes": "(\"System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\",\"System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\")",
    "Arguments": "(\"42\",\"\\\"foo\\\"\")"
}

Con esto es suficiente para llamar al método en un proceso separado con reflection, y teniendo acceso al assembly HangClient donde está declarado.


En los ejemplos, que he visto, se pasan tipos simples (string, int...), imagino que con objetos (clases) bastará tener los ensamblados en Client y Server.

 

Carlos Admirador

unread,
Jun 29, 2018, 5:28:49 PM6/29/18
to AltNet-Hispano
Hola gente!!!

Lo valioso, IMHO, son las experiencias real world, lo que puede llevar a buenas prácticas.

Ejemplo con HangFire y MediatR:




Y una guía detallada sobre Hangfire y ASP NE CORE:

Hangfire Best Practices


Make Job Arguments Small and Simple

Run the Hangfire Server in a Separate Process


Saludos gente!!

Gonzalo Brusella

unread,
Jul 2, 2018, 3:50:10 PM7/2/18
to altnet-...@googlegroups.com

Estimad@s,

En mi experiencia con HangFire, siempre termine teniendo un server aparte para hangfire, ya se apor estabilidad o por que come hilos de IIS.

Hace un tiempo estaba buscando como sacarlo y me parece que  se pueden hacer cosas interesantes con .net core 2.1 Generic Host (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.1). Necesito pensar un poco en la implementacion (y ver como evoluciona esto), pero creo que tiene buen futuro.

Gonzalo A. Brusella
gon...@brusella.com.ar
http://www.brusella.com.ar

.. / .- -- / .-.. --- --- -.- .. -. --. / ..-. --- .-. / - .... . / ... -.-. .... .-. --- -.. .. -. --. . .-. ... / -.-. .- - .-.-.-  / .. - / ... . . -- ... / - --- / -... . / -.. . .- -.. / .- -. -.. / .- .-.. .. ...- . .-.-.- 


--
Has recibido este mensaje porque estás suscrito al grupo "AltNet-Hispano" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a altnet-hispan...@googlegroups.com.

Carlos Admirador

unread,
Jul 6, 2018, 2:24:02 PM7/6/18
to AltNet-Hispano
A ver un ejemplo real-world NET Core 2.1 Generic Host para ver todo su potencial. Parece que así el IIS no tiene sentido ahora???


Y hablando de Colas , Sql Server y distributed locks: sp_getapplock....


Alguien se ha pegado bien con Hangfire, Sql Server y MSMQ ?


Hangfire.SqlServer.MSMQ extension changes the way Hangfire handles job queues. Default implementation uses regular SQL Server tables to organize queues, and this extensions uses transactional MSMQ queues to process jobs in a more efficient way:


Limitations

  • Only transactional MSMQ queues supported for reliability reasons inside ASP.NET.
  • You can not use both SQL Server Job Queue and MSMQ Job Queue implementations in the same server (see below). This limitation relates to Hangfire Server only. You can still enqueue jobs to whatever queues and watch them both in Hangfire Dashboard.



Configuration
GlobalConfiguration.Configuration
.UseSqlServerStorage(GetConnectionStringBuilder().ConnectionString)
.UseMsmqQueues(@“FormatName:Direct=OS:localhost\hangfire-{0}”);


Starting Server
server = new BackgroundJobServer();

Queuing Job
var manager = new RecurringJobManager();
manager.AddOrUpdate(“Rec-Show-Message”,Job.FromExpression(() => ShowMessage()), Cron.Minutely());



Unable to see any queue created in MSMQ or Job getting executed. I have already configured DTC by following the link: [http://nthrbldyblg.blogspot.com/2017/02/msmq-between-two-computers.html 1]


Quién configura automáticamente colas MSMQ con Powershell ?

Added the following code before configuration and MSMQ started working.


var queuePath = @".\Private$";
var queueName = “YourQueueName”;
if (!MessageQueue.Exists(string.Format("{0}{1}", queuePath, queueName)))
{
var queue = MessageQueue.Create(string.Format("{0}{1}", queuePath, queueName), true);
queue.Label = “Your Queue Description”;
}


Reply all
Reply to author
Forward
0 new messages