4,在程序启动前,启动消费者线程
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//在Global的Application_Start事件里单独开启一个消费者线程
Task.Run(OrderConsumer.StartTicketTask);
}
这样程序的运行模式是:用户提交的需求里都会添加到消息队列里去排队处理,程序会依次处理该队列里的内容(当然可以一次取出多条来进行处理,提高效率)。
优点:比上一步快了。
缺点:不够快,而且下单后需要轮询另外一个接口判断是否成功。
第三阶段 反转生产者消费者的角色,把可售产品提前放到队列里,然后让提交的订单来消费队列里的内容
1,创建生产者并且在程序启动前调用其初始化程序
public class ProductForSaleManager
{
/// <summary>
/// 待售商品队列
/// </summary>
public static ConcurrentQueue<int> ProductsForSale = new ConcurrentQueue<int>();
/// <summary>
/// 初始化待售商品队列
/// </summary>
public static void Init()
{
using (RuanMou2020Entities db = new RuanMou2020Entities())
{
db.product.Where(p => p.status == 0).Select(p => p.id).ToList().ForEach(p =>
{
ProductsForSale.Enqueue(p);
});
}
}
}
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//程序启动前,先初始化待售产品消息队列
ProductForSaleManager.Init();
}
}
2,创建消费者
public class OrderController : Controller
{
/// <summary>
/// 下订单
/// </summary>
/// <param name="userName">订单提交者</param>
/// <returns></returns>
public async Task<ContentResult> PlaceOrder(string userName)
{
if (ProductForSaleManager.ProductsForSale.TryDequeue(out int pid))
{
await new TicketHelper2().PlaceOrderDataBase(userName, pid);
return Content($"下单成功,对应产品id为:{pid}");
}
else
{
await Task.CompletedTask;
return Content($"商品已经被抢光");
}
}
}
3,当然还需要一个业务的实际执行者
/// <summary>
/// 订单业务的实际处理者
/// </summary>
public class TicketHelper2
{
/// <summary>
/// 执行复杂的订单操作(如数据库)
/// </summary>
/// <param name="userName">下单用户</param>
/// <param name="pid">产品id</param>
/// <returns></returns>
public async Task PlaceOrderDataBase(string userName, int pid)
{
using (RuanMou2020Entities db = new RuanMou2020Entities())
{
var product = db.product.Where(p => p.id == pid).FirstOrDefault();
if (product != null)
{
product.status = 1;
product.username = userName;
await db.SaveChangesAsync();
}
}
}
}








