使用netcore 3.1实现简单的商品秒杀活动(一)

1、说明

该项目用于简单的模拟尝试,后期完善实际的秒杀活动,将逻辑做到更深更密。

2、接口

接口也只是简单简单的在内存中插入商品,实际要考虑写入Redis

	[Route("api/[controller]/[action]")]
    [ApiController]
    public class OrderController : ControllerBase
    {
        private readonly IHttpContextAccessor _httpContext;
        public OrderController(IHttpContextAccessor httpContext)
        {
            _httpContext = httpContext;
        }
        //这里模拟redis
        private static IDictionary<string, Product> _product = new Dictionary<string, Product>();


        /// <summary>
        /// 模拟下单
        /// </summary>
        /// <param name="product"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Buy([FromBody]Product product)
        {
            // 登陆
            var user = _httpContext.HttpContext.Request.Headers["Client-Remote-User"].ToString();
            // 模拟库存量为100
            if (_product.Count == 100)
            {
                return Ok(new AjaxRepsone(3));
            }
            if (_product.Keys.Contains(user))
            {
                return Ok(new AjaxRepsone(2));
            }
            // 加入到redis中
            _product.Add(user, product);
            return Ok(new AjaxRepsone(1));
        }

        class AjaxRepsone
        {
            public AjaxRepsone()
            {
                Success = true;
            }
            public AjaxRepsone(int type)
            {
                Type = type;
            }
            /// <summary>
            /// 1-购买成功,2-已经购买,3-被抢光
            /// </summary>
            public int Type { get; set; }
            public bool Success { get; set; }
        }
    }

3、模拟器

并发请求接口

	class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            // 10秒后开始执行
            Thread.Sleep(TimeSpan.FromSeconds(3));
            var build = new HostBuilder()
                .ConfigureServices((hostContext, service) =>
                {
                    service.AddHttpClient();
                    // 这里可以添加服务注册
                    //service.AddTransient<TService, Service>();
                }).UseConsoleLifetime(options =>
                {
                    options.SuppressStatusMessages = true;
                });
            var host = build.Build();
            var api = "http://localhost:5000/api/Order/Buy";
            var now = DateTime.Now;
            using (var serviceScope = host.Services.CreateScope())
            {
                var service = serviceScope.ServiceProvider;
                try
                {
                    // 作用域块中获取服务,我这里用于直接请求接口,就免了
                    var httpClient = service.GetRequiredService<IHttpClientFactory>();
                    var client = httpClient.CreateClient("test");
                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                    var content = new HttpRequestMessage(HttpMethod.Post, new Uri(api));
                    var options = new JsonSerializerOptions
                    {
                        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    };
                    // 哨兵,监控后台是否返回库存为0
                    var flag = 0;
                    // 模拟5W并发请求,查看OPS、TPS峰值
                    for (int i = 1; i <= 5 * 1000; i++)
                    {
                        if (flag == 1)
                        {
                            break;
                        }
                        content.Headers.Clear();
                        //content.Headers.Add("Client-Remote-Any", Guid.NewGuid().ToString("N").ToUpper());
                        content = new HttpRequestMessage(HttpMethod.Post, new Uri(api));
                        var json = JsonSerializer.Serialize(new
                        {
                            Id = i,
                            Name = "",
                            Price = 9900d,
                            XingHao = "Y9000X",
                            Describle = "lenov"
                        });
                        var user = Guid.NewGuid().ToString("N").ToUpper();
                        content.Content = new StringContent(json, Encoding.UTF8, "application/json");
                        content.Content.Headers.TryAddWithoutValidation("Client-Remote-User", user);
                        var response = client.PostAsync(api, content.Content);
                        //var response= client.SendAsync(content);
                        if (response.Result.IsSuccessStatusCode)
                        {
                            var res = response.Result.Content.ReadAsStringAsync().Result;
                            var ajax = JsonSerializer.Deserialize<AjaxRepsone>(res, options);
                            switch (ajax.Type)
                            {
                                case 1:
                                    Console.BackgroundColor = ConsoleColor.Green;
                                    Console.WriteLine($"{user}:抢购成功咯!");
                                    break;
                                case 2:
                                    Console.BackgroundColor = ConsoleColor.Yellow;
                                    Console.WriteLine($"{user}:您已经抢购咯!");
                                    break;
                                case 3:
                                    Console.BackgroundColor = ConsoleColor.Red;
                                    Console.WriteLine($"{user}:被其他抢光咯!");
                                    flag = 1;
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }
            Console.BackgroundColor = ConsoleColor.Blue;
            Console.WriteLine($"=======商品{(DateTime.Now - now).TotalMilliseconds}毫秒抢光啦======");
            Console.ReadLine();
        }
    }
    class AjaxRepsone
    {
        public int Type { get; set; }
        public bool Success { get; set; }
    }

后面尽快完善更切入实际秒杀活动,凭借搜索了解秒杀活动原理,便自己先简单的进行了尝试,当大佬看见时还请多多指教

posted @ 2020-03-03 22:39  Jonny-Xhl  阅读(543)  评论(0编辑  收藏  举报