Challenges of micro-service deployments
techtraits.com
techtraits.com
1) massive projects with lots of developers/teams that work on well-defined functionality
2) massive projects that need to have precise capacity at each service level rather than the application level
Other than these situations, monoliths (both in architecture and deployment) will likely be faster, easier, more reliable and more productive.
1. Software stacks for MSAs dovetail too well with the cloud service offerings from the same company or a division of the parent (EMC/Pivotal)
2. Latency kills. How are you avoiding it with highly distributed choreographed flows that are present in MSAs?
Our microservices are reusable. We have lots of user-facing apps -- different web sites, each with their constellation of services required -- that all use an overlapping set of microservice backends. If we have a new app, we are usually able to write it entirely as a front end. We pick and mix those backends we need.
For example, we have microservices for: Identity/auth/authorization; messaging (SMS, email); image processing; geocoding and various other GIS operations; event logging; site map management; and so on. One of most important services manages data as documents, with data in Postgres and queries through ElasticSearch, with a fine-grained security system. All our apps use it, and many of the microservices are layered on top of it.
With a monolithic architecture we would have been forced to write this stuff as libraries, and forced our apps to use a single language. (Our microservices are written in Go, Ruby and JavaScript.)
For example, our image scaling pipeline runs multiple processes per machine, all coordinated through RabbitMQ. Ideally we'd scale deployment automatically based on the number of queued-up tasks, but we don't have the infrastructure set up for that at the moment.
There's also language issue, as mentioned: A library-oriented design would require everything to be written in the same language (modulo anything you can do with C bindings and such — no thanks!).
We have stuff written in three different languages, and it's actually very nice to be able to do that, and not worry about language-level compatibility. For example, we are in the process of writing a completely new data backend in Go (the old one is Ruby). We have that choice because no app needs to care what it's written in.
Having each microservice be its own app also forces you into a different and, in my opinion, healthier "shared nothing" mindset. You're not allowed to cheat by bypassing the API and tightly coupling yourself to the internals of the implementation, which in turn forces you to design good distributed APIs.
Of course integration had to happen either way, and it just kicked the can down the road and made it a "dev ops" problem. (Dev ops in quotes because real dev ops wouldn't have been a separate team in the first place)
The point is, you have to integration test, you have to define an API, you have to not make breaking changes, and you have to do all these things regardless of deployment modality.
Beware the disguised call for microservices which is really just a request "not to worry about integration testing".
Imagine, you join a company and their product is one, ugly monolith with a lot of technical debt. Now, you need to build some big and complicated features on top of this, and there are no similar features so far. Implementing it as a service can be much faster, have quicker iterations (especially if the deployment methods for the monolith are crap, which is often the case) and easier to build a high quality implementation. As long as you don't go crazy and ended up with ridiculous number of poorly separated services, this might be a good decision in long term (been there, done that).
Based on anecdotal data (where n=3), that's very often the case.
This 100x. With a monolith, you can get away with SSH'ing into boxes once in a while to fix or debug stuff. Micro-services must be automated.
That's not to say Microservices are the answer. The answer is a dev environment and proper debug/bug fix procedures.
If you ssh into the box, check some logs or something, find wrong configuration option and then roll out the new configuration in an automated way then that's all good.
The problem comes when you change the configs manually over ssh and call it a day. A few fixes and a few months later, no one really knows how to set up some service because of those undocumented fixes (infrastructure automation serves as documentation). Now image that you have a dozen of services, some people quit, some people join, a year or two of manual fixes passes... And you have an awful mess where no one knows how to set up the services and just hope that you won't need to setup any new servers or migrate to different ones.
Microservices just demand it more, but it's just as useful and necessary with monoliths.
By the way, monoliths describe both the architecture and deployment package. You can have microservices that are deployed as a monolith (like a single binary for example).
All that being said, the above setup only addresses about 1/2 the problems mentioned in the post.
I've seen this before and I've always been suspicious of it. So if version 1 has field r,g,b and version 2 has fields r,g,b,a and i use version 1 in a version 2 stack any data on alpha field is ignored. O.k. so you didn't get a stack trace, but is that working software?
If code was written that expected version 2, and a version 1 object was provided, the static type checker would catch it at compile time.
But with microservices, there is no static type checker and you're essentially coding as if you were in a dynamically typed language.
Hopefully you've at least set up integration tests where you can test the service you're about to deploy against the others, but I think in many microservice situations the only integration testing that happens is in production.
https://blog.codeship.com/exploring-microservices-architectu...