Migrating to microservices
Well I’m trying to write some pretty detailed notes about my experiences at QCon London 2014, and it seems I’m managing about one post per day at the moment, so this could take a while to get through the 18 sessions I attended! Anyway, today’s exciting installment follows…
In actual fact, although exciting might be overstating it a bit, Adrian Cockcroft (@adrianco) gave a talk “Migrating to Microservices” which was genuinely inspiring as well as being incredibly informative and full of sage advice. If you’re able to view a video of the talk, or just read through the slides, I really recommend it. Here are the highlights from my perspective.
Before talking about micro-services per-sé, Adrian first gave a really nice visual summary that explains why the DevOps movement has so much to offer Lean development and business value and efficiency (see my other posts on DevOps here and here).
So what are micro-services? Well obviously they are services that are “small”, but interestingly it’s the functional size that is limited, not the technical size (LOC, memory, whatever). Here are some of Adrian’s guidelines for introducing Micro-services.
Separation of Concerns: Adrian suggested one “verb” per single-function micro-service as a way of thinking about it, for example “put_document” might be a micro-service or “get_contacts”. This single-verb mentality enforces a good separation of concerns. One developer independently produces a given micro-service, which is its own build, largely avoiding trunk conflicts. Related micro-services can be grouped, and developed by a team of developers – inverting Conway’s Law along the way, (the geek shall inherit the Earth!). Each micro-service is has stateless business logic, implemented in immutable code with instant rollback, and persists state using a cached data access layer to a de-normalized single-function NoSQL datastore.
Versioning: If you follow the advice from this talk then you should be looking at versioning as a last resort, but on the assumption you’ve introduced multiple versions of a micro-service for a reason, Adrian’s advice is to leave old versions running, and adopt a “Fast introduction vs. slow retirement” model.
Client Libraries: a client-side driver is the end-state, and the best strategy is to own your own client libraries from the start since if you don’t provide them, someone else will end up writing them anyway and then expect you to support their interpretation of the API/contract. I’m not sure I agree with this, but perhaps I’m assuming a REST/HTTP model with good API documentation, largely used in-house. I can see where even this model breaks down, but I imagine (hope) it would be a lesser issue in a small enterprise than in a global, public platform.
Avoid (or abstract away) multithreading to keep the model simple, and use non-blocking calls to ensure scalability of the micro-service.
ESB/Messaging: Message buses are CP (consistency guaranteed) with big problems getting to AP (availability guaranteed), and should be used only for “send and forget” over high-latency links. SeeBrewer’s Theorem for background.+
Service discovery: use Zookeeper or Eureka
Adrian had some nice patterns for introducing micro-services covering both the “social” and the technical challenges with doing this for the first time. For the social side, one slide says it all:
On the technical side, Adrian suggested “shadow traffic backend redireection” – basically redirecting a real traffic stream to validate the back end. This can be done by duplicating the service request on the back-end (perhaps based on traffic percentage, say). In the first instance this can be done in a send-and-forget manner, i.e. ignoring the response. The goal after all is to test that the new service does behave as intended.
Adrian also covered some deployment models, e.g. canary testing and the automation of this as deployments scale up, and a global roll-out model. Once again, although I found this really interesting, I think it’s of limited use in a small enterprise. Perhaps of more interest were the monitoring solutions he mentioned: Appdynamics, Boundary.com, Cloudweaver.
If you read my previous post on Continous Deployment at Etsy then Adrian’s final slide was particularly interesting in terms of showing the comparison with Netflix, which is a micro-service based architecture compared with Etsy’s monolith: