巴黎吃货之旅

 业务背景

在多少复杂点业务系统中,不可防止会遭逢做定时职责的须要,比如天猫的交易超时自动关闭订单、超时自动确认收货等等。对于有些定时作业相比较多的种类,经常都会搭建专门的调度平台来治本,通过创建定时器来周期性执行任务。如刚刚所说的风貌,我们可以给订单创制一个特其他职责来处理贸易意况,每秒轮询一回订单表,找出这些符合超时条件的订单然后标记状态。这是最简便无情的做法,但肯定也很low,自己都下不去手写那样的代码,所有必须求找个更好的方案。

归来真正项目中的场景,系统中某个活动上线后要给目的用户发送短信通知,那几个文告须求按时间点批量发送。即使一度按照quartz.net给系统搭建了职分调度平台,但真的不想用上述方案来兑现。在网上各样搜索和思辨,找到一篇文章让自家眼睛一亮,稍加分析发现里面的笔触完全符合现在的光景,于是决定在温馨项目中已毕出来。

 

第二站-韩国街

顺着虹井路直接走,向来走,就到了新加坡闵行大名鼎鼎的高丽国街-虹泉路,那条街是高丽国人在新加坡的聚居处,基本都是些大韩民国的店,韩国烤肉,韩式火锅,大韩民国炸鸡,高丽国咖啡店,南朝鲜面包,南朝鲜商厦等等。

虹泉路

即便很想吃烤肉,水源王烤肉,喜来稀肉,不过已经吃过饭了(相对不是因为没钱)。沿着南朝鲜街走来走去,看了一家又一家烤肉,部队锅,然而都吃不起,找了caffebene,张东健,金秀贤代言的,中文名翻译的多好哎,咖啡陪您,奈何没有钱,只点了一个冰激凌。

冰淇淋

说实话,有点太甜了,果然穷人不适合咖啡馆,有时候也是想像文艺青年一样,那么一个午后,安静的坐在咖啡馆的靠窗的职位,望着书。好刺激,好装逼呀。
值得一说的是,咖啡陪您的取餐系统,好高端呀,乡下去的孩子,没见过如此的啊。

叫单机

澳门美高梅手机网站,撸码已毕

光讲原理不上代码怎么能行呢,按照地方的笔触,上边一步步在.net平台下完结出来。

先做一些基础封装。

先是构造职分参数的基类,用来记录职务的职位音信和概念业务回调方法:

    public class DelayQueueParam
    {
        internal int Slot { get; set; }

        internal int CycleNum { get; set; }

        public Action<object> Callback { get; set; }
    }

接下去是中央位置。再社团队列的泛型类,真实类型必须派生自上边的基类,用来扩充部分业务字段方便消费时选拔。队列的紧要品质有眼前地方指针以及数组容器,主要的操作有插入、移除和消费。插入任务时索要传入执行时间,用来总结那个职责的坐标。

    public class DelayQueue<T> where T : DelayQueueParam
    {
        private List<T>[] queue;

        private int currentIndex = 1;

        public DelayQueue(int length)
        {
            queue = new List<T>[length];
        }

        public void Insert(T item, DateTime time)
        {
            //根据消费时间计算消息应该放入的位置
            var second = (int)(time - DateTime.Now).TotalSeconds;
            item.CycleNum = second / queue.Length;
            item.Slot = (second + currentIndex) % queue.Length;
            //加入到延时队列中
            if (queue[item.Slot] == null)
            {
                queue[item.Slot] = new List<T>();
            }
            queue[item.Slot].Add(item);
        }

        public void Remove(T item)
        {
            if (queue[item.Slot] != null)
            {
                queue[item.Slot].Remove(item);
            }
        }

        public void Read()
        {
            if (queue.Length >= currentIndex)
            {
                var list = queue[currentIndex - 1];
                if (list != null)
                {
                    List<T> target = new List<T>();
                    foreach (var item in list)
                    {
                        if (item.CycleNum == 0)
                        {
                            //在本轮命中,用单独线程去执行业务操作
                            Task.Run(()=> { item.Callback(item); });
                            target.Add(item);
                        }
                        else
                        {
                            //等下一轮
                            item.CycleNum--;
                            System.Diagnostics.Debug.WriteLine($"@@@@@索引:{item.Slot},剩余:{item.CycleNum}");
                        }
                    }
                    //把已过期的移除掉
                    foreach (var item in target)
                    {
                        list.Remove(item);
                    }
                }
                currentIndex++;
                //下一遍从头开始
                if (currentIndex > queue.Length)
                {
                    currentIndex = 1;
                }
            }
        }
    }

接下去是采用办法。

开创一个管制体系实例的静态类,里面封装对队列的操作:

    public static class NotifyPlanManager
    {
        private static DelayQueue<NotifyPlan> _queue = new DelayQueue<NotifyPlan>(60);

        public static void Insert(NotifyPlan plan, DateTime time)
        {
            _queue.Insert(plan, time);
        }

        public static void Read()
        {
            _queue.Read();
        }
    }

营造大家的实际上业务参数类,派生自DelayQueueParam:

    public class NotifyPlan : DelayQueueParam
    {
        public Guid CamId { get; set; }

        public int PreviousTotal { get; set; }

        public int Amount { get; set; }
    }

生儿育女端往队列中插入数据:

    Action<object> callback = (result) =>
    {
        var np = result as NotifyPlan;
        //这里做自己的业务操作
        //举个例子:
        Debug.WriteLine($"活动ID:{np.CamId},已发送数量:{np.PreviousTotal},本次发送数量:{np.Amount}");
    };
    NotifyPlanManager.Insert(new NotifyPlan
    {
        Amount = set.MainAmount,
        CamId = camId,
        PreviousTotal = 0,
        Callback = callback
    }, smsTemplate.SendDate);

再创立一个每秒执行一回的定时器用做消费端,我那里运用的是FluentScheduler,大旨代码:

    internal class NotifyPlanJob : IJob
    {
        /// <summary>
        /// 执行计划
        /// </summary>
        public void Execute()
        {
            NotifyPlanManager.Read();
        }
    }

    internal class JobFactory : Registry
    {
        public JobFactory()
        {
            //每秒运行一次
            Schedule<NotifyPlanJob >().ToRunEvery(1).Seconds();
        }
    }

  JobManager.Initialize(new JobFactory());

下一场打开调试运行,打开本机的系统时间面板,对着时间看输出结果。亲测有效。

 

那种天气,毫无疑问,正是出去的好时间啊。

原理分析

 那种方案的中坚就是结构一种数据结构,称之为环形队列,但实质上照旧一个数组,加上对它的大循环遍历,达到一种环状的假象。然后再合营定时器,就可以已毕按需延时的功能。上边提到的小说中也介绍了贯彻思路,那里自己利用我的驾驭再进一步详实的解释一下。

咱俩先为那些数组分配一个恒定大小的上空,比如60,每个数组的元素用来存放在任务的汇集。然后打开一个定时器每隔一秒来围观那个数组,扫完一圈刚好是一秒钟。如若提前安装好职分被扫描的圈数(CycleNum)和在数组中的地方(Slot),在刚好扫到数组的Slot地点时,集合里那几个CycleNum为0的天职就是高达触发条件的职责,拉出来做业务操作然后移除掉,其余的把圈数减掉两回,然后留到下次继续扫描,那样就已毕了延时的效果。原理如下图所示:

澳门美高梅手机网站 1

可以看看中间的首借使持筹握算出种种义务所在的岗位以及要求循环的圈数。如若当前时刻为15:20:08,当前围观地方是2,我的任务要在15:22:35以此随时触发,也就是147秒后。那么自己索要循环的圈数就是147/60=2圈,须要被扫描的职责就是(147+2)%60=29的地点。统计好职责的坐标后塞到数组中属于它的地方,然后静静等待被消费就好啊。

 

第三站-韩国街-酷必香

全新鸡肉和年糕组合“Sweety”受捧!,尝下来,没有那么好吃,其实挺一般的,又失误的点了25元可乐鸡,就是加了一杯可乐,性价比也不是很高,有点失望。

可乐鸡

总结

 那种方案的补益是幸免了累累地围观数据库和不需要的政工操作,其余也很便宜控制时间精度。带来的难题是只要web服务卓殊或重启可能会时有发生职责丢失的场馆,我当下的拍卖措施是在数据库中标记任务意况,服务启动时把状态为“排队中”的天职再度加载到行列中等候消费。

以上方案在单机环境测试没难题,多节点景况下暂时并未追究。若有陈设性完结上的短处,欢迎钻探与指正,如果有更好的方案,那就当投砾引珠,再好不过了~

 

 

首先站-大婶婆卤肉饭

大婶婆卤肉饭,在东京(Tokyo)正如久的一间浙江小吃料理店,来自新浪上的引进,在虹井路797号(近日喀则西路),客车十号线巴黎动物园站,再走四回就到了,味道不错,价格也依然挺管用的,20块为主能吃的科学。本人也吃过不少卤肉饭(譬如永和一把手的卤肉饭),这家店的卤肉有肥有瘦,肥的还广大,不过并不会油腻,好像还有很多分公司,比较失误的是,我点了排骨饭,即便是一大块炸排骨,加上一碗饭,但是卤肉太少,然而瘾,提出我们照旧点一碗小碗的卤肉饭加一个炸排骨,卤肉饭照旧要小碗的才好。

排骨饭

第四站-大韩民国街-多乐之日

蛋糕店什么的突发性真是又以为贵又禁不住诱惑,多乐之日作为南朝鲜的蛋糕店,果然依然又贵。。又美味。奶油号角是那里的标记,奶油好好吃,外皮也很酥化。

面包

奶油号角

出门,外面的天气真不错呢,总觉得像许多年没见过太阳了。

又到了周末,这几天气温骤降,真是个出来的好时刻,来到Hong Kong也有一段时间了,是时候去外边浪一圈了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注