Don't Let Consumers and Service Providers Communicate Directly
getting in the way of making SOA a success probably due to your own misunderstandings and misconceptions of how SOA should work.As Ron sees it, the problem comes down to communication and the way in which developers typically work in traditional integration projects:
... they think about how they’re going to get data or application functionality out of one system, how they’ll get it into another system, the mechanism they’ll use to get that information or functionality from one place to another, and then what they need to do with it while it’s en-route to transform it from one format, protocol, context, process, or policy into another.So according to Ron, what this means is that what integration-centric developers are looking for (expecting) in a Service-based environment is a way to to data transfer and transformation and many vendors are only to happy to help by pulling out their existing integration solutions, which are no more SOA-aware than RPC. There are a number of reasons why this is a bad approach, but Ron's contention is that the communication aspect is critical:
Why? First, the main concept of SOA is that we want to deal with frequent and unpredictable change by constructing an architectural model, discipline, and abstraction that loosely-couples the providers of capability from the consumers of capability in an environment of continuous heterogeneity. This means that we have to somehow develop capabilities without the knowledge of how they might be used.Now of course that raises the usual challenge of ensuring that if things change you don't break anything somewhere else. In complex, large scale systems, the number of variables that can change (location and availability of services, versioning of Service implementations and contracts, changes to business processes and policies etc.) is large enough that change without forethought will likely break something somewhere.
However, if you think that a Service is just an API, then all hell breaks loose when you try to connect a Service Consumer directly to a Service Provider. What if the provider moves? What if the Service contract changes? What if the provider is no longer available? What if you now need a new communication mechanism or change to a data schema?The approach of adding another level of indirection to software to isolate changes, works here too. By putting something between the Service Consumer and the Service Provider you can ameliorate the problem. However, it's the current approach to implementing this that Ron believes is also at fault and developers shouldn't rely on purely on technology to solve this: as with many things in our industry, the worst thing you can do is jump in to solve a problem without considering all of the ramifications. In this particular case, the architecture of the system is the key to the solution and not necessarily some vendor product:
Let’s say you want to build a Service Consumer to consume or compose some functionality, but you don’t know where that functionality is or even how to communicate with it. There are at least three ways of handling this particular challenge. First, you can talk to a proxy (or broker or intermediary) in a language that you do understand and that’s in a location that you already know and send a request to this proxy that will act on the behalf of the Consumer.Obviously assuming that the proxy doesn't change!
This approach simplifies the problem of the Service consumer having to know about changes since they just need to know about the proxy and the end-recipient. From a technology perspective, the use of WS-Addressing simplifies this approach. In essence, a Service consumer just needs to know the WS-Address of a Provider and hand that to a Service proxy to resolve and deliver.Unfortunately Ron forgets that WS-Addressing isn't exactly always well behaved as far as SOA is concerned. However ...
The problem with this approach is that the Service proxy still needs to find a way to deliver the message, and if the proxy contains all the rules internally in the black-box, we have the same problem we have with EAI 2.0-style ESB solutions. This is where the registry steps in. Service proxies should not store their own rules, but rather get all their routing, location, and policy-based binding rules from a central system of record. In SOA, this is the role of the registry.Now although the registry helps alleviate that problem, there's still the issue of connecting the Consumer and the proxy. Just adding another level of indirection with the proxy without thought only pushes the problem elsewhere, it doesn't solve it.
The answer to this challenge is the use of registry-based “late binding”. In this scenario, the Service consumer pings the registry to find out where the proxy is, perhaps based on where the Service consumer is currently located and with what protocols it can communicate. One would think that we can make the Service consumer directly bind to a Service provider after finding its metadata in the registry, but that would be a mistake. The problem is that if the Service provider is using some alternate protocol or is in some location that the Service consumer can’t reach, we’ll have a communications problem. So, even in the case where we’re discovering metadata in a registry, we still don’t want direct communication between a Service consumer and provider.And WS-Addressing can help here too. Finally Ron ends with an answer to the question of the usefulness of ESBs in this scenario:
Is the ESB needed? Not necessarily. Will it make you feel better to buy one anyways? Maybe. Of course, what are these proxies? Surely ESB vendors will want to have you believe that their products can be used as proxies in this configuration, and that’s absolutely true. They certainly can. The point is not that ESB's can't make good proxies. They certainly can, and I want to specifically point that out. But you can also get away with not using one or using your existing infrastructure and it will all still work.
Moving away from a centralized broker?
And finally, how far do we carry this mantra of mediated interactions between service providers and consumers? For example, in a well-controlled environment if my service provider is running on a Java platform and so is the service consumer isn't something like Spring remoting enough to shield the consumer code from the details of network location, remoting protocol etc.? I don't see why going through agents/proxies would necessarily simplify things any further and would only serve as overkill unless we look at Spring remoting as the 'agents/proxies' in this case. Why would we even need something like a bus/broker/registry in between unless specific mediation capabilities are called for? Should we not strive for a balance between pure architecture ideals such as loose coupling and pragmatic considerations like application performance, simplicity etc?
Oliver Wegner, Stefan Tilkov Jul 20, 2014