Skip to content

SO Apps 2, WcfNQueueSMEx2 – A System of Collaborating Microservices

June 12, 2015

This article presents the view that a Service Oriented App (SO App) is a system of collaborating microservices. These are mainly rather small, finely grained internal services. This realization is key in the current interest in microservices. And services internal to the system may also connect with external services as necessary.

As a result, an SO App is not a monolithic structure as is often the case when using a pure object oriented design approach to define software structure. Rather the structure of an SO App is that of several of not-so-large services collaborating with the UI, with data storage, with each other, and with external services to provide the behavior required. This makes SO Apps more readily scalable and more loosely coupled than traditional monolithic object oriented apps. Discrete services – at times separately hosted – greatly facilitate loose coupling and scalability.

Stepping back, one can view the current interest in microservices in part as a result of more and more people applying the things we’ve known for years that make very big differences in the cost, maintainability, scalability, and testability of software systems – The best practices of separation of concerns, abstraction, tight cohesion, loose coupling, and encapsulation.

Seeing code that implements abstract concepts like these best practices often aids in understanding both those concepts, and ways of applying them. To that end, a code example is presented to aid in understanding the idea of an SO App as a “system of collaborating microservices”. You can run the code example by following the Setup Instructions that are in the Visual Studio solution directory.  Also in this directory is a key document defining basic terms used and the organization of the Visual Studio solution.  Don’t miss reading this document.

This WcfNQueueSMEx2 code example is a refinement of the code example used in the prior article in this “SO Apps” series. The code example ignores vital cross cutting concerns like logging, security, and dependency injection to mention a few. This is done to keep the focus on the main topics of this series. Please do not implement your production apps exactly like this example.

Modifications were made to the WcfNQueueSMEx code example used in the first article to produce WcfNQueueSMEx2 as a system of collaborating microservices. Please refer to the following diagrams. Mind you, this is still a code skeleton. However with the below changes, it now has a few muscles and some connective tissue. Here are the main code changes made:

In the previously existing Data Feed Subsystem (services the ingestionqueue) 2 service components were added that collaborate with the Data Feed Manager to do validity checking and persistence:

  1. The Data Feed Manager service now orchestrates the validation of each dequeued ingested data item via a Validation Engine service. Invalid queued items are not stored.
  2. The Data Feed Manager service also now orchestrates the persistence of valid dequeued ingested data items to storage via an IngestedData Data Accessor service. And it does this in a way that is decoupled from the physical storage medium with a repository interface and its implementation. Here, note that the IngestedData Data Accessor currently does not use a local database. Rather it relies on an external service for persistence – Azure PaaS Table Storage via the repository, thus collaborating with an external service in the cloud.

In the new Admin Subsystem:

  1. A second subsystem fronted by the Admin Manager was added to support the IFeedAdmin service contract. This service contract provides its clients (mainly UI clients) with service operations required for administering the Feed subsystem. Only one such operation is implemented now — Present Feed Component Info — used to report information about the ingestionqueue, e.g. queue length. In the future the Admin Manager will also support other system wide administrative behavior via other service contracts (facets) beyond those associated with data feeds.
  2. Again, this subsystem is an example of collaborating services. And, please note the reuse of microservice components across subsystems: Several subsystems use separate instances of the AdminDA and Validation Engine services.

In the new “Some Subsystem”:

  1. A third subsystem was added to further demonstrate how microservice components can be reused across subsystems, and how SO Apps can be composed of multiple separate subsystems that can collaborate in various ways. Note that the collaboration between the Data Feed Subsystem and the new Some Subsystem is currently only via using a shared database – the IngestedData DB (which is accessed via an external service). Such collaboration, however, could be more dynamic involving queues or pub/subs providing Manager-to-Manager communication. Such dynamic collaboration is not presented in this example. Perhaps a subsequent article will feature this.
  2. This subsystem consists of:
    1. The Some Manager WCF service that receives requests from clients.
    2. A Some Data Analysis Engine service performing some sort of analysis on the previously ingested data.
    3. The reuse of the Validity Engine service (used by all subsystems) and the IngestedData Data Accessor service (used in the Data Feed subsystem) to access the IngestedData DB.
  3. This system does not currently access the IngestedData DB simply to reduce development time right now. The analysis results are simply strings inserted by a stub. This system is here only to provide a sketch of the structure of an SO App having multiple subsystems and to demonstrate microservice component reuse.

Below are diagrams of the call chains (the uses relation) of the 3 service operations (implemented by 3 Managers) in the WcfNQueueSMEx2 example. Except for the Clients, each box represents a service, and the arrows between boxes represent calls between services (or messages if you wish). These diagrams are not about classes or inheritance, but about services calling each other. In a real system each Manager would definitely have more than one service operation!

Figure 1 – Data Feed Subsystem’s call chain. DA is Data Accessor and DB is Database.

The Data Feed subsystem has one service operation and call chain implemented. Note that the dashed arrow above, going from the Data Source Client to the Data Feed Manager, indicates this is a queued call — it represents the ingestionqueue. All the solid arrows represent request/response calls.

As an aside, I have found this type of call chain diagram to be quite useful in designing systems, in communicating concepts to developers and between team members, and as a developer to aid me in more quickly implementing the services and clients required. I learned this technique at the week-long IDesign Architects Master Class. Then I got to practice it in the design of several real world systems under the supervision of a very experienced architect at the week-long IDesign Architecture Clinic. Constructing such diagrams does not take much time at all. And refactoring the drawings is vastly much faster than refactoring actual code.

AdminCallChainFigure 2 – Admin Subsystem’s call chain. The Admin subsystem has one call chain for its single service operation. All of its calls are request/response.

SomeCallChainFigure 3 – The new “Some Subsystem” call chain. It has one service operation and call chain implemented. Again, a real app would have more service operations here.

The WcfNQueueSMEx2 example system uses WCF to implement all of its collaborating internal services – Managers, Engines and Data Accessors alike. Managers are hosted in Windows Services (simulated by console apps in the code example) or in Azure Worker Roles. The Engine and Data Accessor services are run “in process“ (aka InProc) to the Managers that use them. This is accomplished by the IDesign InProcFactory (in the ServiceModelEx library), resulting in each Manager using its own private instance of the Engine and Data Accessor WCF services it requires. Performance tests have shown running services in-process like this will support 100 calls per second, and many more by doing performance optimization.

Alternately, one could have a Manager instantiate the Engine and Data Accessor classes it uses as objects rather than WCF services (or use dependency injection to supply instances of these classes) as is done in object oriented systems. However, running Engines and Data Accessors as WCF services in process to a Manager via the InProcFactory provides great value as follows:

  1. InProc WCF services are directly hooked into the “custom contexts” provided by WCF message headers. Thus an InProc Engine or Data Accessor can read from and write to the message headers shared by the Manager and other Engines and Data Accessors. The context these headers provide is a powerful way to separate the concerns of the system (i.e. the system processing the messages) from the concerns of the business domain (i.e. the domain oriented content of data contracts within the messages). This separation of concerns prevents polluting business-oriented data contracts with a bunch of system info required to effectively route and process messages. For example, the context can contain out-of-band parameters like user tokens, environmental info like whether the client is a mobile device or desktop system, message routing information, etc. These valuable kinds of information have no place in business domain oriented data contracts. Please see “Appendix B: Headers and Contexts” in PWS (cited below) for more information in this area.
  1. Running Engine and Data Accessor services InProc also provides them with the full power and extensibility of WCF as a message based communication framework. This includes automatic authentication of the caller if desired, transaction support, and data contract versioning tolerance to mention a few very useful capabilities. It also allows the services running InProc to easily “add tracing and logging, authorization, security audits, profiling and instrumentation, and durability” PWS, p 699. And it enables them to use the powerful extensibility mechanisms of WCF, plus the ability to implement aspect oriented behavior. All this can reduce development and maintenance costs, while supporting the implementation of very sophisticated behavior. There are numerous sections in PWS (cited below) that demonstrate how to exploit the power of WCF. For a comprehensive series of articles and code examples on WCF extensibility please see Carlos Figurea’s blogs at http://blogs.msdn.com/b/carlosfigueira/archive/2011/03/14/wcf-extensibility.aspx

In summary:

  • Viewing and designing Service Oriented Apps as systems of collaborating microservices readily offers the benefits and reduced costs to be gained by applying the best practices of separation of concerns, abstraction, tight cohesion, loose coupling, and encapsulation.
  • WCF as the implementation technology for Service Oriented Apps has the capabilities required to cost effectively build and maintain such systems designed with these best practices as their foundation.
  • The code example shows that the code required to build such systems of collaborating microservices is not difficult at all. In fact I find it quite easy to write, test, and to refactor.

George Stevens

Bibliography

  1. PWS – Programming WCF Services, 3rd Edition, by Juval Lowy, Copyright 2010, O’Reilly Media, Sebastopol, CA.

Creative Commons License

dotnetsilverlightprism blog by George Stevens is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. Based on a work at dotnetsilverlightprism.wordpress.com.

Advertisements
Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: