9.5.13

Understanding Service Activator

From EIP

  • An application has a service that it would like to make available to other application.
Now I understand that this is the context. I am sorry I didn't realize this was part of the Pattern Language (Pattern Language) when I was trying to understand Messaging Gateway.
  • How can an application design a service to be invoked both via various messaging technologies and via non-messaging techniques?
This is the System of Forces part. We need to handle messaging technologies and non-messaging technologies. In this way, we need the decoupled solution, right? Talking about decoupling, I would think about Messaging Gateway. However, Messaging Gateway would have a Messaging System on one side while a non-Messaging System on the other. Service Activator doesn't expect this restriction. It just can't tell what would be there on each side, I think.

The problem here is about service invocation. We need to expose the interface to other application. That includes:
  • Access point. Like the function name, or alike.
  • The parameters.
  • Design a Service Activator that connects the messages on the channel to the service being accessed.
Here comes the solution: a guy named Service Activator sitting on the way the messages will come. When the expected message comes by, the Service Activator just invokes the target service.

Does it still supposed to have messaging system on one side? It sounds like an opposite of Messaging Gateway, isn't it?

What about the parameters? What about the return messages if there is any? Since it just wants to invoke a service, doesn't it imply Asynchronous?
  • A Service Activator can be one-way (request only) or two-way (Request-Reply). 
  • The service can be as simple a method call - synchronous and non-remote - perhaps part of a Service Layer [EAA]. 
  • The activator can be hard-coded to always invoke the same service, or can use reflection to invoke the service indicated by the message. 
  • The activator handles all of the messaging details and invokes the service like any other client, such that the service doesn't even know it's being invoked through messaging.
This is a very good summary of what characteristics a Service Activator has. From the very last characteristics, it confirms my guess that Service Activator works to handle messaging system request and translates it into a service out of the messaging system.

The Original Service Activator


Service Activator was originally named here. 

Problem 

You want to invoke services asynchronously.

Forces

  • You want to invoke business services, POJOs, or EJB components in a asynchronous manner.
  • You want to integrate publish/subscribe and point-to-point messaging to enable asynchronous processing services.
  • You want to perform a business task that is logically composed of several business tasks.

The Half-Sync/Half-Async Pattern in POSA2


  • EIP's Service Activator pattern is related to the Half-Sync/Half-Async pattern, which separates service processing into synchronous and asynchronous layers.
  • The Half-Sync/Half-Async architectural pattern decouples asynchronous and synchronous service processing in concurrent systems, to simplify programming without unduly reducing performance. The pattern introduces two intercommunicating layers, one for asynchronous and one for synchronous service processing.
  • It is hard to develop applications and higher-level system services using asynchrony mechanisms, .... For example, asynchrony can cause subtle timing problems and race conditions when an interrupt preempts a running computation unexpectedly.
  • Blocking I/O, in turn, enables developers to maintain state information and execution history implicitly in the run-time stacks of their threads, rather than in separate data structures that must be managed explicitly by developers.
  • Within the context of an operating system, however, synchronous and asynchronous processing is not wholly independently.
  • A key challenge in the development of ... was the structuring of asynchronous and synchronous processing, to enhance both programming simplicity and system performance.
    • Developers of synchronous application programs must be shields from the complex details of asynchronous programming.
    • The overall performance of the system must not be degraded by using inefficient synchronous processing mechanisms ...
All descriptions above are very natural. The only thing left to us is the solution.
  • Decompose the services in the system into two layers: synchronous and asynchronous, and add a queuing layer between them to mediate the communication between services ...
Really? Before I go further, I would like to recall things that I've done with JBoss Netty. Netty provides a totally event-driven programming model, which is naturally asynchronous. To alleviate the burden of my developers, I encapsulated those Event-Driven API into a set of synchronous API. Did I create a queuing layer in between? No, I didn't. 

I looked into the code again. Oh, yeah, I didn't make everything works synchronously. The major part of the system still relies on Netty's pipeline solution, which is still Event-Driven, or asynchronous. I almost forget about those headache I had.

So, if I had had done those half-sync/half-async things, should I have create a queuing layer in between? And how? I need to think.

  • If services residing in separate synchronous and asynchronous layers must communicate or synchronize their processing, allow them to pass messages to each other via a queuing layer.
To be honest, I am lost here. First of all, I think I didn't really design such a system before. For the Netty usage, I did create a data transferring implementation and made it synchronous. What I did was implementing a data sender and a data receiver using Netty's Event-Driven API and then expose these two as a library for my developers. Nothing more. And I don't know why I need more. Yes, this is too simple, right.

I needed to implement a list of commands sending and receiving between the client and server. I didn't make it synchronous because it was not too difficult to just use Netty's API. I built my own layers for the protocol and encapsulated them though. But I still exposed a callback interface for event handler. So it is still Event-Driven.

Oh, wait. They always related synchrony with long-duration, while asynchrony with short-living.

  • Services in the synchronous layer run in separate threads or processes that can block while performing operations.
  • Services in the asynchronous layer cannot block while performing operations without unduly degrating the performance of other services.
I think this could be a very good example for everyone:
  • Many restaurants use a variant of the Half-Sync/Half-Async pattern. For example, restaurants often employ a host or hostess who is responsible for greeting patrons and keeping track of the order in which they will be seated if the restaurant is busy and it is necessary to queue them waiting for an available table. The host or hostess is 'shared' by all the patrons and thus cannot spend much time with any given party. After patrons are seated at a table, a waiter or waitress is dedicated to service that table.
Oh, yeah! That makes a lot of sense. But how Service Activator pattern is related to Half-Sync/Half-Async Architectural Pattern?

How Service Activator Pattern is Related to Half-Sync/Half-Async Architectural Pattern?

Apparently this is from Core J2EE Patterns.

I could understand that Service Activator separates the Synchronous Layer and the Asynchronous Layer, although this is not necessary to be true. But which is the queuing layer? The Messaging System? So that Service Activator encapsulates the service within the hosting application and works as an Asynchronous Layer. It returns the result and put it into the Messaging System for the Client to poll and use in the Synchronous manner? I don't see another way around, because I would believe Asynchronous layer is always the lower layer:
  • The asynchronous service layer performs lower-level processing services, which typically emanate from one or more external event sources.
However, in Half-sync/Hals-Async Architecture, the Asynchronous services are supposed to be short-lived, aren't they?
  • Services in the asynchronous layer cannot block while performing operations without unduly degrading the performance of the other services.

Service Activator in Spring Integration

  • The Service Activator is the endpoint type for connecting any Spring-managed Object to an input channel so that it may play the role of a service.
I really like this description, and I really hate it also.

I like it because it is clear and matches the original definition in EIP very well. We could adapt the context in EIP to something like this here:
  • I have a Spring-managed Object and want to use it as a service for another application.
I really hate it, because service is a very ambiguous concept. You can have whatever things as a service. And you can do whatever you want in a service. As long as it could be configured as a Spring-managed Object, which is essentially a Spring IoC bean, and which is basically everything in Spring, you could use Service Activator pattern.

And this is why Service Activator is usually abused. 

I need to admit that Service Activator could be a good one to start with when you can't find a matched candidate. The start point. However, we need to evolve it into something after you find out more. Service Activator, as the name suggest, is the Activator. And as the name implies, it should connect heterogeneous systems, like the Messaging Gateway. If the service it would activate will just add some headers into the message, we should not use Service Activator.

No comments: