.net core 下使用 Kafka 延迟队列(四)

在电商业务中存在一个场景,用户生成订单,超过30分钟,将订单修改未支付,延迟队列就可以解决该场景问题

 

1     public class KafkaTopic
2     {
3         public static string Topic = "create-order";
4 
5         public static string DelayOrderTopic = "order-delay";
6     }

 

 1 /// <summary>
 2         /// 延迟消费消息
 3         /// </summary>
 4         public void DelayReveice()
 5         {
 6             ConsumerConfig consumerConfig = this.CreateConsumerConnection();
 7             consumerConfig.AutoOffsetReset = AutoOffsetReset.Earliest;
 8             consumerConfig.GroupId = "order";//分组为order组
 9                                              //consumerConfig.FetchMinBytes = 170;//批量取:一次最少取多少消息大小
10                                              //consumerConfig.FetchMaxBytes = 3060;//批量取:一次最多取多少消息大小
11             var builder = new ConsumerBuilder<string, string>(consumerConfig);
12             using (var consumer = builder.Build())
13             {
14                 // 1、订阅
15                 consumer.Subscribe(KafkaTopic.DelayOrderTopic);
16                 // 2、偏移量恢复
17                 string redisValue = this._distributedCache.GetString(KafkaTopic.DelayOrderTopic);
18                 int offset = 0;
19                 if (!string.IsNullOrEmpty(redisValue))
20                 {
21                     offset = int.Parse(redisValue);
22                 }
23                 this._distributedCache.SetString(KafkaTopic.DelayOrderTopic, (offset + 1).ToString());
24 
25                 //offset重置
26                 //consumer.Assign(new TopicPartition(KafkaTopic.Topic, new Partition(1)));
27                 consumer.Assign(new TopicPartitionOffset(KafkaTopic.DelayOrderTopic, new Partition(0), offset + 1));
28                 //循环消费消息
29                 while (true)
30                 {
31                     // 1、恢复消息
32                     new Timer((s) =>
33                     {
34                         consumer.Resume(new List<TopicPartition> { new TopicPartition(KafkaTopic.DelayOrderTopic, new Partition(0)) });
35                     }, null, Timeout.Infinite, Timeout.Infinite).Change(60*1000, 60*5000);//5秒之后回复
36 
37                     //Change(int dueTime, int period)
38                     //dueTime:在首次调用回调方法之前要等待多少毫秒。
39                     //    如希望立刻调用回调方法,
40                     //    该参数指定为0即可。
41                     //period:指定了以后每次调用回调方法之前要等待多少毫秒
42                     //    (理解成下一次和本次调用的时间间隔即可)。
43                     //    如果为该参数传递Timeout.Infinite(或者直接写 - 1),
44                     //    线程池线程只调用回调方法一次(那也就没有必要用计时器了)。
45 
46                     // 1.1、消费暂停
47                     consumer.Pause(new List<TopicPartition> { new TopicPartition(KafkaTopic.DelayOrderTopic, new Partition(0)) });
48 
49                     // 2、消费消息
50                     var result = consumer.Consume(); //批量获取消息,根据-----》字节数
51                     try
52                     {
53                         // 2.1、获取偏移量
54                         _logger.LogInformation($"订单消息偏移量:Offset:{result.Offset}");
55                         // 3、业务处理
56                         string key = result.Key;
57                         string value = result.Value;
58                         _logger.LogInformation($"创建商品:Key:{key}");
59                         _logger.LogInformation($"创建商品:Order:{value}");
60                         // redis存储 kafka队列的偏移量
61                         _distributedCache.SetString(KafkaTopic.DelayOrderTopic, result.Offset.Value.ToString());
62                     }
63                     catch (Exception)
64                     {
65 
66                         throw;
67                     }
68                     finally
69                     {
70                         consumer.Pause(new List<TopicPartition> { new TopicPartition(KafkaTopic.DelayOrderTopic, 0) });
71                         Console.WriteLine($"暂停消费");
72                     }
73                 }
74             }
75         }

 

 调用延迟消费

 1 using KafkaCommom;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace KafKaWorker
 9 {
10     public class DelayReveiceWorker : BackgroundService
11     {
12         private readonly ILogger<Worker> _logger;
13         private readonly KafKaSevice _kafKaSevice;
14         public DelayReveiceWorker(ILogger<Worker> logger, KafKaSevice kafKaSevice)
15         {
16             _logger = logger;
17             _kafKaSevice = kafKaSevice;
18         }
19 
20         protected override async Task ExecuteAsync(CancellationToken stoppingToken)
21         {
22             _kafKaSevice.DelayReveice();
23             await Task.CompletedTask;
24         }
25     }
26 }

 

webapi 调用发送消息

 1  /// <summary>
 2         /// 发送消息
 3         /// </summary>
 4         /// <param name="msg"></param>
 5         /// <returns></returns>
 6         [HttpGet]
 7         public string Get(string msg)
 8         {
 9             this._kafKaSevice.Send(msg);
10             return "";
11         }

 

测试消费 现在每隔 1分钟消费一次 做到了延迟消费

 

posted on 2023-01-31 00:33  是水饺不是水饺  阅读(58)  评论(0编辑  收藏  举报

导航