asp.net通过消息队列处理高并发请求(以抢小米手机为例)

2020-03-22 18:00:45刘景俊

1,创建订单提交入口(生产者)

public class HomeController : Controller
  {

    /// <summary>
    /// 接受订单提交(生产者)
    /// </summary>
    /// <returns></returns>
    public ContentResult PlaceOrderQueen(string userName)
    {
      //直接将请求写入到订单队列
      OrderConsumer.TicketOrders.Enqueue(userName);
      return Content("wait");
    }

    /// <summary>
    /// 查询订单结果
    /// </summary>
    /// <returns></returns>
    public ContentResult PlaceOrderQueenResult(string userName)
    {
      var rel = OrderConsumer.OrderResults.Where(p => p.userName == userName).FirstOrDefault();
      if (rel == null)
      {
        return Content("还在排队中");
      }
      else
      {
        return Content(rel.Result.ToString());
      }
    }
}

2,创建订单处理者(消费者)

/// <summary>
  /// 订单的处理者(消费者)
  /// </summary>
  public class OrderConsumer
  {
    /// <summary>
    /// 订票的消息队列
    /// </summary>
    public static ConcurrentQueue<string> TicketOrders = new ConcurrentQueue<string>();
    /// <summary>
    /// 订单结果消息队列
    /// </summary>
    public static List<OrderResult> OrderResults = new List<OrderResult>();
    /// <summary>
    /// 订单处理
    /// </summary>
    public static void StartTicketTask()
    {
      string userName = null;
      while (true)
      {
        //如果没有订单任务就休息1秒钟
        if (!TicketOrders.TryDequeue(out userName))
        {
          Thread.Sleep(1000);
          continue;
        }
        //执行真实的业务逻辑(如插入数据库)
        bool rel = new TicketHelper().PlaceOrderDataBase(userName);
        //将执行结果写入结果集合
        OrderResults.Add(new OrderResult() { Result = rel, userName = userName });
      }
    }
  }

3,创建订单业务的实际执行者

/// <summary>
  /// 订单业务的实际处理者
  /// </summary>
  public class TicketHelper
  {
    /// <summary>
    /// 实际库存标识
    /// </summary>
    private bool hasStock = true;
    /// <summary>
    /// 执行一个订单到数据库
    /// </summary>
    /// <returns></returns>
    public bool PlaceOrderDataBase(string userName)
    {
      //如果没有了库存,则直接返回false,防止频繁读库
      if (!hasStock)
      {
        return hasStock;
      }
      using (RuanMou2020Entities db = new RuanMou2020Entities())
      {
        var product = db.product.Where(p => p.status == 0).FirstOrDefault();
        if (product == null)
        {
          hasStock = false;
          return false;
        }
        else
        {
          Thread.Sleep(10000);//模拟数据库的效率比较慢,执行插入时间比较久
          product.status = 1;
          product.username = userName;
          db.SaveChanges();
          return true;
        }
      }
    }
  }
  /// <summary>
  /// 订单处理结果实体
  /// </summary>
  public class OrderResult
  {
    public string userName { get; set; }
    public bool Result { get; set; }
  }