分布式鎖
在Controller當中,提供了分布式鎖的功能,代碼如下:
class HelloworldController : MicroServiceControllerBase { static List<string> Users = new List<string>(); ILogger<HelloworldController> _logger; public HelloworldController(ILogger<HelloworldController> logger) { _logger = logger; } public void Test() { //鎖定指定的key if( this.TryLock("my key")) { _logger.LogInformation("鎖成功"); //使用完畢這里記住要釋放鎖 this.TryUnLock("my key"); } } }
編寫定時任務
創建一個類,實現JMS.IScheduleTask接口
class AutoRun : JMS.IScheduleTask { public double[] Timers => null; public int Interval => 5000;//設置每隔5秒執行一次 public void Run() { Console.WriteLine("auto running at " + DateTime.Now); } }
注冊定時任務
var msp = new MicroServiceHost(services); msp.Register<HelloworldController>("Hello world"); msp.RegisterScheduleTask<AutoRun>(); msp.Build(port, gateways) .Run();
如果定時任務時間間隔單位較大,應設置Times屬性
如:Times = new [] { 11.30 18.45 } 表示在每天的11:30 和 18:45 分別執行一次
在定時任務中使用分布式鎖
定時任務默認支持依賴注入,所以,注入IKeyLocker即可使用分布式鎖
class AutoRun : JMS.IScheduleTask { IKeyLocker _keyLocker; public AutoRun(IKeyLocker keyLocker) { _keyLocker = keyLocker; } public double[] Timers => new[] { 11.47 }; public int Interval => 0; public void Run() { var tranid = $"A{ Thread.CurrentThread.ManagedThreadId }"; if( _keyLocker.TryLock(tranid, "test")) { _keyLocker.TryUnLock(tranid, "test"); } Console.WriteLine("auto running at " + DateTime.Now); } }
tranid是自定義的事務id,為了和controller事務id 區分開來,我使用了字母+線程id的規則生成一個事務id。
controller當中默認事務id為純數字。
使用Quartz實現定時任務
由於quartz能實現更多功能,如支持cron表達式,所以也可以選擇quartz來實現定時任務,如何使用quartz,可以參考
https://www.cnblogs.com/IWings/p/14205224.html
在微服務中使用quartz和在控制台里面使用是一樣的,畢竟微服務也是一個控制台程序而已,唯一需要注意,就是當程序被kill -15強制退出時,我們需要保證正在運行的定時任務執行完畢,
才允許程序退出,為了實現這一點,只需要在創建Task時,改用SafeTaskFactory創建
public class TimingJob : IJob { Task IJob.Execute(IJobExecutionContext context) { return host.ServiceProvider.GetService<SafeTaskFactory>().StartNew(() => { Console.WriteLine("我的任務運行了"); }); } }
這樣,程序被強行關閉時,就不會出現任務執行一半就退出的情況。