If you're considering switching your monolithic application into a SOA you should consider the testing and debugging implications seriously.
If your call graph goes more than one level deep then doing integration/functional testing becomes much more complicated. You have to bring up all of the services downstream in order to test functionality which crosses that boundary. You also have to worry a lot more about different versions of services talking to each other and how to test/manage that. The flip side is that the services will be much smaller, so leaf nodes in the call graph can reach a level of test coverage higher than a monolithic service.
Debugging and performance testing becomes more complicated because when something is wrong you now have to look at multiple services (upstream and downstream) in order to figure out where the cause of some bug or performance issue is. You also run into the versioning issue from above where you have a new class of bug caused by mismatched versions which either have tweaked interfaces or underlying assumptions that have changed in one but not the other (because the other hasn't been deployed and those assumptions are in shared code). The bright side for debugging and performance is that once you know which service is causing the issue it's way easier to find what inside the service is causing the issue. There's a lot less going on, so it's easier to reason about the state of servers.
It depends how you do SOA. We try to publish "events" rather than to "call" another service and expect responses. We try to decide as much as possible in the service that publishes an event, so that information doesn't have to be returned. Other services act on that information.
Your kind of SOA sounds more like distributed RPC, which indeed is complicated.
We do things very differently to that discussed in the OP (and are heavily influenced by the Krepian school of SOA.) I'd write more, but I'm on a train with flaky internet.
Awesome link. Epic is the right descriptor. You could do much, much worse if you were looking to understand data integration in practice.
The links section at the bottom alone are a tremendous resource. I've stumbled across most of these over a period of years and if you started with just skimming over this article and the links, you would save yourself many hard lessons.
For a slightly different slant on SOA's I'd thoroughly recommend watching Fred George's talk on the technical side of implementing micro-service architectures from Oredev last year
Other big benefits you get from well defined interfaces include security - you can do application level firewalling, statistics, anomaly detection really easily - and testing (play back known traffic, literally generate every possible message and see what happens, etc.)
Also, HTTP can be a poor choice in security terms for its complexity baggage (cookies, headers, methods, DNS baggage, SSL baggage, etc.). Alternatives such as MQs can be useful to consider, especially at later points in growth, since they can handle complex topologies with ease.
I believe the author could benefit from making a distinction between stateful and stateless in his description of dumb and smart API clients, since state is the main factor resulting from assumptions here.
So after going back and forth with our startup on SOA or not, I have felt like separating these services out of (in our case) a monolithic Rails application has made sense. I would like to use Sinatra for one service, rails for the web interface, and possibly Python for the last service. I understand this adds a lot of overhead by creating an interface and authentication for each service.
For me the logical division of services seems to make sense especially when using 'the right tool for the right job'
I may be over optimizing, but I think it will pay off at a later date with more developers and the need to scale each service separately. Maybe someone can point out issues with this thinking (besides those addressed in the blog post).
To me the crux of the issue is the interface. If you can define a very clean interface without having to do a lot of contortions to get the data you want where you need it, then extracting a service can be relatively low overhead. But what often happens is at the 30,000-foot view it looks like a service makes sense, but then when you get into the details you realize the separation can not be as clean as you first envisioned.
If you use a message queue system like RabbitMQ, and simply publish messages as JSON you have interfaces, authentication etc. done already. We have 17 different services internally, in four different languages, all communicating over AMQP with JSON messages.
(Disclosure: I'm owner of CloudAMQP - RabbitMQ as a Service, www.cloudamqp.com)
Last job wanted SOA but wouldn't deploy Rabbit (or any other message bus) because "it's another thing to look after". Ended up as a simple REST-alike webservice. Which I guess includes "service" in the description...
What you've just described is a proper micro service architecture. Which is basically a more minimalist and opinionated form of SOA.
Nothing wrong with wanting to avoid dependencies. Good programmers try to avoid dependencies and coupling, especially to third party products, all the time.
Service buses like Rabbit are cool n' all but sometimes you don't need the complexity.
We don't call it an ESB in our non-Enterprise environment. It's just called "service bus" or "message bus". Which is really just a fancy application-level API around services, queues, and messages (see http://particular.net/NServiceBus). It's incredibly useful, dare I say essential, for abstracting away those infrastructure level concerns when developing complex distributed applications.
We use it pretty extensively in our SaaS product to achieve loose coupling, yet high cohesion, between our various software components.
We use SOA a lot, we have a RabbitMQ server/cluster in the middle who all services communicate via. We have applications written in Ruby, Go, Clojure and Node.js, all publishing and subscribing JSON messages.
Benefits over monolithic: New languages/techniques can be introduced at any stage, and used for what's best for. Applications can be isolated, and only do one thing, making the system much more reliable. Your web front doesn't have to down because you have a bug in the mailer app.
Benefits over HTTP: Not everything is web facing, workers etc doesn't need a full web stack. Services can be offline, without interrupting other services. You get load balancing and work queuing for free. Performance, 5000msgs/s with disk persistence is no problem for a low end RabbitMQ server. Great inspection capabilities with RabbitMQ's management interface.
Tip: Get away from a "RPC" mindset, think "events" instead. Let other services subscribe to events they should take action to. Decide as much as possible up front, in the application that publishes events, so that information doesn't have to be returned.
Disclosure: I'm the owner of CloudAMQP (www.cloudamqp.com), RabbitMQ as a Service. But have used SOA and RabbitMQ a lot longer, both for small and large projects.
I've used Kafka, ActiveMQ, MSMQ and Tibco on long running projects.
An ESB can be incredibly powerful when you give a small developer team access to it and wait to see what they dig out of the data. We pulled realtime data about sales that no one had access to and it was enlightening for everyone.
When non-programmers use something like tibco, the results are abysmal. Slow overly complicated highly coupled mess that only one person will understand, the creator. When most people say ESB, this is what they mean and it is a tax on the company.
How will you manage communication between services in a SOA? If you exclusively use point-to-point welcome to spaghetti code.
Our philosophy is to use point-to-point when you absolutely need another service's input to complete your task. Otherwise put a message into the bus. See the Jay Kreps blog post I linked in below.
..."in a non-Enterprise environment" - yes...well..expanding into an enterprise; using BizTalk server (Microsoft).
I design and create SOA solutions through services exposed by/through BizTalk and build an ESB solution to orchestrate the services which acts as a substrate for 'composable' applications (again, using BizTalk and apps that use the services are web-based, or whatever client apps the organization wants to use; many apps are integrations between systems like line of business using various approaches that include EDI, etc).
[+] [-] JeffJenkins|12 years ago|reply
If your call graph goes more than one level deep then doing integration/functional testing becomes much more complicated. You have to bring up all of the services downstream in order to test functionality which crosses that boundary. You also have to worry a lot more about different versions of services talking to each other and how to test/manage that. The flip side is that the services will be much smaller, so leaf nodes in the call graph can reach a level of test coverage higher than a monolithic service.
Debugging and performance testing becomes more complicated because when something is wrong you now have to look at multiple services (upstream and downstream) in order to figure out where the cause of some bug or performance issue is. You also run into the versioning issue from above where you have a new class of bug caused by mismatched versions which either have tweaked interfaces or underlying assumptions that have changed in one but not the other (because the other hasn't been deployed and those assumptions are in shared code). The bright side for debugging and performance is that once you know which service is causing the issue it's way easier to find what inside the service is causing the issue. There's a lot less going on, so it's easier to reason about the state of servers.
[+] [-] CarlHoerberg|12 years ago|reply
Your kind of SOA sounds more like distributed RPC, which indeed is complicated.
[+] [-] noelwelsh|12 years ago|reply
We do things very differently to that discussed in the OP (and are heavily influenced by the Krepian school of SOA.) I'd write more, but I'm on a train with flaky internet.
[+] [-] tom_b|12 years ago|reply
The links section at the bottom alone are a tremendous resource. I've stumbled across most of these over a period of years and if you started with just skimming over this article and the links, you would save yourself many hard lessons.
[+] [-] adrianhoward|12 years ago|reply
https://vimeo.com/79866979
along with his talk on Programmer Anarchy which is more about the resulting team / working patterns
https://vimeo.com/79866978
It's moved playing with much finer-grained service architectures way up my to to list.
[+] [-] alecthomas|12 years ago|reply
[1] http://en.wikipedia.org/wiki/Tuple_space
[+] [-] zeroDivisible|12 years ago|reply
[+] [-] contingencies|12 years ago|reply
Also, HTTP can be a poor choice in security terms for its complexity baggage (cookies, headers, methods, DNS baggage, SSL baggage, etc.). Alternatives such as MQs can be useful to consider, especially at later points in growth, since they can handle complex topologies with ease.
I believe the author could benefit from making a distinction between stateful and stateless in his description of dumb and smart API clients, since state is the main factor resulting from assumptions here.
[+] [-] ndcrandall|12 years ago|reply
For me the logical division of services seems to make sense especially when using 'the right tool for the right job'
I may be over optimizing, but I think it will pay off at a later date with more developers and the need to scale each service separately. Maybe someone can point out issues with this thinking (besides those addressed in the blog post).
[+] [-] dasil003|12 years ago|reply
[+] [-] CarlHoerberg|12 years ago|reply
(Disclosure: I'm owner of CloudAMQP - RabbitMQ as a Service, www.cloudamqp.com)
[+] [-] fleitz|12 years ago|reply
[+] [-] brown9-2|12 years ago|reply
A new interface for each service, sure, but if your services only need to be deployed internally, some sort of authentication layer could be overkill.
[+] [-] al2o3cr|12 years ago|reply
Howsabout the one that was addressed in the blog post, namely that SOA is going to slow down your process?
Premature optimization indeed.
[+] [-] hartror|12 years ago|reply
[+] [-] zimpenfish|12 years ago|reply
[+] [-] mattmanser|12 years ago|reply
[+] [-] nbevans|12 years ago|reply
Nothing wrong with wanting to avoid dependencies. Good programmers try to avoid dependencies and coupling, especially to third party products, all the time.
Service buses like Rabbit are cool n' all but sometimes you don't need the complexity.
[+] [-] nl|12 years ago|reply
Is anyone doing SOA+ESB in a non-Enterprise environment?
Is an ESB actually useful beyond the idea that it is supposed to let "non skilled" people "develop services" (which I'm somewhat cynical about)?
[+] [-] daigoba66|12 years ago|reply
We use it pretty extensively in our SaaS product to achieve loose coupling, yet high cohesion, between our various software components.
[+] [-] CarlHoerberg|12 years ago|reply
Benefits over monolithic: New languages/techniques can be introduced at any stage, and used for what's best for. Applications can be isolated, and only do one thing, making the system much more reliable. Your web front doesn't have to down because you have a bug in the mailer app.
Benefits over HTTP: Not everything is web facing, workers etc doesn't need a full web stack. Services can be offline, without interrupting other services. You get load balancing and work queuing for free. Performance, 5000msgs/s with disk persistence is no problem for a low end RabbitMQ server. Great inspection capabilities with RabbitMQ's management interface.
Tip: Get away from a "RPC" mindset, think "events" instead. Let other services subscribe to events they should take action to. Decide as much as possible up front, in the application that publishes events, so that information doesn't have to be returned.
Disclosure: I'm the owner of CloudAMQP (www.cloudamqp.com), RabbitMQ as a Service. But have used SOA and RabbitMQ a lot longer, both for small and large projects.
[+] [-] nahname|12 years ago|reply
An ESB can be incredibly powerful when you give a small developer team access to it and wait to see what they dig out of the data. We pulled realtime data about sales that no one had access to and it was enlightening for everyone.
When non-programmers use something like tibco, the results are abysmal. Slow overly complicated highly coupled mess that only one person will understand, the creator. When most people say ESB, this is what they mean and it is a tax on the company.
[+] [-] noelwelsh|12 years ago|reply
Our philosophy is to use point-to-point when you absolutely need another service's input to complete your task. Otherwise put a message into the bus. See the Jay Kreps blog post I linked in below.
[+] [-] ewest|12 years ago|reply
I design and create SOA solutions through services exposed by/through BizTalk and build an ESB solution to orchestrate the services which acts as a substrate for 'composable' applications (again, using BizTalk and apps that use the services are web-based, or whatever client apps the organization wants to use; many apps are integrations between systems like line of business using various approaches that include EDI, etc).
[+] [-] unknown|12 years ago|reply
[deleted]