Actor-ES框架:Actor编写-ESGrain与ESRepGrain
ESGrain
生命周期
Ray中ESGrain繼承自Grain擴展了Grain的生命周期。Grain的生命周期參加文檔附錄:1-Grain生命周期-譯注.md
ESGrain重寫了Grain的OnActivateAsync方法。ESGrain的初始化過程如下:
初始化ESGrain中的State
調用ReadSnapshotAsync()讀快照。
如果沒有獲得快照,調用InitState()根據InitState()中代碼初始化ESGrain,InitState()是虛方法,可以被具體的ESGrain重寫,以自定義初始化。
讀取事件庫,重放事件,獲得最新的State。
小技巧:在實際開發中,可以重寫InitState(),在其中根據關系型數據庫中的數據自定義state的初始化。
使用
State
ESGrain的數據存儲在State中,當ESGrain被激活后State數據存儲在內存中,持久化會存儲為快照。定義ESGrain時,需要定義State,實現IState接口,序列化默認使用protocol buffer,State類要添加protocol buffer特性。IState接口定義的是State的基礎部分,即示例中的base部分,base之外的是當前actor需要的要存儲的數據。
示例代碼:
[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傳遞數據,Event編寫請參考Event編寫.md
EventHandles
使用ESGrain引發事件,一般出于兩種考慮:1.傳遞數據到Handler;2.修改State中的數據。修改ESGrain中的數據通過EventHandle中的代碼實現。
使用:
實現IEventHandle
在Apply中實現定義要處理的事件。
示例代碼:
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中的數據存儲在內存中,大量的數據存在State中,在某種角度可以將State看做內存數據庫。
Ray中,修改State的數據要通過EventHandle實現(只有一種方式)。
ESGrain種類
Ray默認提供了MongoESGrain和SqlGrain兩類。
ESGrain<K, S, W>說明:
K:StateId的類型。
S:ESGrain的State。
W:MessageInfo。
完整ESGrain示例
編寫ESGrain時
明確RabbitPub。
明確MongoStorage。
繼承MongoESGrain或SqlGrain。
實現ESGrain接口。
如果需要重寫OnActivateAsync。
編寫感興趣的Actor方法
如果需要發送事件: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默認是主Actor,當單個Actor壓力過大時,可以實現該actor的副本actor,副本actor主要用來處理:1.讀的操作;2.其他非寫的異步操作。
主actor與副本actor之間保持同步的機制:
主actor引發事件,在CoreHandler里將消息傳遞給副本actor,在副本actor里面重放該事件。
主actor與副本actor持久化的是同一個快照庫、事件庫。也會從同一個庫里激活。
生命周期
與主actor類似。
使用
與ESGrain類似,對比如下:
| 明確RabbitPub | 不需要 |
| 明確MongoStorage | 明確MongoStorage |
| 繼承MongoESGrain或SqlGrain | 繼承MongoESRepGrain或SqlRepGrain |
| 實現ESGrain接口 | 自定義的副本Actor接口 |
| 如果需要重寫OnActivateAsync | 如果需要重寫OnActivateAsync |
| 編寫感興趣的Actor方法 | 編寫感興趣的Actor方法 |
| 如果需要發送事件:1.定義事件;2.編寫EventHandler | 不會引發事件 |
示例
[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社區新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結
以上是生活随笔為你收集整理的Actor-ES框架:Actor编写-ESGrain与ESRepGrain的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Actor-ES框架:Ray-Handl
- 下一篇: Actor-ES框架:消息发布器与消息存