C# 扩展Akka.Net
我们使用Akka.net框架在能源领域进行高度扩展的应用 我们使用Akka.net执行各种任务,主要采用以下形式:C# 扩展Akka.Net,c#,akka.net,C#,Akka.net,我们使用Akka.net框架在能源领域进行高度扩展的应用 我们使用Akka.net执行各种任务,主要采用以下形式: var system=ActorSystem.Create("actorSystem"); var props=Props.Create<UpdateActor>(); .WithRouter(new SmallesMailboxPool(100)); var actorRef=system.ActorOf(props,"UpdateAct
var system=ActorSystem.Create("actorSystem");
var props=Props.Create<UpdateActor>();
.WithRouter(new SmallesMailboxPool(100));
var actorRef=system.ActorOf(props,"UpdateActor");
foreach(var timerow in timeRowList)
actorRef.Tell(timerow)
var system=ActorSystem.Create(“ActorSystem”);
var props=props.Create();
.带路由器(新的SmallesMailboxPool(100));
var-actorRef=system.ActorOf(props,“UpdateActor”);
foreach(timeRowList中的var timerow)
actorRef.Tell(timerow)
不幸的是,Akka.net框架在许多情况下伸缩性非常差。
CPU负载仅为12%。
显然,只使用一个线程或几个线程
如何配置Akka.Net以使用多个线程来处理参与者?这是一个有根据的猜测,但如果您使用的是
SmallestMailboxPool
,请记住,它在非阻塞I/O和存储方面的效果非常差
第一件事通常是检查是否没有阻塞操作(如同步I/O,调用asynchmethod().Result
或Thread.Sleep
),这将阻塞当前线程,有效防止其他参与者使用它
另一个问题非常具体到最小的邮箱路由器,它与隐藏和持久参与者有关
藏匿
隐藏是处理多步骤操作的常用方法之一。此模式可以表示为以下模式
公共类MyActor:ActorBase,IWithUnboundedStash
{
公共IStash隐藏{get;set;}
公共接收活动(状态工作单元)=>消息=>
{
开关(信息)
{
箱销:
//隐藏与当前工作无关的所有消息
隐藏。隐藏(消息);
返回true;
案例一已完成:
//当前工作单元完成后,取消搁置挂起的消息
藏起来;
变得(空闲);
返回true;
}
};
公用布尔空闲(对象消息)
{
开关(信息)
{
案例工作:
StartWork(工作状态);
变为(活动(work.State));//以新的行为继续工作
返回true;
违约:
返回false;
}
}
公共bool接收(对象消息)=>空闲(消息);
}
这种情况非常常见,即持续参与者在恢复过程中使用它。问题是,它正在清理邮箱,这给SmallestMailbox
路由器一种错误的感觉,即该参与者的邮箱是空的,而实际上它只是在隐藏所有传入的消息
这也是为什么不应使用
SmallestMailbox
路由器路由支架周围参与者的原因!Tbh。我想不出在任何情况下,将持久参与者放在任何类型的路由器后面都是一个有效的选择。我认为您需要做的是创建一个参与者协调器类,并在其中创建一个参与者列表/字典。然后(据我所知),在你告诉协调员新的更新后,他们应该并行工作
public class UpdateCoordinator : ReceiveActor
{
//all your update referenced
private readonly Dictionary<int, IActorRef> _updates;
public UpdateCoordinator()
{
_updates = new Dictionary<int, IActorRef>();
//create the update reference
Receive<UpdateMessage>(updateMessage =>
{
//add to the list of actors
CreateUpdateReferenceIfNotExists(updateMessage.Identifier);
IActorRef childUpdateRef = _updates[updateMessage.Identifier];
//start your update actor
childUpdateRef.Tell(updateMessage);
});
}
private void CreateUpdateReferenceIfNotExists(int identifier)
{
if (!_updates.ContainsKey(identifier))
{
IActorRef newChildUpdateRef = Context.ActorOf(Props.Create(()=> new UpdateActor(identifier)), $"Update_{identifier}");
_updates.Add(identifier, newChildUpdateRef);
}
}
}
公共类更新协调器:ReceiveActor
{
//您的所有更新都被引用
私人只读字典更新;
公共更新协调器()
{
_更新=新字典();
//创建更新引用
接收(更新消息=>
{
//加入演员名单
CreateUpdateReferenceIfNotExists(updateMessage.Identifier);
IActorRef childUpdateRef=_更新[updateMessage.Identifier];
//启动你的更新演员
childUpdateRef.Tell(updateMessage);
});
}
私有void CreateUpdateReferenceIfNotExists(int标识符)
{
如果(!\u updates.ContainsKey(标识符))
{
IActorRef newChildUpdateRef=Context.ActorOf(Props.Create(()=>newupdateactor(identifier)),$“Update_{identifier}”);
_Add(标识符,newChildUpdateRef);
}
}
}