From 1faff966385212227bd94b03d0dafd9d90ecf208 Mon Sep 17 00:00:00 2001 From: zuohuaijun Date: Thu, 18 Jul 2024 17:48:15 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=98=8E=E5=A2=9E=E5=8A=A0=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E6=80=BB=E7=BA=BF=E5=B9=BF=E6=92=AD=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventBus/RedisEventSourceStorer.cs | 81 +++++++++++++------ 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs index 272b5ba1..475bdf41 100644 --- a/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs +++ b/Admin.NET/Admin.NET.Core/EventBus/RedisEventSourceStorer.cs @@ -4,6 +4,8 @@ // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! +using NewLife.Caching.Queues; +using Newtonsoft.Json; using System.Threading.Channels; namespace Admin.NET.Core; @@ -11,6 +13,12 @@ namespace Admin.NET.Core; /// /// Redis自定义事件源存储器 /// +/// +/// 在集群部署时,一般每一个消息只由一个服务节点消费一次。 +/// 有些特殊情情要通知到服务器群中的每一个节点(比如需要强制加载某些配置、重点服务等), +/// 在这种情况下就要以“broadcast:”开头来定义EventId, +/// 本系统会把“broadcast:”开头的事件视为“广播消息”保证集群中的每一个服务节点都能消费得到这个消息 +/// public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable { /// @@ -23,11 +31,9 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable /// private readonly Channel _channel; - ///// - ///// Redis 连接对象 - ///// - //private readonly FullRedis _redis; - private IProducerConsumer _queue; + private IProducerConsumer _queueSingle; + + private RedisStream _queueBroadcast; /// /// 路由键 @@ -54,24 +60,48 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable //_redis = redis as FullRedis; _routeKey = routeKey; - // 创建消息订阅者 - _queue = cacheProvider.GetQueue(routeKey); - _eventConsumer = new EventConsumer(_queue); + // 创建广播消息订阅者,即所有服务器节点都能收到消息(用来发布重启、Reload配置等消息) + FullRedis redis = (FullRedis)cacheProvider.Cache; + var clusterOpt = App.GetConfig("Cluster", true); + _queueBroadcast = redis.GetStream(routeKey + ":broadcast"); + _queueBroadcast.Group = clusterOpt.ServerId;//根据服务器标识分配到不同的分组里 + _queueBroadcast.Expire = TimeSpan.FromSeconds(10);//消息10秒过期() + _queueBroadcast.ConsumeAsync(OnConsumeBroadcast); + + // 创建队列消息订阅者,只要有一个服务节点消费了消息即可 + _queueSingle = redis.GetQueue(routeKey + ":single"); + _eventConsumer = new EventConsumer(_queueSingle); // 订阅消息写入 Channel _eventConsumer.Received += (send, cr) => { - // 反序列化消息 - //var eventSource = JsonConvert.DeserializeObject(cr); - - // 写入内存管道存储器 - _channel.Writer.WriteAsync(cr); + var oriColor = Console.ForegroundColor; + ChannelEventSource ces = (ChannelEventSource)cr; + ConsumeChannelEventSource(ces); }; - - // 启动消费者 _eventConsumer.Start(); } + private Task OnConsumeBroadcast(string source, Message message, CancellationToken token) + { + ChannelEventSource ces = JsonConvert.DeserializeObject(source); + ConsumeChannelEventSource(ces); + return Task.CompletedTask; + } + + private void ConsumeChannelEventSource(ChannelEventSource ces) + { + // 打印测试事件 + if (ces.EventId != null && ces.EventId.IndexOf(":Test") > 0) + { + var oriColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine($"有消息要处理{ces.EventId},{ces.Payload}"); + Console.ForegroundColor = oriColor; + } + _channel.Writer.WriteAsync(ces); + } + /// /// 将事件源写入存储器 /// @@ -82,29 +112,28 @@ public sealed class RedisEventSourceStorer : IEventSourceStorer, IDisposable { // 空检查 if (eventSource == default) - { throw new ArgumentNullException(nameof(eventSource)); - } // 这里判断是否是 ChannelEventSource 或者 自定义的 EventSource if (eventSource is ChannelEventSource source) { - // 序列化消息 - //var data = JsonSerializer.Serialize(source); - - //// 获取一个订阅对象 - //var queue = _redis.GetQueue(_routeKey); - // 异步发布 await Task.Factory.StartNew(() => { - //queue.Add(source); - _queue.Add(source); + if (source.EventId != null && source.EventId.StartsWith("broadcast:")) + { + string str = JsonConvert.SerializeObject(source); + _queueBroadcast.Add(str); + } + else + { + _queueSingle.Add(source); + } }, cancellationToken, TaskCreationOptions.LongRunning, System.Threading.Tasks.TaskScheduler.Default); } else { - // 这里处理动态订阅问题 + // 处理动态订阅问题 await _channel.Writer.WriteAsync(eventSource, cancellationToken); } } From ac630a2d075efc597a74e0be15f93f60fb2b9f13 Mon Sep 17 00:00:00 2001 From: zuohuaijun Date: Thu, 18 Jul 2024 17:49:22 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=98=8E=E4=BC=98=E5=8C=96=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs index b621a55a..7d684e28 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs @@ -380,7 +380,7 @@ public static class SqlSugarSetup .Where(u => !u.GetCustomAttributes().Any()) .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(SugarTable), false) && !u.IsDefined(typeof(SysTableAttribute), false) && !u.IsDefined(typeof(LogTableAttribute), false) && !u.IsDefined(typeof(TenantAttribute), false)).ToList(); - if (!entityTypes.Any()) return; + if (entityTypes.Count == 0) return; foreach (var entityType in entityTypes) { From d6cbbee1e0e884baaea991a2e2c4301fee2b0af8 Mon Sep 17 00:00:00 2001 From: zuohuaijun Date: Thu, 18 Jul 2024 17:59:01 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=98=8E=E5=88=A0=E9=99=A4=E5=A4=9A?= =?UTF-8?q?=E4=BD=99=E7=9A=84=E8=B0=83=E8=AF=95=E5=92=8C=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Web/src/views/home/widgets/components/schedule.vue | 1 - Web/src/views/home/widgets/components/scheduleEdit.vue | 2 -- Web/src/views/system/print/component/hiprint/preview.vue | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Web/src/views/home/widgets/components/schedule.vue b/Web/src/views/home/widgets/components/schedule.vue index f6f2535a..2437c671 100644 --- a/Web/src/views/home/widgets/components/schedule.vue +++ b/Web/src/views/home/widgets/components/schedule.vue @@ -78,7 +78,6 @@ onMounted(async () => { // 查询操作 const handleQuery = async () => { - debugger; state.queryParams.startTime = GetMonthFirstDay(state.calendarValue); state.queryParams.endTime = GetMonthLastDay(state.calendarValue); diff --git a/Web/src/views/home/widgets/components/scheduleEdit.vue b/Web/src/views/home/widgets/components/scheduleEdit.vue index 983c55ef..cee9a032 100644 --- a/Web/src/views/home/widgets/components/scheduleEdit.vue +++ b/Web/src/views/home/widgets/components/scheduleEdit.vue @@ -78,8 +78,6 @@ const cancel = () => { // 提交 const submit = () => { - console.log(JSON.stringify(state.ruleForm)); - ruleFormRef.value.validate(async (valid: boolean) => { if (!valid) return; if (state.ruleForm.id != undefined && state.ruleForm.id > 0) { diff --git a/Web/src/views/system/print/component/hiprint/preview.vue b/Web/src/views/system/print/component/hiprint/preview.vue index e453dd22..0cf5aa0a 100644 --- a/Web/src/views/system/print/component/hiprint/preview.vue +++ b/Web/src/views/system/print/component/hiprint/preview.vue @@ -48,7 +48,7 @@ const showDialog = (hiprintTemplate: any, printData: {}, width = 210, printType const print = () => { state.waitShowPrinter = true; - debugger; + // debugger; // 判断是否已成功连接 if (state.printType == 2) { // 注意:连接是异步的 From 25dce06bfdb670a5d4af7787b2fb89dfe26a7dae Mon Sep 17 00:00:00 2001 From: "CAOMEI\\s" Date: Fri, 19 Jul 2024 00:36:31 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AFindex.v?= =?UTF-8?q?ue=E5=AD=97=E5=85=B8=E4=BD=BF=E7=94=A8value=E5=80=BC=E4=B8=BA?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=80=BC=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm index 8eb33055..1877b132 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/index.vue.vm @@ -53,7 +53,7 @@ - + @@ -194,7 +194,7 @@ import { Local } from '/@@/utils/storage'; @:import { codeToName, getConstType } from "/@@/utils/constHelper"; } @if(@Model.TableField.Any(x=>x.EffectType == "Select") || @Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ -@:import { getDictDataItem as di, getDictDataList as dl } from '/@@/utils/dict-utils'; +@:import { getDictLabelByVal as di, getDictDataList as dl } from '/@@/utils/dict-utils'; } @if(@Model.TableField.Any(x=>x.EffectType == "EnumSelector")){ @:import { getDictLabelByVal as dv } from '/@@/utils/dict-utils'; @@ -313,7 +313,7 @@ const options = useVxeTable<@(@Model.ClassName)>( // 工具栏配置 toolbarConfig: { export: false }, // 行设置 - rowConfig: { height: 80 }, + // rowConfig: { height: 80 }, } ); From 57d6bbd874a0c9395321441fe946959c0f6f6c74 Mon Sep 17 00:00:00 2001 From: "CAOMEI\\s" Date: Fri, 19 Jul 2024 00:45:26 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E7=BC=96=E8=BE=91=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E4=B8=8B=E6=8B=89=E6=A1=86=E6=98=BE=E7=A4=BA?= =?UTF-8?q?name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm index 83b5d7df..21874350 100644 --- a/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm +++ b/Admin.NET/Admin.NET.Web.Entry/wwwroot/Template/editDialog.vue.vm @@ -78,7 +78,7 @@ @: @: @: - @: + @: @: @: