JMS微服务开发示例(三)使用分布式锁和编写定时任务

分布式锁

在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("我的任务运行了");
            });
        }
    }    

这样,程序被强行关闭时,就不会出现任务执行一半就退出的情况。

 

上一篇 示例(二)    下一篇 示例(四)

posted @ 2020-07-23 10:06  IWing  阅读(765)  评论(0编辑  收藏  举报