19 ms·
Starting with microservices
- guntars 5y agoThere's something to be said about the benefits of having a serialization boundary between parts of the code that's a natural consequence of microservices, but it's something that could be employed in a monolith just as well. Then if at any point you actually need to split out a module into its own process or machine, it would be trivial to do.
- AtNightWeCode 5y agonoob
- yawnxyz 5y agoI don't understand why people treat microservices or monoliths as either or. If I find my various projects using the same functionality over and over, then I'll split that off as a microservice to serve my monolith projects of various sizes. It's like functions: don't turn code into a function until you need it in three different places.
- galovics 5y agoI agree but the trend still seems to prefer one or the other and that's why it's so important to talk about the potential downsides instead of closing our eyes and saying everything is gonna be better if we do microservices.
- foobarian 5y agoMaybe it's just the activation energy. Until you have the setup for making a microservice, you're kinda limited to a monolith. Once you pay the setup cost though, making incrementally more services is trivial so you end up on the other end of the spectrum.
- marcus_holmes 5y agoOr you could have it as a module/library that you import into all your monoliths, and save the communication overhead. But then, I'm firmly in the old-skool "don't split the monolith until you absolutely have to" camp.
- m4l3x 5y agoIn my opinion implementing strong interfaces and good modularization is something, that we should talk about more, than doing Microservices. In the end it might be easy to rip of a Microservice, when needed, if the code is well structured.
- fatnoah 5y ago> In my opinion implementing strong interfaces and good modularization is something, that we should talk about more, than doing Microservices. This is my position as well. Strong interfaces, good logical separation of function under the covers, etc. should allow splitting off things at whatever level of micro you prefer.
- jerf 5y agoThis is what I do in practice. I've seen it called a "distributed monolith". One of the good reasons to spend time with Erlang or Elixir is it'll force you to learn how to write your programs with a variety of actors. Actors are generally easy cut points for turning into microservices if necessary. As with many programming languages I appreciate not being forced to use that paradigm everywhere, but it's great to be forced to do it for a while to learn how, so you can more comfortably adapt the paradigm elsewhere. My Go code is not 100% split into actors everywhere, but it definitely has actors embedded into it where useful, and even on my small team I can cite multiple cases where "actors" got pulled out into microservices. It wasn't "trivial", but it was relatively easy.
- ravi-delia 5y agoThat's where a lot of the fun of Elixir comes from I think. It's viscerally satisfying to split off functionality into what almost feels like an independent machine that happens to be in the same codebase. It clicked in a way normal object oriented programming never did for me, I guess since it's not feasible to mint 10,000 genservers to use as more complicated structs.
- cultofmetatron 5y agohaha I was thinking the same thing. The code base of my startup is a monolith but in reality its a fork on request webserver sending messages to a collection of genservers actings as services. In essence, creating a microservice with elixir is about the same amount of effort as adding a controller in rails.
- marcosdumay 5y agoDo you know what kind of software has an absurd level of horizontal scalability by default? Web servers. The idea of splitting your web servers into multi-tiered web servers for scalability is, well, weird. Yet, somehow it's the main reason people keep pushing it. Even this article repeats this. There's nothing on microservices that adds scalability. They make it convenient to deal with data partitioning, but it's an ergonomics change, not one of capability.
- antihero 5y agoI guess the idea is to split the workload into parts so if one part of the workload is proving to use more resources, it can then get a larger dedicated pool of resources. Plus being able to choose different tech for different types of work, and also being able to split between teams when your org gets more vast. Though I guess this is more about using services than micro services, per-say.
- delusional 5y ago> but it's an ergonomics change, not one of capability. Isn't that a bit of an empty argument. Literally anything Turing complete is an ergonomics change when compared to anything else Turing complete. We are writing for the same computer. There's nothing different (fundamentally) about the kernel and my program.
- marcosdumay 5y agoHum... You won't model scalability and concurrency using Turing machines. The Turing model is all about theoretical computation and those two parameters are all about real limits. What you have on your desk isn't equivalent to a Turing machine.
- Nextgrid 5y agoI never got the “scalability” argument of microservices. You can trivially deploy multiple instances of your monolithic web application - chances are you’re already doing so by running multiple workers/threads in your application server. Spreading that to other machines is trivial. The real issue is in scaling the data store. Microservices typically work around that problem by each having their own separate database, but nothing prevents your monolith from also talking to different DBs.
- scanr 5y agoI have a theory that auto-wired Dependency Injection in a single DI container is partly to blame for monolith spaghetti. Once an app reaches a certain size and anything can depend on anything else, reasoning about the whole can become difficult. I think there is value in wiring a monolith together in such a way that each course grained subcomponent exposes a constrained interface into the rest of the system (payments, orders, shipping, customers etc) before needing to break it into distributed micro-services. Note: I quite like Dependency Injection, I just think the 1 giant bag of dependencies can lead to complexity at scale.
- lmilcin 5y agoI wouldn't blame (badly implemented) DI for all the problems of monoliths. I think the real main issue is lack of discipline when dividing the application into modules. Spaghetti is basically defined as an application where real modularisation does not exist and everything talks to everything. It is much easier to work with an application when you can abstract parts of it when you are solving your problem. You effectively work on much smaller part of the application. Spaghetti == you effectively have to take into account possibility of the piece of code you look at interacting with any other piece of code in the application. Well modularised application == you only need to take into account the contents of your current module and the interface of the other modules you are using. One reason why microservices sort of work (when done well) is because they force people to think about APIs and how those services talk to each other. In most cases you could just put these microservices as modules in a monolithic application and expend the effort on ensuring APIs and application structure. I have successfully rolled back couple microservice initiatives by integrating services into monoliths. This usually results in the team getting back a lot of their time because their environment suddenly became much simpler. Less applications to manage, less network communication, less possible ways for things to break, less frameworks, less resources needed to run the application, less processes (like processes around deployment, release management, etc.), less boilerplate code, and so on. The list is very long. Of course, when you work on a large monolith vs a lot of small microservices, it is now important to be able to structure your applications. But there is also an opportunity for improvement.
- 5y ago
- bob1029 5y agoI have done the full theme park ride on monolith->microservices->monolith. Both have ups and downs. The most important thing I learned is that "microservices" in absolutely no way necessitates "bullshit spread across multiple cloud vendors and other scenarios involving more than 1 computer". What part of microservices says things must be separated by way of an arbitrary wire protocol? We now have a "monolith" (process) that is comprised of many "microservices" (class files), each of which is responsible for its own database, business logic, types, etc. These services are able to communicate amongst themselves using the simple path of direct method invocation. If you are looking to scale up your capacity or even make things more resilient, microservices vs monolith is really not the conversation you need to be having. If you are trying to better organize your codebase, you might be in the right place but you also need to be super careful with how you proceed. We wasted a solid 3 years trying to make microservices solve all of our problems. Looking back, we spent more time worrying about trying to put Humpty Dumpty back together again with JSON APIs and other technological duct tape than what our customers were complaining about.
- crdrost 5y agoYeah, the biggest problem that people get into with microservices is that they allow the communication structure to dictate the app structure. A monolith gives you some refactorability because you can run what would have been "integration" tests locally, as you massage your module boundaries to match the problem that you're solving. So a monolith can become a clean monolith, and then a clean monolith can maybe become microservices if you need the scale attributes. The basic problem is that before you know where the module boundary is, you cannot have a clear module boundary. So three popular approaches emerge: (a) DDD "milliservices". Basically define the different sorts of users, come up with a clustering of the different sorts of people that you think will be using your app. People are considered to be in the same cluster if they use the same jargon to refer to things, or different clusters if they both use some word but they both mean subtly different things by it. (b) Gut-feeling microservices that become feature microservices. I should probably have an "auth service," I don't know what it does but I'm going to be doing auth so that's probably a service. I need to import a git library to contact GitHub, probably there should be a "git service" that handles all communication to GitHub or other git repos. Each of these things exposes some swagger/openAPI docs, maybe we should have a docs service? -- that sort of thing. The danger is that the things that are easy to break off are usually not the core competency of the product, and so there emerges some sort of "core services," one or two big honkers that basically are monoliths. People are aware that they aren't supposed to keep adding to the core services and so new services emerge named after feature requests, hello "sharing service," hello "wallet service." Except the core usually is tightly coupled to these new feature services and they all kind of connect to each other. The idea of splitting the core services into other services to fit the newfound module boundaries becomes complicated by all these ties to nearby features, you are not actually loosely coupled because you do RPCs and you probably code in the expectation of success into these RPCs like method calls. (c) Every noun becomes a "nanoservice". This is a service that watches just one or two tables (or NoSQL document types or what have you) and exposes a CRUD API for that noun, plus a couple auxiliary verbs to do actual business needs with those nouns. So if you were implementing Git there would be a file service, a tree service, a branch service, a commit service, probably a working tree service... But you just have to "know" that logs and rebases and cherrypicks live in CommitService while diffing for some reason lives in TreeService and adding a file to your working tree requires first creating it in FileService and then handing that link off to the WorkingTreeService which will make needed calls to TreeService, creating your own tree is exposed via TreeService's CRUD but the developers tell you that down that road There Be Dragons and you should not have been messing with that. Any of these three can be successful but only insofar as you can create new module boundaries and move module boundaries and test to make sure that your users will not notice any performance regressions. Of them I would only recommend option (a), because it gives a really nice place for these tests to live and an intuition that each test should document a user journey for the system.
- a45a33s 5y agoi think everything is already covered with this video https://www.youtube.com/watch?v=y8OnoxKotPQ https://www.youtube.com/watch?v=y8OnoxKotPQ
- cbkeller 5y ago> I’m still not understanding this… why is it so hard to display the birthday date on the settings page?
- speed_spread 5y agoTL;DR - don't. (which I agree with)
- kosolam 5y agoThe author needs to express itself more succinctly, maybe it will help also with his architecture struggles
- monocasa 5y agoI've come to the conclusion that microservices as usually implemented are simply a Conway's law concern. We haven't had a great track record defining the semantics of component boundaries, but http is both simple enough that it constricts code flow in a particular way leaving a lot of misunderstandings and bike shedding discussions off of the table, and is the ligua franca for external services owned by other orgs so your engineers can be universally expected to understand those semantics. There is a nice decoupling of letting teams make technology choices though. Letting that drift on a per team basis is kind of nice to allow experimentation with different technologies without having to get the whole org onboard. Maybe I need to go on the talk giving, consultant circuit reselling a restricted view of DI as "hybrid service architecture! Write your code as microservices but DevOps can colocate your apps in the same process if that's more efficient!" Lolz It's also quite a nerd trap as we developers love to separate components into as small of boxes as possible, but just like I've seen super deep object hierarchies that didn't gain you anything at the end of the day, it's easy to fall into the trap of spinning every tiny bit of code into its own service. I'm creating my own backend arch right now from scratch, and really trying to look at each network traversal from a "what does drawing this boundary actually get me" perspective. And I'm only splitting that out because the third party protocol being implemented is inherently separate services in an interesting way.
- karmakaze 5y agoSpot on. Microservices is a way of scaling people. There are other ways of scaling systems. I would suggest that http not be the go-to mechanism for communicating between microservices. Each should be able to operate to some degree without hard dependencies. If you build using microservices with RPC over http or what-have-you replacing function calls, you've done it wrong. You can usually tell if your 'bounded context' is of the form noun-service or adjective-noun-service. Usually the context boundary should be a process (workflow kind) that serves a user type. Reliable one-way async datastreams are more useful for keeping microservices fed with the information it needs, and it can decide how to utilize that information in a way that makes sense for that service. If you have core 'source of truth' services used by many others, you have a distributed monolith.
- scottious 5y ago
- jiggawatts 5y agoArchitecture astronauts love microservices. I'm watching a government customer take simple, cohesive systems developed by a small team (4-5 people) and split it up into tiny little pieces scattered across different hosting platforms and even clouds. Why? Because it's "fun" for the architects and pads out their resume. Just now, I'm watching a "digital interactions" project that will have dozens of components across two clouds, including multiple ETL steps. In all seriousness, half of that could be replaced by a database index, and the other half with a trigger. They're seriously going to deploy clusters of stuff on Kubernetes for 100 MB of data to make sure it "scales"... to 200 MB. Maybe. Eventually. What kills me is that now that they've made the decision to over-engineer the thing, my consultancy firm can't bid on the tender because we don't have the appropriate experience building over-engineered monstrosities! The simple and effective solutions to problems we've delivered in the past are disqualifying us from work. You guessed it: my next project will be an architect's wet dream and will be over engineered just so that we can say on tender applications that "yes, we have the relevant experience". Gotta play the game by the rules...
- pphysch 5y agoI'm involved in a (greenfield) project right now where the lead insists on gluing a bunch of Google Sheets/Forms/Docs/whatnot together with triggers and custom APIs (roadmap TBD) instead of just building a simple website in $framework. Fingers crossed he doesn't discover k8s...
- wmichelin 5y agoDo you feel those hosted solutions are worse than rolling your own website? Why stand up your own website and architecture if you can use off the shelf solutions? I am genuinely curious.
- rgbrgb 5y agoFor me it's a judgement call based on how easy to integrate the hosted solution is, how much lock-in there is, how much flexibility I think we'll need, and how fast we need to ship. One definite disadvantage is testability (which drives stability and ease of refactoring). I can write an automated end-to-end test that will enter some text into a CMS on my site, hit submit, then verify that a post was published. If the CMS is google sheets, I'm going to violate some terms of service and possibly get a blacklisted IP if I do that. Instead I'm going to mock out a response according to the API contract sheets gives me. If they change the API in a subtle way, it may break. An advantage is that google sheets is probably more robust than my CMS and I'll never be able to look at (or have to fix) their code. Flexibility cuts both ways: I can't add features to sheets. So if there's a field I really need to validate on the client, I'm out of luck. But also nobody is going to ask for that feature because I obviously can't add it, so that may be good assuming there's a workaround.
- marginalia_nu 5y agoLifecycle management is also a big part of it, I think. My search engine is a hybrid architecture, with some monoliths and some microservices. * Index - 5+ minute start time and uses 60% of system RAM.; * Search Server (query parser, etc.) - 30 second start time due to having to load a bunch of term frequency data, low resources, ephemeral state * Assistant Server (dictionary lookups, spell checks, etc.) - fast start, medium resources, stateless * Crawler - only runs sometimes, high resources, statefull * Archive Server- fast start, low resources, ephemeral state * Public API gateway - 5 second start time, low resources, ephemeral state + a few others A lot of the ways it's divided is along the lines of minimizing disruption when deploying changes. I don't have the server resources to run secondary instances of any of these, so I'm working with what I've got. If I patch the crawler, I don't want the search function to go down. If I patch the search function, I don't want to have to wait 5 minutes to restart the index. It would certainly be cleaner to say break apart the Index service in terms of design, as it does several disparate things, but those things have a resource synergy which means I can't, not without buying another server and running a small 100 GbE network between them. Seems silly for a living room operation.
- teekert 5y agoWe have a big codebase where I work and it’s written as a set of micro services. I’m a bit of a noob but I thought that micro services were always containerized. Turns out we don’t do that and it all runs in a very bespoke and poorly documented VM. Now can we call this a microservices based architecture? I feel like we cannot, it feels like worst of both worlds…
- deleted 5y ago[deleted]
- noizejoy 5y agoI have no idea how much sense it makes to have this discussion without a reasonably specific underlying business context.
- dmitriid 5y ago> Starting a greenfield project with microservices is easy. That's an overstatement if I've ever heard one. Staring a greenfield project with microservices is a nightmare. In a greenfield monolith you can code and deploy your dependencies together. In greenfield microservices? Oh, right. Set them all up for deployment, figure out netwroking and access between them, any change requires the fix-test-deploy dance etc.
- adamnemecek 5y agoMicroservices are all about starting and never about finishing.
- reilly3000 5y agoCompanies that aren’t B2D have a hard time with monolithic architecture. They simply have too many disparate needs, teams, vendors, and timelines to try to force everyone to share a codebase, unit of deployment, and set of endpoints. The supply side and demand side of any business has vastly different objectives, SLAs and priorities. Should we have to wait two weeks to deploy a minor patch to the Purchase Order portal because there is a risky ecommerce deployment that needs to be finalized first? Do we need to scale up the web servers to batch process some nightly data? Surely there are excesses in the realm of microservice architecture… “every library is a microservice…” is advice I’ve read in the past. Service discovery / routing isn’t easy. Naming things is hard. Personally I prefer the term Service and try to make no prescriptions as to what size it will end up being.
- jayceedenton 5y agoThe example given, of adding new instances of a session service that consumes from a Kafka topic, is completely wrong. Kafka producers use a partition key of your choice, so the UserLoggedInEvent and UserActivityEvent that relate to the same userId will always be written to same partition. This is how horizontal scaling of Kafka consumers works, without ordering problems. Anyone that isn't aware of this has very limited experience with Kafka and event-driven microservices. I respect the author's attempt to give some balance, but I think some parts aren't well informed. It's important to understand the benefits of microservices AND the costs. Small focused projects have small, fast test suites, can be wholly owned and developed by a single team amongst many, can be released and deployed without fear of breaking unrelated features across a vast platform, can be retired easily when obsolete. They also introduce the complexity of communication across many systems to complete an end-to-end journey, and require incredibly careful design and carefully chosen boundaries and responsibilities if you want to allow each one to evolve independently. This takes time and experience, and many organisations get themselves into a big mess with no governance, consistency or cohesion across a confusing sea of services and teams. There's no free lunch, but let's get beyond fashion-driven lurching from one extreme to another. This cycle of having a few years where the costs of an approach aren't acknowledged, to a few years where the benefits aren't acknowledged, is very lame.
- Orou 5y ago> This cycle of having a few years where the costs of an approach aren't acknowledged, to a few years where the benefits aren't acknowledged, is very lame. Well said. I do sympathize with some of the criticisms but only insofar as people who didn't have experience with microservices get sold on a lot of hype, the tradeoffs aren't made clear, and they get burned. The cycle seems to be "This is the silver bullet for programming complexity!" for a few years, followed by a few years of "This isn't a silver bullet!" before the Next Big Thing (TM) comes along and the cycle starts over.
- doctor_eval 5y agoI’m going to be the contrarian in this discussion. I think microservices are awesome and I’ve deployed architectures in anger in both Java and Go. 100% would (and will) do it again. Most of the problems people are talking about seem to be around using microservices inappropriately, without sufficient preparation, or when an application is not complex enough to benefit from it. Microservices are not a panacea any more than any other architecture. Properly implemented, they have significant strengths vs monoliths, but require experience to get right. Properly implemented monoliths built by experienced developers are likely to strongly resemble microservices but without some of the advantages that I enjoy. As others have said, it’s not all or nothing, one or the other, but I don’t get the hate for microservices here.
- jamesfinlayson 5y agoI'm guessing more than a few here have seen and been burned by colleagues jumping on the microservice bandwagon: plenty of developers think microservices = good regardless of how the system is architected.
- mbrodersen 5y agoIf you don’t know how to manage the complexity of a monolith (by using modules/libraries/clean interfaces) then you will have even more problems managing the complexity of micro-services. Since micro-services include all the complexity of the monolith with added networking and deployment complexity.
- namelosw 5y agoMicroservices mix several different needs: scalability, function decomposition, and team structure. If you want them all you might want microservices, but there are better alternatives when you only want one or two of them. People have different opinions on microservices because microservices is great when done right, but can easily screw things up if people don't split the bounded contexts carefully. It's also more expensive to correct these mistakes because there are APIs between them instead of just code, so many projects would live on with them painfully forever.
- blip54321 5y agoIf microservices were a bad idea, we wouldn't all be running GNU Herd right now.
- loziuu 5y agoYou know what's underrated and underused? Encapsulation and common sense. You can't just do microservices for sake of microservices, but if you see that one of domains in your monolith is growing faster than others it MIGHT be good idea to split it to microservices. Every decision has to be reasoned by something. If you "don't know" or you haven't done basic designing like event storming, then you should start with monolith because it's easier to take step back. Choosing architecture has to be conscious not based on trends or beliefs. Even small app can be easy to mantain and develop in miroservices manner if you know WHY you decided to split it up. Don't do (or don't stop doing this) because you read some comments on hacker news or reddit :)
- _pdp_ 5y agoI have a different view of what microserves are and how they can be used without the overhead everyone is right to point out and hate. In my project we do utilise microserve architecture through the serverless paradigm (i.e. bunch of lambdas) but those services are exposed directly to the client via API gateways (many of them). In essence there is very little service-to-service communication. Each service has its own data storage (s3, dynomo, etc), its own queues and topics and there is very little service inter-dependencies of any sort. Each "micro Service" is kind of its own "micro API" if you like. The reason I believe this is a good approach for pretty much any problem is because each component is 100% swapable, it builds on its own and frankly has little to do with the rest of the system and such erros do not have a cascading effect. These services can be moved and reused in other systems too. The responsability for using these services in some sort or orchestrated manner lies with the client and yes the client/s is heavy. Now it is true that I cannot simply union select bunch of data. You need to except that each "micro service/API" is much like all other 3rd-party APIs and so you need to come up with your own way of pulling analytics, data consistency checks, etc. The fact that service-to-service comms are sort of banned have forced us to come up with interesting algorithms that rely heavily on solid computer science (math) principles. Just saying
- wackget 5y ago> The reason I believe this is a good approach for pretty much any problem is because each component is 100% swapable In reality, how often will a client actually want to perform a straight swap like this, though? And that's assuming there is such a thing as a straight swap, which there almost never is. It's a nice idea in theory but in practice it's worth very, very little.
- _pdp_ 5y agoYou might want to swap different versions of the same component or you might want to swap by implementing it in a different programming language, etc. These ideas work for me in practice so I don't know.
- dmux 5y agoOne problem I've never seen mentioned regarding microservices is what happens when the organization that produced them has moved from growing to stagnation and finally into decline. If microservices ship the org-chart, what happens when that organization fails to attract engineers? I worked for a company that microserviced themselves into a pit. We had a huge layoff which completely killed the morale of the remaining engineering staff. Over the next 3 years, more and more engineers left and the company refused to replace them. What started out as teams (~5 people) responsible for ~3 microservices ended up as teams of ~3 people responsible for ~6 microservices. It was kind of cool to be responsible for more architecture and see how it all fit together, but the sad reality was that too many of the microservices that had been stood up were stitching together disparate data from other microservices to then perform what a single SQL query against a RDBMS was doing.