微信企业号如何在十分钟内发送一万个红包

10 篇文章 0 订阅
8 篇文章 0 订阅

最近接到的项目是在公司年会将有一个摇红包的环节,公司共有一千人,每人可以领取十个红包。这对于程序来说是一个不小的压力吧,活动已经结束,效果很好。下面我来分享下我们Java后端采用的基本设计。


总体设计思路是: 多线程 + 并发队列 + 数据库(尽可能与微信少交互)


	@WesApi
	@RequestMapping(value = "/pay/bonusThread", method = RequestMethod.POST)
	public String BonusAsync(@RequestBody String wxBody) throws Exception {
		long time1 = System.currentTimeMillis();
		logger.info("**********1*****************get body current time***************" + time1);
		queue.offer(wxBody);
		long time2 = System.currentTimeMillis();
		WesBonusController.writeTime = time2;
		logger.info("**********2*****************offer queue time ******************" + (time2-time1));
		return "{\"return_code\":\"SUCCESS\"}";
	}


真正的API 只有上面一个,原因很简单,在各位打开企业号开始摇红包那个过程,前端的访问压力非常的大,所以后端不可能进行同步代码执行,因此我们的设计理念是每当前端post数据给后端时,API只做两件事情 1、放入队列 2、返回JSON字符串。


前面说到我们会采用多线程来开发,那么很显然需要一个线程来处理队列中的数据。所以我们在Spring boot开启时就会注入线程。

	@Bean
	public BonusThread returnBonusThread(){
		thread.start();
		return thread;
	}


线程中的处理代码如下:


	public void run() {
		
		while(true){
			if(!WesBonusController.queue.isEmpty()){
				
				logger.info("**************** queue size**********" +WesBonusController.queue.size());
				String wxBody = WesBonusController.queue.poll();
				
				try {		
					wxBody = URLDecoder.decode(wxBody);
					WxBonus bonus = JsonUtils.jsonStr2Model(wxBody.trim(), WxBonus.class);
					//get current time
					long currentTime = System.currentTimeMillis();
					// check from map time by userId
					String userIdTime = WesBonusController.recodeUserTimeMap.get(bonus.getUserId());
					if("".equals(userIdTime) || null == userIdTime){
						// first
						long getSuccessTime = sendBonus(bonus, wxBody);
						// save time to success current time
						WesBonusController.recodeUserTimeMap.put(bonus.getUserId(), String.valueOf(getSuccessTime));
					}else if((Long.valueOf(userIdTime)+1000*60) < currentTime){
						// can send bonus
						long getSuccessTime = sendBonus(bonus, wxBody);
						// update time to success current time
						WesBonusController.recodeUserTimeMap.remove(bonus.getUserId());
						WesBonusController.recodeUserTimeMap.put(bonus.getUserId(), String.valueOf(getSuccessTime));
					}else if((Long.valueOf(userIdTime)+1000*60) >= currentTime){
						// poll data to queue
						WesBonusController.queue.offer(wxBody);
					}
					

				} catch (Exception e) {
					e.printStackTrace();
				}
			}else{
				try {
					BonusThread.sleep(100);
					sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}


由于需要while(true)因此需要在队列为空的情况下释放CPU压力。


至于怎样发送红包的代码可以参考我之前的微博。需要提下的是,在很大的访问量压力下,切记能将微信返回数据存入数据库的一定要存入数据库(建议Redis), 否则会很大程度影响用户体验。


需要转载此文章需要征得同意。谢谢! 

上海地区有合适的开发工作可以加我。

微信ID: wangyan199366

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值