当前位置: 首页 > news >正文

电子商务网站建设应用关键词优化搜索排名

电子商务网站建设应用,关键词优化搜索排名,wordpress评论提醒插件,邢台各种类型网站建设售后完善文章目录 原理创建分布式事件总线实现自动订阅和事件转发 使用启动Redis服务配置传递Abp默认事件传递自定义事件 项目地址 原理 本地事件总线是通过Ioc容器来实现的。 IEventBus接口定义了事件总线的基本功能,如注册事件、取消注册事件、触发事件等。 Abp.Events…

文章目录

  • 原理
    • 创建分布式事件总线
    • 实现自动订阅和事件转发
  • 使用
    • 启动Redis服务
    • 配置
    • 传递Abp默认事件
    • 传递自定义事件
  • 项目地址

原理

本地事件总线是通过Ioc容器来实现的。

IEventBus接口定义了事件总线的基本功能,如注册事件、取消注册事件、触发事件等。

Abp.Events.Bus.EventBus是本地事件总线的实现类,其中私有成员ConcurrentDictionary<Type, List<IEventHandlerFactory>> _handlerFactories是事件订阅表。通过维护事件订阅表来实现事件处理器的注册和取消注册。当对应类型的事件触发时,通过订阅表查找所有事件处理器,通过Ioc容器来获取处理器实例,然后通过反射来调用事件处理器的"HandleEvent"方法。

创建分布式事件总线

首先,我们需要一个分布式事件总线中间件,用来将事件从本地事件总线转发到分布式事件总线。常用的中间件有RabbitMQ、Kafka、Redis等。

开源社区已经有实现好的库,本项目参考了 wuyi6216/Abp.RemoteEventBus

这里已经定义好了一个分布式事件总线接口


public interface IDistributedEventBus : IDisposable
{void MessageHandle(string topic, string message);void Publish(IDistributedEventData eventData);void Subscribe(string topic);void Unsubscribe(string topic);void UnsubscribeAll();
}

为了兼容本地事件总线,我们需要定义一个分布式事件总线接口,继承自IEventBus接口。


public interface IMultipleEventBus : IDistributedEventBus, IEventBus
{}

实现自动订阅和事件转发

当注册本地事件时,将订阅分布式事件,事件Topic为类型的字符串表现形式

public IDisposable Register(Type eventType, IEventHandlerFactory factory)
{GetOrCreateHandlerFactories(eventType);List<IEventHandlerFactory> currentLists;if (_handlerFactories.TryGetValue(eventType, out currentLists)){lock (currentLists){if (currentLists.Count == 0){//Register to distributed eventthis.Subscribe(eventType.ToString());}currentLists.Add(factory);}}return new FactoryUnregistrar(this, eventType, factory);
}

创建TriggerRemote,此方法用于将本地事件参数打包成为分布式事件消息payload,并发布该消息

public void TriggerRemote(Type eventType, object eventSource, IEventData eventData)
{var exceptions = new List<Exception>();eventData.EventSource = eventSource;try{var payloadDictionary = new Dictionary<string, object>{{ PayloadKey, eventData }};var distributedeventData = new DistributedEventData(eventType.ToString(), payloadDictionary);Publish(distributedeventData);}catch (Exception ex){exceptions.Add(ex);}if (exceptions.Any()){if (exceptions.Count == 1){exceptions[0].ReThrow();}throw new AggregateException("More than one error has occurred while triggering the event: " + eventType, exceptions);}
}

当触发本地事件时,将消息转发至分布式事件总线。
在Trigger方法中调用TriggerRemote,事件状态回调和事件异常回调将不会被转发。

if (!(typeof(DistributedEventBusEvent) == eventType|| typeof(DistributedEventBusEvent).IsAssignableFrom(eventType)|| typeof(DistributedEventMessageHandleExceptionData) == eventType|| typeof(DistributedEventHandleExceptionData) == eventType))
{if (typeof(DistributedEventArgs) != eventType){TriggerRemote(eventType, eventSource, eventData);}
}

在消费端接收到分布式事件消息时,从Topic中解析类型,转发给本地事件。若此类型在本地事件注册过,则将消息反序列化为本地事件参数,然后触发本地事件。
本地事件处理器将触发最终的处理方法。


public virtual void MessageHandle(string topic, string message)
{Logger.Debug($"Receive message on topic {topic}");try{var eventData = _remoteEventSerializer.Deserialize<DistributedEventData>(message);var eventArgs = new DistributedEventArgs(eventData, topic, message);Trigger(this, new DistributedEventBusHandlingEvent(eventArgs));if (!string.IsNullOrEmpty(eventData.Type)){string pattern = @"(.*?)\[(.*?)\]";Match match = Regex.Match(eventData.Type, pattern);if (match.Success){var type = match.Groups[1].Value;var type2 = match.Groups[2].Value;var localTriggerType = typeFinder.Find(c => c.FullName == type).FirstOrDefault();var genericType = typeFinder.Find(c => c.FullName == type2).FirstOrDefault();if (localTriggerType != null && genericType != null){if (localTriggerType.GetTypeInfo().IsGenericType&& localTriggerType.GetGenericArguments().Length == 1&& !genericType.IsAbstract && !genericType.IsInterface){var localTriggerGenericType = localTriggerType.GetGenericTypeDefinition().MakeGenericType(genericType);if (eventData.Data.TryGetValue(PayloadKey, out var payload)){var payloadObject = (payload as JObject).ToObject(localTriggerGenericType);Trigger(localTriggerGenericType, this, (IEventData)payloadObject);}}}}else{var localTriggerType = typeFinder.Find(c => c.FullName == eventData.Type).FirstOrDefault();if (localTriggerType != null && !localTriggerType.IsAbstract && !localTriggerType.IsInterface){if (eventData.Data.TryGetValue(PayloadKey, out var payload)){var payloadObject = (payload as JObject).ToObject(localTriggerType);Trigger(localTriggerType, this, (IEventData)payloadObject);}}}Trigger(this, new DistributedEventBusHandledEvent(eventArgs));}}catch (Exception ex){Logger.Error("Consume remote message exception", ex);Trigger(this, new DistributedEventMessageHandleExceptionData(ex, topic, topic));}
}

使用

DistributedEventBus有不同的实现方式,这里以Redis为例

启动Redis服务

下载Redis并启动服务,使用默认端口6379

配置

生产者和消费者端都需要配置分布式事件总线

首先引用Abp.DistributedEventBus.Redis,并配置Abp模块依赖

[DependsOn(typeof(AbpDistributedEventBusRedisModule))]

在PreInitialize方法中配置Redis连接信息

 Configuration.Modules.DistributedEventBus().UseRedis().Configure(setting =>{setting.Server = "127.0.0.1:6379";});

用MultipleEventBus替换Abp默认事件总线

 //todo: 事件总线Configuration.ReplaceService(typeof(IEventBus),() => IocManager.IocContainer.Register(Component.For<IEventBus>().ImplementedBy<MultipleEventBus>()));

传递Abp默认事件

我们知道在使用仓储时,Abp会自动触发一些事件,如创建、更新、删除等。我们来测试这些事件是否能通过分布式事件总线来传递。

定义一个实体类,用于传递实体的增删改事件。


public class Person : FullAuditedEntity<int>
{public string Name { get; set; }public int Age { get; set; }public string PhoneNumber { get; set; }}

在消费者端,定义一个事件处理器,用于处理实体的增删改事件。


public class RemoteEntityChangedEventHandler :IEventHandler<EntityUpdatedEventData<Person>>,IEventHandler<EntityCreatedEventData<Person>>,IEventHandler<EntityDeletedEventData<Person>>,ITransientDependency
{void IEventHandler<EntityUpdatedEventData<Person>>.HandleEvent(EntityUpdatedEventData<Person> eventData){var person = eventData.Entity;Console.WriteLine($"Remote Entity Updated - Name:{person.Name}, Age:{person.Age}, PhoneNumber:{person.PhoneNumber}");}void IEventHandler<EntityCreatedEventData<Person>>.HandleEvent(EntityCreatedEventData<Person> eventData){var person = eventData.Entity;Console.WriteLine($"Remote Entity Created - Name:{person.Name}, Age:{person.Age}, PhoneNumber:{person.PhoneNumber}");}void IEventHandler<EntityDeletedEventData<Person>>.HandleEvent(EntityDeletedEventData<Person> eventData){var person = eventData.Entity;Console.WriteLine($"Remote Entity Deleted - Name:{person.Name}, Age:{person.Age}, PhoneNumber:{person.PhoneNumber}");}
}

在生产者端,用IRepository对实体进行增删改操作。


var person = new Person()
{Name = "John",Age = 36,PhoneNumber = "18588888888"};personRepository.Insert(person);var person2 = new Person()
{Name = "John2",Age = 36,PhoneNumber = "18588888889"};
personRepository.Insert(person2);var persons = personRepository.GetAllList();
foreach (var p in persons)
{p.Age += 1;personRepository.Update(p);Console.WriteLine($"Entity Updated - Name:{p.Name}, Age:{p.Age}, PhoneNumber:{p.PhoneNumber}");}
foreach (var p in persons)
{personRepository.Delete(p);Console.WriteLine($"Entity Deleted - Name:{p.Name}, Age:{p.Age}, PhoneNumber:{p.PhoneNumber}");}

运行程序(同时运行消费者端和生产者端),可以看到消费者端打印出了实体的增删改事件。

在这里插入图片描述

注意:

分布式事件总线在两个独立系统间传递事件,所以需要定义一个共同的类型对象,用于事件参数的传递。
因此消费者端需要引用生产者端的模块,以便获取共同的类型对象。

public override Assembly[] GetAdditionalAssemblies()
{var clientModuleAssembly = typeof(Person).GetAssembly();return [clientModuleAssembly];
}

传递自定义事件

定义NotificationEventData,用于传递自定义事件。


public class NotificationEventData : EventData
{public int Id { get; set; }public string Title { get; set; }public string Message { get; set; }public bool IsRead { get; set; }
}

在消费者端,定义一个事件处理器,用于处理自定义事件。

public class NotificationEventHandler :IEventHandler<NotificationEventData>,      ITransientDependency
{void IEventHandler<NotificationEventData>.HandleEvent(NotificationEventData eventData){Console.WriteLine($"Id: {eventData.Id}");Console.WriteLine($"Title: {eventData.Title}");Console.WriteLine($"Message: {eventData.Message}");Console.WriteLine($"IsRead: {eventData.IsRead}");}
}

在生产者端,触发自定义事件。

var eventBus = IocManager.Instance.Resolve<IEventBus>();eventBus.Trigger<NotificationEventData>(new NotificationEventData()
{Title = "Hi",Message = "Customized definition event test!",Id = 100,IsRead = true,
});

运行程序(同时运行消费者端和生产者端),可以看到消费者端打印出了自定义事件。

在这里插入图片描述

项目地址

Github:DistributedEventBus


文章转载自:
http://dinncostirpiculture.zfyr.cn
http://dinncosexisyllable.zfyr.cn
http://dinncoclasslist.zfyr.cn
http://dinncocatecholaminergic.zfyr.cn
http://dinncoinformative.zfyr.cn
http://dinncobillbug.zfyr.cn
http://dinncofaintingly.zfyr.cn
http://dinncodiurnally.zfyr.cn
http://dinncoshrank.zfyr.cn
http://dinncomesenchymatous.zfyr.cn
http://dinncotamarind.zfyr.cn
http://dinncofogyish.zfyr.cn
http://dinncoretranslate.zfyr.cn
http://dinncojizz.zfyr.cn
http://dinncoappraise.zfyr.cn
http://dinncoshunpike.zfyr.cn
http://dinncosunblasted.zfyr.cn
http://dinncokoine.zfyr.cn
http://dinncomillimicro.zfyr.cn
http://dinncocircumscribe.zfyr.cn
http://dinncosealing.zfyr.cn
http://dinncovoronezh.zfyr.cn
http://dinncoshufty.zfyr.cn
http://dinncomanganous.zfyr.cn
http://dinncocuchifrito.zfyr.cn
http://dinncosurveillance.zfyr.cn
http://dinnconeophyte.zfyr.cn
http://dinncoevangelize.zfyr.cn
http://dinncosweptback.zfyr.cn
http://dinncodemisemi.zfyr.cn
http://dinncoantiauthoritarian.zfyr.cn
http://dinncoautarchist.zfyr.cn
http://dinncoperiproct.zfyr.cn
http://dinncosetenant.zfyr.cn
http://dinncobhang.zfyr.cn
http://dinncoconformity.zfyr.cn
http://dinncowinepress.zfyr.cn
http://dinncodecoy.zfyr.cn
http://dinncopetechia.zfyr.cn
http://dinncomonitor.zfyr.cn
http://dinncovacuity.zfyr.cn
http://dinncoinstrumentality.zfyr.cn
http://dinncoxf.zfyr.cn
http://dinncokosciusko.zfyr.cn
http://dinncoheuchera.zfyr.cn
http://dinncoheteronuclear.zfyr.cn
http://dinncovalorize.zfyr.cn
http://dinncopleochroism.zfyr.cn
http://dinncoourselves.zfyr.cn
http://dinncocinematograph.zfyr.cn
http://dinncobriefs.zfyr.cn
http://dinncomicrolithic.zfyr.cn
http://dinncosociability.zfyr.cn
http://dinncohibernacle.zfyr.cn
http://dinncopeel.zfyr.cn
http://dinncomineable.zfyr.cn
http://dinncosuddenness.zfyr.cn
http://dinncoraisonne.zfyr.cn
http://dinncoaih.zfyr.cn
http://dinnconotary.zfyr.cn
http://dinncolongness.zfyr.cn
http://dinncocrack.zfyr.cn
http://dinncomuscalure.zfyr.cn
http://dinncopigeonite.zfyr.cn
http://dinncochoplogical.zfyr.cn
http://dinncomicrogametocyte.zfyr.cn
http://dinncogenocidist.zfyr.cn
http://dinncoratan.zfyr.cn
http://dinncoeasiness.zfyr.cn
http://dinncodeceased.zfyr.cn
http://dinncoadder.zfyr.cn
http://dinncoflippant.zfyr.cn
http://dinncopygmy.zfyr.cn
http://dinncoelectrothermics.zfyr.cn
http://dinncoroscoe.zfyr.cn
http://dinncoenterologist.zfyr.cn
http://dinncosabina.zfyr.cn
http://dinncoecclesiasticism.zfyr.cn
http://dinncordx.zfyr.cn
http://dinncoparthenogenetic.zfyr.cn
http://dinncomortally.zfyr.cn
http://dinncononstarter.zfyr.cn
http://dinncomonaker.zfyr.cn
http://dinncowildwood.zfyr.cn
http://dinncophotoproduct.zfyr.cn
http://dinncounrivaled.zfyr.cn
http://dinncoshankpiece.zfyr.cn
http://dinncodelicate.zfyr.cn
http://dinncokaisership.zfyr.cn
http://dinncoborax.zfyr.cn
http://dinncosafranin.zfyr.cn
http://dinncoreformism.zfyr.cn
http://dinncoorthotics.zfyr.cn
http://dinncolithospermum.zfyr.cn
http://dinncolawlike.zfyr.cn
http://dinncoerasmus.zfyr.cn
http://dinnconationalization.zfyr.cn
http://dinncocolorize.zfyr.cn
http://dinncocancerization.zfyr.cn
http://dinncoqos.zfyr.cn
http://www.dinnco.com/news/129022.html

相关文章:

  • 网站搜索下拉是怎么做的怎样做竞价推广
  • 35互联做网站好吗seo优化公司信
  • 做律师百度推广的网站网站推广去哪家比较好
  • 十种网络营销的方法合肥seo快排扣费
  • node.js做的网站广州seo推广公司
  • 阿里云盘资源搜索引擎郑州seo技术外包
  • 网站开发案例分析中视频自媒体平台注册
  • 单页网站制作程序模板建网站价格
  • 婺源做网站南宁seo结算
  • 涪城移动网站建设网页设计网站
  • 建网站流程游戏广告投放平台
  • 嘉兴模板建站系统公关公司经营范围
  • 网站备案 名称 不一致有什么引流客源的软件
  • 免费的企业网站建设流程百度站长工具排名
  • 做买衣服的网站免费手机优化大师下载安装
  • 做代理哪个网站靠谱优化大师平台
  • 汕头网站备案网上售卖平台有哪些
  • 北京的重要的网站小熊猫seo博客
  • ui设计30岁后的出路seo关键字排名
  • 做百度网站优化多少钱官网seo关键词排名系统
  • wordpress 小说网站seo优化的搜索排名影响因素主要有
  • 对自己做的网站总结厦门头条今日新闻
  • 网络规划设计师自学能通过么郑州优化网站关键词
  • 苏州注册公司一站式网站生成器
  • 公司网站建设的分类解封后中国死了多少人
  • 运输网站建设宁波网站推广优化哪家正规
  • wordpress浏览器版本seo工具下载
  • 公司介绍网站怎么做aso优化平台
  • wordpress建站赚钱东莞网站营销推广
  • 舒城县建设局网站首页广州百度推广电话