Michael Poulin @ ebizq doesn’t like the Active Service pattern I suggest you read his post first but in a nutshell Michael sees two possible ways to understand the term Active Service:
“a) service view - a service that actively looking for companions to complete its own task
b) consumer view – a service which triggers its own execution by itself”
…and he doesn’t like both…
I think that both of these definitions aren’t that far… and I like both :). The way I see it there are two concern here
1. Are services only reactive (“passive”) ? - i.e. The service only “works” when it gets a request from a service consumer (user/another service/an orchestration engine) ? If the service also has at least one thread working to do internal stuff (e.g. scavenging outdated data, pre-fetching data from other service etc.) then that’s what I call an Active Service (option “b” above)
2. How do services get data they need to complete a request when they actually get a request – There are many possibilities here: events, pub/sub, an orchestration engine that takes care of that, services that check for a known contract in a registry and then go to that service, even hardcoded. The options where the service looks for other services (e.g. using a registry) is option "a” above.
So basically all the options are valid a service can be a+b just a or just b or none and, in my eyes, these are orthogonal concerns.
Regarding pre-fetching – I think this can be beneficial as a way to achieve caching. Note that if you control both sides and you’ve got the needed infrastructure then it is probably better to push changes (eventing or pub/sub) but that’s not always the case.
In the comment I left on Michael’s blog I talked about different strategies for services “There are several strategies for that - one is to take that knowledge out of the service (e.g. using choreography or orchestration), providing a subscription and/or wiring infrastructure i.e. something that will tell you where to find certain contracts, hard coding , registry , using uniform interfaces (e.g. REST) etc.”
lets take a concrete (albeit very very simplistic) scenario to illustrate some of the approaches
Business scenario: When a customer makes an order we want to give a 5% discount for preferred customers. A customer get’s a proffered status upon a business decision (annual orders of 1M$ or knowing the CEO or whatever) and the status lasts for a year from the date it was introduced.
For the sake of this discussion say we have two services (again this is overly simplified) an Ordering service and a Customer service.
Here are a few technical options:
Technical Scenario 1.
Customer places and order, the ordering service talks to “the” customer service to check if the customer deserves a discount if she does. the ordering service then updates the order with the discount and present it to the customer to finalize the order.
Technical Scenario 2.
Same as 1, with the ordering looking for a service that matches the customer contract it knows about
Technical Scenario 3
The ordering service asks “the” Customer service twice a day for a list of discounts and caches the result. When the user sends her order. it calculates the price and present it to her
Technical Scenario 4
Same as 3, with the ordering looking for a customer service (not using a known service)
Technical Scenario 5
The customer service sends a message to known subscribers whenever a new customer status occurs. The ordering service listens on that and update its internal cache. When the customer places her order, the ordering hits the cache for the discount
Technical Scenario 6
same as 5 but publishing an event to unknown subscribers
Technical Scenario 7
The customer service publish an event with the discounts (or changes in discounts) twice a day. The ordering service listens on that and update its internal cache. When the customer places her order, the ordering hits the cache for the discount
Technical Scenario 8
The customer order is passed to an orchestrating service, which hits a customer service for a discount and then passes all the data to an ordering service
There are quite a few more options and variants on the options listed but which one is best?
Yeah, you’ve guessed it - it depends.It depends since each option has its own strength and weaknesses which can work best in different circumstances . It also depends on the available infrastructure, on the structure of other services, on the services being internal or external etc.
for instance scenario 1 is less flexible than most others but it is simple to implement. There is coupling in time between ordering and customer (both have to be up for the order to complete). Scenario 4 needs to solve the problem of finding other services (e.g. using some kind of registry, or other services “pushing” their existence or whatever) but when a customer makes her request it (most likely) have all the needed info to process that request, making the ordering service more autonomous. As a side note, the fact that different approaches to achieve the same end-goal work in different situations is why I decided to write patterns in the first place
Lastly, in case you are wondering the scenarios are:
- choreography with pre-known (configured or hardcoded) companion services
- choreography with “active service” of type a (ordering is active)
- choreography with “active service” type b (ordering is active)
- Choreography with “active service” type a + b (ordering is active)
- pub/sub (e.g. using an ESB)
- eventing with “active service” type b (customer is active)