https://metaplay.io logo
Entity deployment question
# questions-and-feedback
d
hi, i have an persisted entity with the following usage pattern. * low write frequency. only from the liveops dashboard. * high read access I'm currently using these setting: public override IShardingStrategy ShardingStrategy => ShardingStrategies.CreateSingletonService(); public override TimeSpan ShardShutdownTimeout => TimeSpan.FromSeconds(10); public override EntityShardGroup EntityShardGroup => EntityShardGroup.Workloads; public override NodeSetPlacement NodeSetPlacement => NodeSetPlacement.Logic; does this make sense? I'm wondering whether I should use ServicesProxies as EntityShardGroup. Basically ideally i'd like a kind of primary/replica setup. I'm a little concerned about the single threading in a single instance of the entity. Thanks Andre
After writing the question i'm wondering if i should just implement some simple caching in the entities that need the data and refresh every minute or something similar.
j
> Shard settings, does this make sense? They seem sensible. One tweak could be to move the
NodeSetPlacement => NodeSetPlacement.Logic
to
NodeSetPlacement.Service
to run it on the dedicated service node when running in multi-node setup. > I'm wondering whether I should use ServicesProxies as EntityShardGroup. EntityShardGroup only controls the order in which the Services/Entities are started up on server boot. Normally this doesn't need to be tweaked. The exception is mainly in the case of "Proxy" entities which copy the main entity's state into a node-local global variable. Since we want the global variable set before some depending entities start, we have the Proxy entity on
ServicesProxies
and dependees on
Workloads
.
> I'd like a kind of primary/replica setup. I'm a little concerned about the single threading in a single instance of the entity. The performance per se is rarely a problem. A single thread is surprisingly powerful, and for CPU heavy work, you could always run computations on threadpool with
Task.Run()
. However, as you say, there is always messaging, processing and sometimes network latency in the read access if implemented over MetaMessages / EntityAsk. It really depends on use case if this adds up or not but in some cases we indeed avoid the latency with a primary/replica pattern which we call Manager/Proxy. If you want to implement this, check out
LiveOpsTimelineProxyActor
. The implementations is roughly as: * LiveOpsTimelineManager is a persisted entity that maintains state. State can be mutated by LiveOps dashboard. Manager is a singleton. * A single ProxyActor lives on every node. * ProxyActor subscribes to the manager on start and updates a
ActiveLiveOpsEventState
global variable. * When manager state is changed, manager informs Proxies, and Proxies update the global variable. * All consumers can read the current data from
LiveOpsTimelineProxyActor.ActiveLiveOpsEventState
. * (To read the data, you need the
AtomicValueSubscriber
and remember to call Update() before accessing Current) > Should implement some simple caching in the entities that need the data? That is possible approach too. However, if the caching is needed, I would personally prefer the Proxy pattern so the cached is updated almost immediately instead of waiting for the stale data to invalidate.
Generally I'd start with the simplest solution of using a singleton entity and EntityAsking from it and see how long it scales. If latencies start becoming an issue, adding a cache or changing the implementation to fetch from a Proxy should be relatively simple update.
d
Thanks a lot for all the details. I agree with not optimizing prematurely. Not being familiar with the monitoring and troubleshooting of scaling in metaplay i guess i was a bit worried about not being able to spot issues it they arise and hence maybe to eager to optimize. I like the Manager/Proxy pattern. Will investigate.