0

I apologize in advance for a long-read question, but i'm hardly stuck here and don`t how to ask for help using fewer words.

I need to implement a middleware service which should be placed between two big systems: First - Asterisk virtual telephony station; Second - our company enterprise core.

Enterprise core consist from many instances of CoreServer. They all considered to be the same (duplicates) Asterisk considered to be a singleton system.

So I need to implement a service that must be kind a bridge/access window between many CoreServers and single Aster. Lets call it AsterService.

Restrictions:

  • Part that should be inside CoreServer can be written using Net Framework 4.5.2 maximum! So such technologies like gRPS can't be used.
  • Generally Microsoft tech stack, no containers. So no Kafka, RabbitMQ and etc is allowed.

That explains why I choosed WCF for implementing this service.

Service must provide next features:

1) Base communication between systems. For example, sending commands from core to Aster and getting data from Asterisk database.

2) Observe and store current state of Aster server (queues, active calls, members etc.)

3) Monitoring that state. Here the intersting point is that each CoreServer serves many clients. Each client may want to obsreve some concrete of Aster state (queues list or queue members or active channels list etc)

Let's discuss each of them:

1) This part is OK, no questions. I have a good interface for interacting with Asterisk for getting data from it or sending commands to it. I'm using AsterNET if someone's interested. Other parts are not so clear for me and want to discuss each of them.

2) Observing and storing Aster state

Ok, I have all necessary functional for this regarding to interaction with Aster. I can get queues, it's members, I receive all events if, for example, new active channel is created. This should be a singleton, that holds one connection to Aster, observes it's events and provide a channel for sending commands to it. Of course, I can store all this data in some data collections, which always evolve reflecting all changes in Aster state. Let's call this part AsterMonitor.

The problem is how to make properly interaction between WCF service and this singleton part that observes Aster state?

As I understand for WCF the best way is to implement perCall InstanceContextMode, not single. So where I should keep my AsterMonitor? I can't store it inside WCF without using Single instance mode. (currently I'm using single, but I want to change it to PerCall or PerSession, keeping AsterService lightweight)

Should this AsterMonitor be a separate service with its own interface for AsterService? Maybe, but it's hard to maintain, because both of them are always evolving.

Maybe there is a better way to make it like system service, keeping it singleton, allowing to interact with it directly through shared memory without maintaining WCF interfaces and all it's structure?

3) Providing access for Aster state data

The problem is that behind each CoreServer can be many clients. Each client may want to observe his concrete point of interest. For example members list of concrete queue.

First idea is to store a copy of Aster state in each CoreServer, so clients will interact with CoreServer. Bad idea, because:

  • our CoreServers instances are really overloaded by other functionality. We to need to reduce load from them.
  • Clients interacr with CoreServer via Remoting. If so, we need to implement some extra layer.
  • We can connect clients directly to our AsterService, leaving CoreServers separate from all this kitchen.

Ok, all our clients, who are interested in interacting with Aster, can interact directly with our AsterService through WCF. Appears next problem: How to send data to all the clients? Aster state is pretty big array of data and each client is interested only in 1% of this data. More, many clients can be interested in same data type, but with different Ids. For example, two clients, who observe member list of two different queues. So we need something like Observer/Publisher pattern.

Sounds good, but:

  • AsterMonitor consists from many separate objects - Monitors. Each monitor observes it's part of state and provides it's own pack of operations to get that data. If we'll try to put that all in our AsterService interface - it turns into disaster. It's very hardly maintanable. Especially keeping in mind, that we want to keep AsterService lightweight and AsterMonitor singleton.
  • We should not send changed data to all the clients, only for those who are interested.

Ok, let's try to create a tiny message broker between client and AsterService. Each Monitor inside AsterMonitor can publish kind a message inside AsterService Host. AsterService provides functionality to subscribe\unsubsribe for some messages, keeping inside of it list of subscribers and resending those messages only to clients who subscribed.

It works somehow, but also turns into disaster in maintaining. Especially trying to implement ability to subscribe to concrete objects with it's own Id. Especially without ability to transmit generic classes.

How to implement ability to subscribe\unsubscribe to topics and concrete objects? I have next thoughts about it:

  • Switch to messaging in JSON
  • Intergrate those monitors in ASterService using MEF, But have no idea how to it.
  • Implement one big AsterMonitor service. For client interacting with every type of monitor implement separate tiny AsterService. Like AsterService_QueueMonitor, AsterService_ActiveCallsMonitor.

I will appreciate any ideas about this problem.

6
  • 3
    WCF isn't a messaging technology so doesn't actually do any communication; it's a layer of abstraction on top of other messaging/transport technologies such as MSMQ or HTTP. WCF is a strongly opinionated application-layer framework about defining strict API contracts/specifications; yet the problem you seem to be trying to solve looks to be about transport and delivery, and sounds as if you're actively seeking to avoid defining strict API contracts. With that in mind, it seems that WCF will do nothing but make your life difficult by getting in the way of the underlying transport layer. Commented Jul 19, 2023 at 8:11
  • I'd suggest looking toward transport and messaging solutions instead; If you can't use any 3rd party services then the NetMQ library may be a good fit; it has a number of message patterns built-in and is intended for problems related to transport, delivery and queueing: github.com/zeromq/netmq Commented Jul 19, 2023 at 8:11
  • Thanks for you advices! Luckily, I convinced the management that we need modernization. Now I have ability to use RMQ, so all the messagging will be organize throgh it. Now I have new question: Is it a good idea to use WCF for observing and storing Aster state data? With RMQ I'm not limited to use WCF. Commented Jul 21, 2023 at 11:24
  • My thoughts: Client side will stay on Framework 4.8. Unforunately, there is no way for modernization. I'm planning to use RMQ deployed as a docker container. I think that it would be nice to put my AsterService in docker container also. It is important to stay on Net developing AsterService. Does WCF-service best fits for this? Maybe there are newer technologies solutions using latst versions of Net? Commented Jul 21, 2023 at 11:24
  • WCF still can't help with your problem -- to be clear, WCF is an API contracts framework, to define the external "surface area" of a service; but does this in a way which achieves exactly the opposite of your goal in providing flexibility for message content (it creates very tight constraints and removes flexibility). WCF does not handle any of the underlying implementation for services themselves, so doesn't do anything relating to storing state, nor does it provide any kind of notifications/messaging for observability - you'd still need to implement all of these things yourself. Commented Jul 22, 2023 at 7:03

1 Answer 1

1

I would implement as follows:

  1. A Windows Service on each machine that is running Aster. A service is easy for your operations team to set up health monitors and controls for starting and resetting. And it is easy to implement because it is a single process that you have complete control over.

    The service can get the data any way you need, either responding to events or by polling. It keeps all of the data required in a single data structure, and maintains the two most recent copies. When the copies differ, it saves the most recent copy to a database.

  2. A WCF service that wraps the database and allows the caller to retrieve the required data.

Your core components can then access the WCF service to see the most recent data about the Aster system.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.