我有一个有两台服务器的真实场景。我有一个队列,我只想在两台服务器之一上同时运行一项作业。但看起来两台服务器都在尝试处理这项工作。有可能吗?
我的代码不起作用。要求是,如果一台服务器运行一项作业,另一台服务器不应放入队列而是忘记。在实际场景中,我需要将其分布在多台服务器上。
可能的存储只能是 Redis 和 PostgreSQL。
有关如何解决此问题的任何想法?
using System.Threading;
using System.Threading.Tasks;
using Hangfire;
using Hangfire.Logging;
using Hangfire.Logging.LogProviders;
using Hangfire.MemoryStorage;
using Hangfire.MemoryStorage.Database;
using Hangfire.PostgreSql;
using Hangfire.Pro.Redis;
namespace HangfireLockQueue
{
public class Program
{
static void Main(string[] args)
{
// 1.memory
//JobStorage storage = new MemoryStorageFake(new MemoryStorageOptions());
// 2.redis
//JobStorage storage = new RedisStorage("redis:6379,ssl = false", new RedisStorageOptions
//{
// Prefix = "HangfireRedis-Local:"
//});
// 3.postgres
var connectionString = "Host=postgres;Database=scheduler;Username=test;Password=<>;";
JobStorage storage = new PostgreSqlStorage(connectionString, new PostgreSqlStorageOptions
{
InvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.FromMilliseconds(200),
DistributedLockTimeout = TimeSpan.FromSeconds(10),
});
JobStorage.Current = storage;
Console.WriteLine(JobStorage.Current);
LogProvider.SetCurrentLogProvider(new ColouredConsoleLogProvider());
RunServer1(storage);
RunServer2(storage);
Console.ReadLine();
}
private static void RunServer1(JobStorage storage)
{
Task.Factory.StartNew(() => RunServer1Client1Queue(storage));
}
private static void RunServer1Client1Queue(JobStorage storage)
{
var serverOptions = new BackgroundJobServerOptions
{
ShutdownTimeout = TimeSpan.FromMinutes(5),
ServerName = $"{Environment.MachineName}1.{Guid.NewGuid()}",
Queues = new[] { "queue1" },
WorkerCount = 1
};
using (new BackgroundJobServer(serverOptions, storage))
{
Log("Hangfire Server 1 started. Press any key to exit...");
RecurringJob.AddOrUpdate(
Guid.NewGuid().ToString(),
() => JobThree(),
"* * * * *",
queue: "queue1");
Console.ReadKey();
}
}
private static void RunServer2(JobStorage storage)
{
Task.Factory.StartNew(() => RunServer2Client1Queue(storage));
}
private static void RunServer2Client1Queue(JobStorage storage)
{
Thread.Sleep(2000);
var serverOptions = new BackgroundJobServerOptions
{
ShutdownTimeout = TimeSpan.FromMinutes(5),
ServerName = $"{Environment.MachineName}2.{Guid.NewGuid()}",
Queues = new[] { "queue1" },
WorkerCount = 1
};
using (new BackgroundJobServer(serverOptions, storage))
{
Log("Hangfire Server 2 started. Press any key to exit...");
RecurringJob.AddOrUpdate(
Guid.NewGuid().ToString(),
() => JobThree(),
"* * * * *",
queue: "queue1");
Console.ReadKey();
}
}
public static void JobThree()
{
// implement guard if not working
Thread.Sleep(3000);
Log($"JobThree, current time:{DateTime.Now.ToString()}");
}
public static void Log(string msg, LogLevel level = LogLevel.Info)
{
LogProvider.GetLogger("Main").Log(level, () => { return msg; });
}
}
}