When I see a team of 7 deciding to go with microservices for a new project I know they're gonna be in for a world of unnecessary pain.
When I see a team of 7 deciding to go with microservices for a new project I know they're gonna be in for a world of unnecessary pain.
hahaha
Do you know if there are some well chronicled cases of this happening? I find it very believable, but you know, would love to read something "actual".
A kinda-random example off the top of my head of "shipping the org chart" would be the historical gaps between Windows, Development, and Office at Microsoft. Ie Office is getting a new ribbon, but no development can't supply those icons or any components because they're an "office thing", or the internal API/VBA battles along the same lines.
On the opposite side, as reported in the press, Amazon has used this effect to create manageable teams and build up their own SOA: the two-pizza rule for teams means that teams can only really make targeted self-contained services. In this case Amazon worked backwards and re-structured their teams so that 'shipping their org chart' created the desired architecture.
Microsoft has an app store built into every Windows 10 computer worldwide. And of course, you can not download Microsoft Office from it. However, it does helpfully tell you to get Office by heading to 'MicrosoftStore.com'.
It's all sort of head scratching. A normal person might ask a lot of totally reasonable questions about this, like:
- Why does Microsoft's App Store not have Microsoft's own Apps in it? Office isn't the only missing app, Visual Studio is missing too (even the free 'Code' electron editor).
- Why does the phrase 'Microsoft Store' refer to something 100% different (in products and functions) than 'MicrosoftStore.com'?
- Why does the Office team have their own app updating utility, when there's already supposed to be one 'blessed' place for App Updates inside the Store? (Same question for Visual Studio Code).
---
Anyway, I know a lot of the above is org chart related, or enterprise needs / backwards compatibility related. But they are all reasonable questions despite that.
And stuff like this is part of the reason why reasonable people still fall for phishing schemes. The above sounded to me like some weird popup advertisement trick, until I saw it first hand.
(Isn't it the only way to get Apple software for your Apple devices, even?)
Not that this actually happens-or would be a particularly good idea if it did for other reasons (like breaking up teams etc).
It does have a single point of failure that is also a bottleneck (the router) and it's a lot of work to load balance / failover it.
But other than that, it provides a fantastic way to make microservices:
- anything is a client of the crossbar router. Your server code is a client. The db can be a client. The web page JS code is a client. And they all talk to each others.
- A client can expose any function to be called remotely by giving it a name. Another client can call this function by simply providing the name. Clients don't need to know each others. Routed RPC completly decoupled the clients from each others.
- A client can subscribe to a topic at any time and be notified when anothe client publishes a message on that topic. Quick, easy and powerful PUB/SUB with wildcard.
- A client can be written in JS (node and browser), Python, C#, Java, PHP, etc. Clients from other languages can talk to each others transparently. They all just receive JSON/msgpack/whatever and error are propagated and turn into the native language error handling mechanisme transparently.
- The API is pretty simple. If you tried SOAP or CORBA before, this is way, way, way simpler. It feels more like using redis.
- It uses websockets, which mean it works anywhere HTTP works. Including a web page or behind a NAT or with TLS.
- Everything is async. The router handles 6000 msg / s to 1000 clients on a small Raspberry Pi.
- The router can act as a process manager and even a static / wsgi web server.
- you can load balance any clients, hot swap them, ban them, get meta event about the whole system, etc.
- you can asign clients permissions, authentications, etc. Sessions are attached to each connexion, so clients knows what other clients can do.
Service Lookup - Hashicorp's Consul.
Authorization/Authentication - I've played with Hashicorp's Vault. It seems overly complicated but the advantage is that it doesn't tie you to a single solution and it can use almost anything as a back end. I haven't had to solve that problem yet.
Had to implement a micro-service architecture in python about a year ago and was jealous of my Java colleagues who (so I heard) have great ecosystem for enterprise service discovery, messaging etc.
Faced this a couple of years ago, and I was the lone dissenting voice suggesting this was not going to go well. Then I learned that "microservice" in reality just meant everything was going to be one nodejs process running endpoints, with ios and android clients hitting it, which... didn't really fit my understanding of "microservice"; that's just "service".
Also, the same team spent several hours in meetings deciding whether or not to allow email signup, or facebook signup, or both, or neither, in the mobile app. Then had the same discussions/arguments a few weeks later when a couple new people joined the team.
I realize I sound a bit bitter. I got pushback because I'd used the 'microservice api' in a "we don't like that" language. consuming the api (which I'd understood to be part of the reason of having a central API vs just hitting db tables directly) by anything that wasn't also node was outside the groupthink, and caused problems.
I left the project.
They've got their microservice architecture, but no userbase (yet?) to be concerned about scaling issues.
I understand it's reasonable to be concerned about potential scaling problems, the team/project spent far too much time chasing architectural perfection (and really... 'shiny new stuff') vs executing a marketing plan. It's easier for a group that is tech-folk-heavy to focus on that; I get it. But it didn't solve any problems at hand. But when the mythical "2 million users in an hour" problem happens, it'll probably hold up, unless it doesn't.
I chose this approach because the developers who were already there were relatively new to C#, and I knew we were going to have to ramp up contractors relatively fast.
Our dev ops process revolves around creating build and release processes by simply cloning an existing build and release pipeline in Visual Studio Team Services - the hosted version of Team Foundation Services - and changing a variable. Every service is a separate repo. Each dev is responsible for releasing their own service.
The advantages:
1. All green field development for a new dev. They always start with an empty repo when creating a new service.
2. Maintenance is easier. You know going in all you have to do is use a few documented Postman calls to run your program if you need to make changes. Also, it's easy to see what the program does and if you make a mistake, it doesn't affect too many other people if you keep the interface the same.
3. The release process is fast. Once we get the necessary approvals, we can log on to VSTS from anywhere and press a button.
4. Bad code doesn't infest the entire system. The permanent junior employees are getting better by the month and we are all learning what works and doesn't work as we build out the system. Each service is taking our lessons learned into account. We aren't forced to keep living with bad decisions we made earlier and building on top of it.
A microservice strategy only works if you have the support system around it.
In our case, an easy to use continuous integration, continuous deployment system (VSTS), easy configuration (Consul), service discovery and recovery (Consul with watches), automated unit and integration tests, a method to standardize cross cutting concerns
And finally, Hashicorp's Nomad has been a god send for orchestration. Our "services" are really just a bunch of apps. Nomad works with shell scripts, batch files, Docker containers, and raw executables. It was much easier to set up and configure than kubernetes.
Imagine you have a library that implements the serialization and deserialization of something in your system (or anything else where the library implements two "halves" of some functionality). You might (or might not, depending on the change) need to push out that library to other apps to effect the fix you're working on. That new proposed library change may be in a queue behind another pending change that's in development, etc.
And guess what, you have to do the same thing with microservices. You must ensure that all its clients are pointing to the correct version, and you must ensure that the new version didn't add any bugs in the clients.
Adaptations for new service versions will also get into the release queue, and can also get blocked by other stuff.
YAGNI is almost always the right approach.
There have been plenty of times where I've taken a project out of a monolith and created a separate shippable package to be consumed by another monolith in a separate repo.
There were also occasions where I had to rip out a feature in a monolithic API that either needed to scale independently or be released independently and then just created a facade in the originally API that proxies the "microservice".
I mostly tell my people "We aren't going to do that yet - or possibly ever - but keep in mind that we might have to if we ever win the user growth hockey-stick graph lottery, so when choosing between options of how to architect things, prefer very narrow focus that _could_ be pulled apart into microservices more easily if practical"
I've also been known to stand up duplicated instances on a monolith with path routing on the load balancer as a "pretend microservices" scaling or upgrade trick.
Decomposing and fragmenting an established service into smaller clones of itself should be reasonably straightforward. In most languages with a component story (ie java), library reuse across microservices should make your service architecture orthogonal to your application logic. This kind of approach also eases a lot of pain of cross-service issues.
These days I kinda wince at "I run 8 services myself."
If it takes 1 person to run 1 microservice, we are all doomed.
Higher levels of abstraction makes it easier to get something up and running fast, but at some point you need to be able to look under the hood and understand what's going on, and many programmers today can't do that.
That being said I think the drop in average skill is mostly a product of the growth in the number of programmers. I imagine that if the ability to sculpt a basic statue suddenly became really valuable, the skill level of the average working sculptor would plummet.
More layers of indirection in a system and more dependencies on external libraries and tooling does not necessarily get you any abstractions. To take a contemporary example, there is no "abstraction" in being driven to use Docker because your dependencies have gotten unmanageable otherwise.
I also feel that ceteris paribus, the meetings got longer, project management tools now consume a lot of input from programmers, and I need to communicate with a lot more people to get something done.
Which seems to end up meaning productivity has gone down when measured by "things end users of websites can do", even though modern FE devs end up creating much more code and html and css than "the old days". (Admittedly, if you include privacy invasion, user tracking, and various other requirements of surveillance capitalism, dev productivity has probably skyrocketed...)
Complex? We still call a function with a return value on a stackmachine.
Sorry for the negativity.
And yet, most homepages today can't be viewed without javascript. You are correct, for the end user the complexity has absolutely not resulted in better homepages but worse.
seq 21 | while read port; do
python2 -m SimpleHTTPServer 80$port &
done seq 21 | while read port; do
python3 -m http.server 80$port &
done
FTFYSo if Netflix has a "User logon" service, and a "payment processing" service, used across their clients clients you might be looking at a couple of "microservice"s with hundreds of related employees. Imagine services for Googles search autocomplete, ML, or analytics...
As the article states the "micro" aspect is mostly in terms of deployment responsibility, freeing those 10-1000 employees from thinking about the totality of Googles/Netflixes' operations before rolling out a patch :)
It’s 8 or so but it’s possible for me to handle it all. If we add features they’re going to be new services, so adding big features to the services I manage is unlikely. It is more likely that I get a new service on my plate in 6 months time than getting additional members of the engineering team to work on already completed services.
I’m obviously not entirely alone... I’ll ask for help if I need it, and I help out with other people’s stuff too, but I am primarily in charge of them and I am responsible for keeping everything working well.
If it takes 10 people to manage one service, it is not a microservice by definition. It is more like a 10x-microservice or a macroservice.
The definition isn't small teams, per se, it's a small area of responsibility with singular focus. A lego block instead of duplo. That lends itself very well to small teams, but you could reasonably have 100 people working on a service and call it "micro".
Reason being: if those 100 people weren't working on their scoped 'microservice' they would be part of a much, much, much larger pool working on the shared 'product', 'platform', or 'service' that contains that exact same functionality, only without the clarity/scalability of application boundaries surrounding the individual service components.
That's not to say microservices are ideal, just that the size of "micro" is highly relative to ongoing operations.
One developer can certainly be responsible for coding many microservices and even maintaining them depending on the scope, number of users, etc.
Sometimes people might even rotate with a core architect coordinating how they all interact and if they are consistent with each other.
Discussing about microservices can be very confusing if people are thinking about different things and, as always, when there's a good idea implemented in a specific context and people who don't use it get exposed to it as a silver bullet we'll end up with a huge backlash like in this article.
And it's just one of many.