背景:在实际的项目中,经常有客户需要做抽奖的活动,大部分的都是注册送产品、送红包这些需求。这都是有直接的利益效果,所以经常会遇见系统被盗刷的情况,每一次遇见这种项目的上线都是绷紧神经,客户又都喜欢在过节的时候上这种活动,有好多次放假前夕都是在解决这种事情,甚至有一次的活动短信接口直接被恶意刷爆了。在这种恶意请求下对系统并发性要求就很高,但是即使做多方面的完善,有一个问题始终得不到根本的解决,那就是奖品池数量的控制,总是会出现超兑,或者一个奖品被多个人兑走的问题。之后尝试了多种及方法,例如:限制IP,限制次数等等。后来最有效的解决方法就是使用Redis锁住奖品逻辑,但是这种实现有点复杂,也不是很友好,因此就想到了使用消息队列的优势来实现此功能。
做这个示例首先是为了学习,再者也是留下学习的笔记,不然后面又遗忘掉了
这个示例是一边学习RabbitMQ,一边实现自己的需求功能的。主要功能有【投放奖品】、【模拟多户请求】、【模拟用户抽奖】,并且在这些操作中及时的展示各个队列中数据的数量变化,先上一张效果图:
示例测试下来,始终能保证奖品的数量与实际的中奖人数是一致的,不会多出一个中奖人,也不会出现有多个人中同一个奖品的问题。
实现方式主要就是多线程模拟用户请求,结合RabbitMQ,其中还是用了RabbitMQ的在线API进行数据的监控展示。
实现思路:
1:先将奖品丢入奖品池;
1 #region 投放奖品 2 /// <summary> 3 /// 投放奖品 4 /// </summary> 5 /// <param name="sender"></param> 6 /// <param name="e"></param> 7 private void btn1_Click(object sender, EventArgs e) 8 { 9 try 10 { 11 SetSendfigModel(PrizeQueueName); //设置队列信息(奖品池) 12 new Thread(SetPrize) { IsBackground = true }.Start(); 13 } 14 catch (Exception ex) 15 { 16 MessageBox.Show(ex.Message, "出错了", MessageBoxButtons.OK); 17 } 18 } 19 20 /// <summary> 21 /// 22 /// </summary> 23 private void SetPrize() 24 { 25 string value = string.Empty; 26 for (int i = 1; i <= PrizeCount; i++) 27 { 28 PrizeInfo prize = new PrizeInfo 29 { 30 Id = i, 31 Name = "我是奖品" + i, 32 Type = 1, 33 PrizeNo = DateTime.Now.ToString("hhmmssfff"), 34 Total = PrizeCount, 35 Balance = PrizeCount 36 }; 37 value = JsonConvert.SerializeObject(prize); 38 RabbitSend.Send(prize); 39 ShowSysMessage($"我骄傲,我是奖品:{i}/{PrizeCount}"); 40 } 41 ShowSysMessage("奖品投放完成"); 42 } 43 #endregion