17 ms·
Microservices – Not a free lunch
- cs02rm0 12y agoI was prepared to be convinced, what in our field does bring nothing but benefits? I didn't see much to worry about here though; * who cares if you're deploying 20 services or 1 when you run your deploy script? * who doesn't have an operationally focused dev team? * who isn't already dealing with interfaces even if not micro services? * since when do micro services have a monopoly on distributed architectures or asynchronicity? I can't agree testing is harder either. Too much fluff in this article to read much value into it.
- zwischenzug 12y agoI've run such operational teams, and the benefits of monoliths are immense.
- cs02rm0 12y agoFancy listing some then rather than just stating it? Better yet, write a more concrete article than the above and post a link to it.
- tracker1 12y agoI think that mentioning that many of these microservice environments tend to be polyglot environments or that infrastructure is a big deal. Moving towards containerized deployments helps at some levels and is more difficult at others. Having internalized heroku-like abilities goes a long way too.. it really depends. Even looking at Lambda as a service layer seems pretty nice... the bigger issue to me seems to be the coordination layers of these services. You have upstarts like etcd, along with the likes of zookeeper and others. Just the same, it takes a lot of effort. For the same note, you may want to just keep some more logical service/worker boundaries in place, and API all the things so to speak... that doesn't even mention caching and related issues. It depends on the environments.. when you are trying to introduce half a dozen platform/technology changes in a small company, it's not easy in terms of training alone...
- ExpiredLink 12y agoYou can easily end up in microservice spaghetti like this application: http://www.infoq.com/presentations/scale-gilt http://www.infoq.com/presentations/scale-gilt scroll to 20:40
- ddorian43 12y agoA minute later, I think they create a service whenever they need a function.
- ExpiredLink 12y agoSurprisingly, this application is presented as 'success story'.
- ryanbrunner 12y agoRegarding interfaces, dealing with an in-process, code level interface is just on the surface simpler than dealing with an external interface like a JSON endpoint. If you're working with a statically-typed language, the comparison isn't even worth making - a contract that needs to be extensively tested turns into a compile error. Even in a dynamically typed language, the tooling to test that methods are being called correctly are much more mature and developed than determining that two independent services are conforming to the same contract.
- ayrx 12y agoJust wondering out loud: maybe it's possible that tooling for this just hasn't been written yet? Something along the lines of declaratively stating what a JSON endpoint should be like and having a tool automatically assert that the services conform to that interface doesn't look impossible.
- logicchains 12y agoF# could do this with type providers. Or, something like Google Protocol Buffers could be used.
- cs02rm0 12y agoOr Java with JAX-RS. Or one of probably hundreds of alternatives.
- jacques_chester 12y agoIt's been tried many many times, but as a network service you simply have no way to enforce what messages you are going to receive until you receive them. So you have to type check at runtime. You can build tooling to make it easier to produce conforming software at each end, but you can't guarantee that someone won't just go ahead and write any old thing. So in practice you still perform validation on each message. Put another way: distributed systems turn all type errors into runtime errors. The guarantees of compile-time checking are severely weakened.
- 12y ago
- olalonde 12y agoOn a related note, is anyone aware of any tool(s) to declaratively describe an application architecture and automate its deployment on something like AWS or in a single virtual machine + docker? For example "I want 10 replicated microservice1 processes and 5 replicated microservice2 processes in front of a nginx load balancer. Also, throw in a Redis and a PostgreSQL database." This would be immensely useful for (one man show) developers who don't necessarily have the time or experience to "properly" setup and fine tune infrastructure. I think what I'm describing is known as "Infrastructure as code" in DevOps parlance. Edit: Since this question is getting many replies, I'll be a bit more specific in what I am looking for. Is there a tool that would let me describe the infrastructure and deploy it on a given cloud provider but also have the ability to deploy the same infrastructure on my local machine (using VMs/docker) for development purposes.
- pavlov 12y agoSounds like you want AWS OpsWorks? https://aws.amazon.com/opsworks/ https://aws.amazon.com/opsworks/
- Denzel 12y agoSalt/salt-cloud operates as you describe. It allows you to define any number of virtual machines associated to a cloud provider 'profile', i.e., instance type, size, platform, etc.
- kikibobo69 12y agoWe're working on a very low-tech version of this at Zalando, here: https://github.com/zalando/aws-minion https://github.com/zalando/aws-minion
- ryanbrunner 12y agoCloud66 can handle most of what you describe using manifest files. You can have a relatively simple yml file describing what types of servers exist in your stack - something like "I need Postgres servers, Redis, a RabbitMQ server, oh and here's the 3 different types of process servers I have and also how my main web server functions." There's still a point where it's beneficial to split an application into seperate stacks, in which case the manifest concept breaks down and you're stuck doing a lot of work yourself, but they can take you a fairly long way.
- DanielBMarkham 12y agoI'm really happy to see DevOps, CD, and Microservices take off, although, as usual, I'm a little perplexed as to why we need new slang. But hey, if it works to get the message out, I'm all for it. These things are not new, but like so many other ideas, they're just old ideas re-appearing in a context that had forgotten about them. Traditionally, many of the potential problems the author relates have been solved by architectural conceits. For instance, standardize on a programming language and datastore, then share all persistence-related files. (I'd strongly suggest a FP language, preferably used in a pure manner). Then you've decreased the "plumbing" issues by a couple orders of magnitude, lowered the skill bar for bringing in new programmers, and you can start talking about using some common testing paradigms to work on the other issues. I'm a huge fan of microservices, but it's good to talk about the bad parts too, lest the hype overrun the reality.
- waps 12y agoIt's just a technology cycle. Microservices have serious disadvantages as well, which will cause their elimination in, oh, 5 years if they're lucky. 1) They're not really simple. If you take essential functions like a key-value store, that'd be a microservice. Simple ? Yeah right. Business logic ... simple ? Yeah right. 2) It's slower. You can wine all you want, but when it comes right down to it, there's a reason people avoid crossing the network, and the microservice approach essentially comes close to crossing the network every single time you cross module boundaries. You'll be spending 50%+ of your cpu time marshalling and unmarshalling and waiting for transmission, even on the same system. This also manifests in all these "no-sql" datastores. They have all the problems of sql datastores, but they have one more. There's no way to have indexes. So in a table indexing all your sales by "id", the only way to find sales of product "X" is by going through each and every record (you can build indexes yourself, but it's not easy and it's sure as hell not flexible. Plus I guarantee you'll do it wrong the first 10 times). This means that retrieving 10 sales records takes the exact same amount of time as generating the yearly sales reports. In other words : you won't be doing it, because it takes too long. 3) There's just so damn many of them if you want to achieve anything useful. Every single one of them needs to be sufficiently well-designed to operate like an individual web server. So (d)dos-resistance, fairness, anti-slowloris, anti-starvation, autoscaling, resource exhaustion (like maximum number of file descriptors ...) correct sharding, access control (not too tight, not too loose, ... correct caching of security credentials, ...), and load testing, you've thought of all that for that "really small and dumb" service that basically copies information across the payment/non-payment firewall right ? If you haven't ... prepare to be surprised. A related problem here is the shear amount of diagnostic monitoring you'll need. 4) They are inflexible, and don't deal well with different data types (this is one of the things object oriented programming solved). They work well when they deal with strings, or with company-standard datatypes. Only companies don't like to have company-wide standards. Yeah, I know Sun and to a lesser extent Facebook succeed at it, but does your company ? Last time I consulted at a bank they had systems interoperating using every interchange format from fixed-width fields (old cobol code), 5 different kinds of xml, and of course json and a dozen binary formats. Microservices can't work in such an environment. It destroys the flexibility of individual actors. The argument here, of course, is that that is a good thing, and I'd say you're right, but you've just created yourself a hell of a lot of enemies, some of them powerful. 5) It's extremely hard to orchestrate integration across multiple microservices. The first thing this will manifest in is testing. How do I test one service ? The answer is "unit tests" or "a system test". But this is the result of a fundamental misunderstanding. As a company, or even an IT department, you don't really care if unit tests and/or system tests succeed for a microservice. You care that if you connect a -> b -> c -> d -> e -> f -> g (and usually this is a network of microservices, not a sequence) that you can sell gizmos on your website. Testing if that works requires throwing up three dozen services. Now first, having watched the netflix talks, they do this. Congrats. That's can't be easy. They also talk about the disadvantages : they have 3 teams doing nothing other that making that work, and it eats a significant part of their AWS resources. They can't do it on developer's workstations, nor even on a number of them. The second thing this will manifest in is the cross-microservice redesign. Say a new law comes in. With a payment we now need to have a scan of the driver's licence of the buyer (say "gizmos" are treated like alcohol). So we simply need an extra image field going through the payment system. Oh-oh. The payment system is 8 microservices, and therefore around 64 interfaces to the rest of the system. Let's be generous ... only about 30 need to be redesigned. There is nothing to help. Refactoring, or even type checking doesn't work across microservice boundaries. This presents 2 problems. First is that it's a hell of a lot of work, even though most services only do basic things and don't care about the new data. But they still copy the data, save it, ... each of them needs logic to deal with missing data (historical data for instance), and the copy from one json dict to another needs to be implemented. And as you'll find every microservice has it's own methods for dealing with said datatype, you'll be checking up to 8 libraries for marshalling problems. Second is testing. Any error you make won't come up unless you're testing multiple of those services simultaneously. If you manage to have just a bit more complexity in your system, those problems won't come out until the massive full-system integration test. You know, the one you can't do yourself, and even your whole department can't do. Oh-oh. That's an awfully long feedback loop to find those 3 dozen places where you forgot to copy that field across.
- aidos 12y agoI enjoyed the article. As ever, there are tradeoffs and your milage will vary using different approaches. This doesn't seem like an entirely fair comparison: "It seems to me that all three of these options are sub-optimal as opposed to writing the piece of code once and making it available throughout the monolithic application." There's a different scenario that could have played out with how to share a library between different services. You could have written the bulk of your application in the same language, like a monolithic application but split into several services. In that case you could create a library for your tax calculations and use it freely within your services. For me, I split my application into a small number of services and, as much as possible, split things out into libraries to make reuse simple (more libraries, thiner applications). Sometimes I use different languages, but when I do, I consider very carefully whether the (rather large) tradeoff that presents will be worth it in the long run for what I'm getting in the short term. A question: when people talk about microservices, how small are they talking?
- blatherard 12y agoThe OP addresses this as one of the three options: The final option is to share resources such as a tax calculating library between the services. This can be useful, but it won't always work in a polyglot environment and introduces coupling which may mean that services have to be released in parallel to maintain the implicit interface between them. This coupling essentially mitigates a lot of the benefits of Microservices approaches.
- aidos 12y agoI rambled a little - my point was that by avoiding te polyglot language situation you make things easier (and closer to the monolithic application). I take the other point though, parallel releases are harder.
- polskibus 12y agoIn my opinion the article does not put enough weight on lack of transactions in a microservices architecture. Of course you can add distributed transactions, but doing so makes the architecture much more intertwined and much less error-proof.
- macNchz 12y agoIt's always fun diagnosing rarely occurring race conditions in a system with many services, work queues, some eventual consistent components, and various databases with their own transactions.
- ExpiredLink 12y ago> Implicit Interfaces This is a crucial point. 'We use microservices' does not say much unless you can describe how you design consistent and granular service interfaces. Otherwise you most probably just produce microservice spaghetti.
- gbog 12y agoListing the difficulties on microservices is useful, but let's not forget the difficulties encountered in monolithic big applications, which are the reason for splitting into smaller pieces. In the big app 1) a single syntax error breaks everything. 2) simply loading all the app takes a huge part of ram, and tests are very slow. 3) there is a gigantic dependency tree, as when you depend on a module you also depend on every ones of the module dependencies. 4) Almost no one knows everything about the app. 5) it is impossible to split the company into separate services without getting fights about shared code and architecture decision.
- jacquesm 12y agoAnd it is much easier to test a microservice than a monolith. (Going on the assumption that you do spec out the interface to your microservices with some care.)
- ericb 12y agoIf you have a microservice, typically that means a REST API. -Tests for all response codes -Test for all failure modes (timeout, service down) -Load tests both services. -Two sets of deployments to test. -Two healthchecks to test. Seems harder to test, not easier.
- possibilistic 12y agoHTTP is pretty terrible at cancellation, retry, cluster load balancing, in-channel health checks, etc. Some form of RPC is better suited for non-web facing APIs. And yeah, I agree that it's absolutely harder to test. (Integration test especially.) But you gain a lot for the trouble: independent deployability, scalability, dynamic traffic shifting, easy sevice boundaries and ownership (data stores, state, downstream deps, etc.). For a large company, this makes a lot of sense. Edit: microservices are not the easy path.
- jacquesm 12y agoLike with any tool, misapplying is worse than not having it. I think a big problem with microservices is that people that really don't need them think 'neat idea' and start implementing what would be otherwise trivial products using a whole slew of intercommunicating services. They get all the downsides and probably very little if any of the upsides that way. If you don't need it it's best left alone but if you do need it it can help structure a large project in ways that would be otherwise hard to achieve.
- Someone 12y agoSee also: - Subroutines - Not a free lunch - Libraries - Not a free lunch - Client-Server - Not a free lunch - OO - Not a free lunch - Multiprocessing - Not a free lunch Many of these arguments apply to these, too. The main difference is that of scale. Latency and call overhead are way larger than for the examples I gave. Improved tooling can bring both down, but not by that much. That's why you will not see many micro services that are truly micro. You won't see (I hope) a 'printf' micro service, or not even a 'ICU' micro service. A regex service might make sense, if the 'string' it searches in is large and implicit in the call (say a service that searches Wikipedia), but by that time, it starts to look like a Database query. Is that still micro?
- parasubvert 12y ago"Micro" is relative, keep in mind PC's and Macs were once "microcomputers". Microservices (as described by Amazon, Netflix, and Thoughtworks) are effectively indistinguishable from Bounded Contexts (from Domain-Driven Design). http://martinfowler.com/bliki/BoundedContext.html http://martinfowler.com/bliki/BoundedContext.html They're all about effectively decomposing large applications into independent teams and runtimes.
- possibilistic 12y ago(My company loves microservices, so I'll weigh in at a really high level.) The author speaks of the complexity in managing and coordinating processes in a distributed system. By designing a microservice, you trade simplicity of software design for increased operational complexities. There's a shift in terms of problem solving too--it migrates from the cross functional engineers to the DevOps and distributed systems engineers. Don't get me wrong--I think microservices are brilliant and make reasoning about application design easier. But be prepared to bring in some heavy engineering talent to coordinate all the things. Until there are open source frameworks for handling the difficult bits, it might be unwise for a start-up to go the microservice route. Microservices are purposed for scale (since reasoning about traffic is easier with a simpler service and there predictable traffic patterns from a microservice's clients). Edit : In terms of the examples you mention, I you may have the wrong idea. Think about fulfilling a specific goal or class of functionality, and make that a microservice: email gateway microservice, user/session microservice(s), SMS gateway microservice, etc. Each is a component that responds to various request types (you really should use RPC instead of REST for deadlines, retries, cancellation, pooling, etc.), but they all sit within a single domain of purpose. The service could be stateless or not, but you try to make the requests idempotent to aid client reasoning. To again cite your example, several services may use regex, but there might be only one authority on "normalized input" (eg. addresses, etc.). Or maybe there is a client lib for that. This brings up another point. Services at the periphery (dependency graph-wise) are coordinated by interior services. That can get complicated...
- mavdi 12y agoI've pretty much faced all of the problems mentioned in this article. An application is set of services with a certain complexity that work together. In some cases this complexity just gets transferred from service level to orchestration level. Don't get me wrong, I love microservices and will try to use them in all my future work, but I think where people often go wrong is that they over commit to it without realising the downsides. I often see people casually using AMQP queues for pretty much everything, only when they need the worker service to talk back to the originating service that they realise they've made a wrong architectural decision.
- muffs 12y agoCan you elaborate on your latter point? Why is that considered an incorrect architectural decision?
- marktangotango 12y agoFor example if the caller needs the result of a possible long running task, ie success or fail, then it has to maintain state in a way to associate the async queue message back to the task. Zeromq has the concept of request/reply to handle this, its more problematic with plain old queues, the solution ive worked with is mq for tasks, rest calls for results. Yes it sucks.
- muffs 12y agoAwesome, thanks for the explanation.
- icedchai 12y agoI worked with some guys once who put every HTTP REST request in to AMQP. And every response. There were temporary queues all over the place to allow for communication between the front end and back end servers. It was a complete joke of a system.
- programminggeek 12y agoFundamentally, there isn't a huge difference between microservices and monotlic apps if both systems do the same thing. However, a lot of the issues of general complexity are more apparent in one approach or the other. For example, breaking changes are breaking changes in either system. It's not an issue of architecture style, it's a matter of business needs changing, and thus protocols change. A change in protocol breaks the existing protocol. We understand this intuitively when you are talking about a de-facto protocol like HTTP, but we seem to think our own programs are somehow different. They aren't. Architecture is about taking the essential complexity of a problem and creating components and protocols to solve a problem in a way that makes the most sense for the team trying to solve it. Monolithic apps or microservices then should be a question more of what your team is going to execute well as much as it is a question of which structure more elegantly solves the problem at hand.
- blablabla123 12y agoWhy is highavailabilty.com slower than most other websites? :>
- ExpiredLink 12y agoBecause it's highavailabilty.com, not highspeed.com.
- matthewmacleod 12y agoNot a fan of microservices myself - IME it pushes the complexity that exists in any application into implicit interfaces and dependencies between microservices. The difference is that we have better tools for managing this complexity at the application level than we do at the operation level. Still a big proponent of SOA generally, though. I think the granularity when defining "service" is ultimately going to vary from application to application, however, leaving the sweet spot slightly larger than e.g. Amazon's microservices.
- parasubvert 12y agoI'm not sure I understand this. SOA == microservices, basically. Arguably one could say that Microservices = SOA minus ESBs, which is what necessitated the new term. IOW, don't hide your mess of dependencies in a black box, expose and manage them where they're needed. The granularity of the service is generally determined by the size and responsibility of the maintaining team, and will vary from company to company. With regards to tooling, I'm curious what you're referring to. Some selection of tools like Splunk, AppDynamics, New Relic, or Boundary certainly can handle both applications and microservice chains, no?
- matthewmacleod 12y agoI've reconsidered what I wrote above – you're right. I'd built a mental model of what "microservice" and "SOA" meant that apparently isn't entirely in line with what others are commonly using. I maintain that it's not a panacea, and that complexity is pulled into other places (operations) where we perhaps don't have equally effective tools at this point. I'd also argue that it's difficult to understand the correct level of granularity (and potentially expensive to fix errors in this decision). But it's not the problem I made it out to be.
- parasubvert 12y agoI agree with the above. It's not a panacea but it seems to be worth exploring further as a way (not THE way) to manage (not cure) scale/complexity in multi-team environments.