This stops short at all the really interesting stuff of microservices. Where's the service discovery? Failover? Secret storage? Communication?
Besides that, I don't agree with putting dependency injection in a microservice. Why bother? In a sense, microservices are a breath of fresh air, because they're supposed to "fit in one developer's head." If you're already adding layers of indirection, you're making the code harder to reason about for no good reason.
Yep - yet another half-baked project that someone is using for internet points. I'm really getting sick of people re-inventing the wheel poorly.
The number of available tools is really getting out of hand and I wish projects like this wouldn't suck away resources from established, functional projects.
I would even expect some out of the box management APIs to help upgrade the microservice with low to zero downtime, feature toggles, etc... A lot of these get built into each app typically but when you're creating many different microservices, the overhead of creating a service needs to be as close to zero as possible.
I am developing something similar with effe [1] and effe-tool [2] (completely WIP), that are suppose to be an open source implementation of AWS lambda.
I am facing problems similar to the one of the author, and I can see why he made some choices but I disagree on most.
In my opinion we should aim to a tool to build single executables and another tool to package those executable in a docker container.
Also I am doing my best to have as little as possible configurations, configurations are needed to deploy your application, and deployment is a different kind of problem.
I must say that is HARD, mainly for the constrain of go.
I would love to attach metadata to a go package, configuration would became a no-issues.
I would love to build my packages in a dynamic way, eg. these file is the scaffolding, those other are the custom logic, go compile and create a single artefact. However this seems impossible.
Go is a nice language but its tool really kill creativity.
What Go really needs for microservices is a library equivalent to Finagle[0]. GRPC is getting there, but we need some community standards for RPC, circuit breaking, exponential backoff, zipkin-like debugging etc...
We do not have a Go implementation yet, but at Datawire.io we are working on a IDL that compiles into a number of target languages and generates client and server code with all those features. Go is on our TODO list after we add Ruby support.
An IDL + target language compilers is a necessary precondition for, but totally orthogonal to, something like Finagle. All of the transport and mechanical stuff happens above the IDL's domain.
"IDL" is perhaps the wrong technical term for this because it's not really an IDL in the traditional sense. Quark is turing-complete and can be used to compile the protocol semantics, for example, backoffs, retries, circuit breaking, tracing etc right into the generated code. We're working on some cloud services to handle stuff like seamless service discovery and log/tracing information collection.
I feel the same problems with scaffolding / boilerplate, but I'm not sure I want to bring in Ruby / Cucumber to run my acceptance testing. These are just as easily written in Go too.
Typically via HTTP using JSON. Frequently though people realize JSON is a bad format for exchange between many services at scale so they will switch to something like protobufs/thrift/avro.
The HTTP part is not a requirement either, as there are microservices that talk via application specific tcp protocols , udp, or if they are housed on the same machine memory mapped files.
Thanks for mentioning this, I have never considered the mentioned alternative to xml/json for lack of needing to, but I did a quick search to understand a bit more and found this slideshare: http://www.slideshare.net/IgorAnishchenko/pb-vs-thrift-vs-av....
This seems to be much more interesting than I anticipated. But I am left wondering what's the 'market' share for each.
interesting read. i started using go for small api integrations, server-based networking work - i like the language - i have to admit it is ugly though
Not sure if you're trolling or you are that rare breed of person who likes things like a convenient proxy factory bean superclass for proxy factory beans that create only singletons. Beautiful.
Seems you are conflating Java with Java + old Spring (not that older J2EE was any better.)
I find modern Java really nice and the only things that annoy me are runtime type erasure (scheduled to be fixed in Java 9 IIRC) and some niceties such as LINQ.
What drives me away from other cooler alternatives is if not high-ceremony then at least the unfamiliar and annoying (IMO) ceremonies they require.
Java has Maven, which for all its warts is quite stable and mostly just works. Switching between compiling for version 5, 6, 7 or 8 is a one-liner (but we never do anyway because everywhere I deploy I can use 8.)
I'm the author of this post and thanks for the feedback, just wanted to make a few comments...
1. Half baked
Not sure I think this is a fair comment, it implies a lack of care, I do however think that work in progress is a fair assessment and actually I state this myself, the approach taken is an evolutionary one. With every use, identify improvements and make them so next time things are better. The more we share our learnings the faster the industry will advance and to many Microservices patterns are still a new approach, there are huge learnings to be had, some from personal experiences other from avoiding the failings of others. Just trying to share what I know in the hope it might help someone else.
2. Dependency Injection
I was fairly confident this is a marmite (love or hate) approach with Go, there are some threads out there longer than the complete works of Shakespeare arguing if it is needed or not. For me it helps with decoupling when taking a test first approach and this is the main reason I choose to use it as a pattern. I have written services with and without DI, I definitely prefer with, I did say it was opinionated :)
3. Service Discovery, Failover, Storage, etc
This is a huge topic in itself yet from people I speak to when discussing Microservices is something that often comes up. I personally hope that service discovery will be picked up at a Platform level by Mesosphere, Kubernetes or new PAAS providers like Docker Cloud or Google Container Service. At present I am using Consul, Consul Registrator, and HA Proxy but the bigger and more complicated the system the bigger this problem becomes and I am not 100% happy with things in this space. Storage is best avoided where possible, Docker certainly introduces problems with mutability, S3 is an option at the moment for shared storage but there are interesting things in the works with Docker Volumes. Event Sourcing is another huge area for Microservices, effectively decoupling them removes many of the problems around failover but this in itself huge complicated area. In general developing for failure is a good approach, deciding how things fail should be a cross functional requirement when discussing the features.
4. Feature Toggles
Good call and in fact at my day job we use these extensively, in fact we could not deploy without them. At the moment this is not a problem I have had to tackle and therefore have not added this feature. I suspect this is something that will affect me in the future once I move from writing new services to changing and maintaining existing ones. Feature toggling in microservices opens up a completely new approach, do you toggle in the service code or with a different copy of the service itself and toggle within the service routing?
Really appreciate all the comments, I have certainly learned some stuff and I'm really looking forward to where the industry will head in the next 12 months.
Besides that, I don't agree with putting dependency injection in a microservice. Why bother? In a sense, microservices are a breath of fresh air, because they're supposed to "fit in one developer's head." If you're already adding layers of indirection, you're making the code harder to reason about for no good reason.