Actor-ES框架:Actor编写-ESGrain与ESRepGrain
ESGrain
生命周期
Ray中ESGrain繼承自Grain擴(kuò)展了Grain的生命周期。Grain的生命周期參加文檔附錄:1-Grain生命周期-譯注.md
ESGrain重寫了Grain的OnActivateAsync方法。ESGrain的初始化過程如下:
初始化ESGrain中的State
調(diào)用ReadSnapshotAsync()讀快照。
如果沒有獲得快照,調(diào)用InitState()根據(jù)InitState()中代碼初始化ESGrain,InitState()是虛方法,可以被具體的ESGrain重寫,以自定義初始化。
讀取事件庫,重放事件,獲得最新的State。
小技巧:在實(shí)際開發(fā)中,可以重寫InitState(),在其中根據(jù)關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)自定義state的初始化。
使用
State
ESGrain的數(shù)據(jù)存儲在State中,當(dāng)ESGrain被激活后State數(shù)據(jù)存儲在內(nèi)存中,持久化會存儲為快照。定義ESGrain時(shí),需要定義State,實(shí)現(xiàn)IState接口,序列化默認(rèn)使用protocol buffer,State類要添加protocol buffer特性。IState接口定義的是State的基礎(chǔ)部分,即示例中的base部分,base之外的是當(dāng)前actor需要的要存儲的數(shù)據(jù)。
示例代碼:
[ProtoContract(ImplicitFields = ImplicitFields.AllFields)] public class AccountState : IState<string> { ? ? #region base ? ? public string StateId { get; set; } ? ? public uint Version { get; set; } ? ? public uint DoingVersion { get; set; } ? ? public DateTime VersionTime { get; set; } ? ? #endregion ? ? public decimal Balance { get; set; } }
Event
ESGrain之間通過Event傳遞數(shù)據(jù),Event編寫請參考Event編寫.md
EventHandles
使用ESGrain引發(fā)事件,一般出于兩種考慮:1.傳遞數(shù)據(jù)到Handler;2.修改State中的數(shù)據(jù)。修改ESGrain中的數(shù)據(jù)通過EventHandle中的代碼實(shí)現(xiàn)。
使用:
實(shí)現(xiàn)IEventHandle
在Apply中實(shí)現(xiàn)定義要處理的事件。
示例代碼:
public class AccountEventHandle : IEventHandle
{
? public void Apply(object state, IEvent evt)
? {
? ? ? if (state is AccountState actorState)
? ? ? {
? ? ? ? ? switch (evt)
? ? ? ? ? {
? ? ? ? ? ? ? case AmountAddEvent value: AmountAddEventHandle(actorState, value); break;
? ? ? ? ? ? ? case AmountTransferEvent value: AmountTransferEventHandle(actorState, value); break;
? ? ? ? ? ? ? default: break;
? ? ? ? ? }
? ? ? }
? }
? private void AmountTransferEventHandle(AccountState state, AmountTransferEvent evt)
? {
? ? ? state.Balance = evt.Balance;
? }
? private void AmountAddEventHandle(AccountState state, AmountAddEvent evt)
? {
? ? ? state.Balance = evt.Balance;
? }
}
State中的數(shù)據(jù)存儲在內(nèi)存中,大量的數(shù)據(jù)存在State中,在某種角度可以將State看做內(nèi)存數(shù)據(jù)庫。
Ray中,修改State的數(shù)據(jù)要通過EventHandle實(shí)現(xiàn)(只有一種方式)。
ESGrain種類
Ray默認(rèn)提供了MongoESGrain和SqlGrain兩類。
ESGrain<K, S, W>說明:
K:StateId的類型。
S:ESGrain的State。
W:MessageInfo。
完整ESGrain示例
編寫ESGrain時(shí)
明確RabbitPub。
明確MongoStorage。
繼承MongoESGrain或SqlGrain。
實(shí)現(xiàn)ESGrain接口。
如果需要重寫OnActivateAsync。
編寫感興趣的Actor方法
如果需要發(fā)送事件:1.定義事件;2.編寫EventHandler。
[RabbitMQ.RabbitPub("Account", "account")]
[MongoStorage("Test", "Account")]
public sealed class Account : MongoESGrain<String, AccountState, IGrains.MessageInfo>, IAccount
{
? ? protected override string GrainId => this.GetPrimaryKeyString();
? ? static IEventHandle _eventHandle = new AccountEventHandle();
? ? protected override IEventHandle EventHandle => _eventHandle;
? ? public override Task OnActivateAsync()
? ? {
? ? ? ? return base.OnActivateAsync();
? ? }
? ? public Task Transfer(string toAccountId, decimal amount)
? ? {
? ? ? ? var evt = new AmountTransferEvent(toAccountId, amount, this.State.Balance - amount);
? ? ? ? return RaiseEvent(evt).AsTask();
? ? }
? ? public Task AddAmount(decimal amount, string uniqueId = null)
? ? {
? ? ? ? var evt = new AmountAddEvent(amount, this.State.Balance + amount);
? ? ? ? return RaiseEvent(evt, uniqueId: uniqueId).AsTask();
? ? }
? ? [AlwaysInterleave]
? ? public Task<decimal> GetBalance()
? ? {
? ? ? ? return Task.FromResult(this.State.Balance);
? ? }
}
ESRepGrain
ESGrain默認(rèn)是主Actor,當(dāng)單個(gè)Actor壓力過大時(shí),可以實(shí)現(xiàn)該actor的副本actor,副本actor主要用來處理:1.讀的操作;2.其他非寫的異步操作。
主actor與副本actor之間保持同步的機(jī)制:
主actor引發(fā)事件,在CoreHandler里將消息傳遞給副本actor,在副本actor里面重放該事件。
主actor與副本actor持久化的是同一個(gè)快照庫、事件庫。也會從同一個(gè)庫里激活。
生命周期
與主actor類似。
使用
與ESGrain類似,對比如下:
| 明確RabbitPub | 不需要 |
| 明確MongoStorage | 明確MongoStorage |
| 繼承MongoESGrain或SqlGrain | 繼承MongoESRepGrain或SqlRepGrain |
| 實(shí)現(xiàn)ESGrain接口 | 自定義的副本Actor接口 |
| 如果需要重寫OnActivateAsync | 如果需要重寫OnActivateAsync |
| 編寫感興趣的Actor方法 | 編寫感興趣的Actor方法 |
| 如果需要發(fā)送事件:1.定義事件;2.編寫EventHandler | 不會引發(fā)事件 |
示例
[MongoStorage("Test", "Account")]
public sealed class AccountRep : MongoESRepGrain<String, AccountState, MessageInfo>, IAccountRep
{
? ? ?protected override string GrainId => this.GetPrimaryKeyString();
? ? ?static IEventHandle _eventHandle = new AccountEventHandle();
? ? ?protected override IEventHandle EventHandle => _eventHandle;
? ? ?public Task<decimal> GetBalance()
? ? ?{
? ? ? ? ?return Task.FromResult(this.State.Balance);
? ? ?}
}
原文地址:http://www.cnblogs.com/CharlesZHENG/p/8438057.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的Actor-ES框架:Actor编写-ESGrain与ESRepGrain的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Actor-ES框架:Ray-Handl
- 下一篇: Actor-ES框架:消息发布器与消息存