开发者

How to do multiple publication scheduling in C# service?

开发者 https://www.devze.com 2023-04-07 00:27 出处:网络
I have one service which is listening forposition updates coming from upstream system. Now there are multiple consumers of this position updates.

I have one service which is listening for position updates coming from upstream system. Now there are multiple consumers of this position updates.

  • One consumer wants to get update as soon as possible
  • One consumer wants to get update every 30 seconds
  • One consumer want to get updat开发者_开发知识库e when 50 updates are accumulated
  • One consumer want to get update when 50 updates are accumulated or 30 seconds which ever is earlier.

Above can be changed anytime or new variation can be added ?

How can I make this configurable, scalable, and what kind of programming approach I should use.

I am developing in C#, Window Service


It sounds like you are describing a scenario where the service is an intermediary between the publishing source (the service itself is a subscriber) and the service re-broadcasts this information to N subscribers, but according to their schedule.

So assuming an update is a single position update and not some sort of aggregation like a rolling average nor a buffering (e.g. just the latest position of a car every 30 seconds not all its positions since the last 30 seconds), then you need to maintain some information for each subscriber:

  • a subscription. Who is the consumer? how do I notify it? (e.g. callback, reply queue, etc.)
  • a specification. What does the consumer want and when? (e.g. every 50 ticks)
  • state
    • time since last send
    • number of updates since last send
    • ...

As the service receives updates, for each consumer it must evaluate the specification against the state for each update from the source; something like:

if (consumer.Spec.Matches(consumer.State, updateMessage)
    SendUpdate(consumer.Subscription.Callback, updateMessage)

The above assumes your spec is directly executable by the service (i.e. the consumers are in-process or the spec was serialized and can be deserialized by the service. If this isn't the case, your spec could perhaps represent a DSL (e.g. a parseable representation that the server could compile into something it could execute). Another approach is thinking of the spec as an instruction set. For example,

public enum FrequencyUnit
{
    SecondsSinceLastSend,
    UpdatesSinceLastSend,
}

public class Frequency
{
    public double Value { get; set; }
    public FrequencyUnit Unit { get; set; }
}

public class Operator
{
   Every, // Unary: e.g. every update; every 10 sec; every 5 updates
   Or,   // Nary: e.g. every 50 or every 20 sec (whichever's first)
   And,   // Nary: e.g. 19 messages and 20 sec have passed
   // etc.
}

public class UpdateSpec
{
    public Frequency[] Frequencies { get; set; }
    public Operator Operator  { get; set; }
}

These are pretty flexible, and can be configured on the server in-code, or built-up by reading XML or something. These could also be passed to the service from the consumer itself upon registration. For example, an IService.Register() could expose an interface taking in the subscription and specification.

The last bit would be scalability. I described the service looping on each update for the consumers. This won't scale well because the loop may block receiving the updates from the source or if asynchronous with the source, would at least likely accumulate updates faster than processing them.

A strategy to deal with this is to add an internal queue to the information you maintain for each subscriber. The service, upon receiving an update, would enqueue it to each internal queue. Service tasks (TPL-based), thread-pool threads, or long-lived threads would then dequeue and evaluate the update as above. There are many possible variations and optimizations of this.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号