Rick

Rick
Rick

Thursday, March 19, 2015

More Random Thoughts on Java Microservices Part 2



You can read part 1 here: Random Thoughts on Java Microservices Part 1. My plan is to publish this in pieces and then piece the whole thing together into one article after some heavy edits.


Microservice doubters

Before you roll your eyes and buck against the goad, realize that words have power. People were doing Ajax before it was called Ajax. Giving something a name, helps guide it evolution and development. People were doing NoSQL before the term was coined, but the ideas were powerful, and in many ways Microservice is a term like Ajax and NoSQL, it is a post adoption name for what people are mostly already doing to a certain extent.  

”Microservices” - is a powerful term, but it is one you need to embrace. It is likely that you have been doing some or all of what Microservice Architecture is already. One day Microservice will go the way of Ajax, it will be so common it will be a forgone conclusion. Microservices is about pragmatism not vendors raising barriers to competitors by creating overly complex specifications. 

We need to define Microservices a little more formerly so it does not go the way of SOA and every vendor gets to form a committee and dishonor its intentions with a set of nifty shiny baubles. SOA was a huge success and a failure. A failure because the term has actually no meaning or rather so many meanings, and yet Amazon and Google’s version of SOA are a huge success. Look at successful things that we had to call SOA and those are probably microservices.


Microservices support mobile clients well

In the Java world, microservices has a special meaning. Besides Android, which uses the language formerly known as Java 1.6, Java on the client is dead or very insignificant. One of Java’s many roles is a platform for building services for mobile devices and web clients. This is another reason to embrace a common, flexible, HTTP standards based communication mechanism, because one of the biggest consumers of services are mobile apps, and web apps. Web Apps are thicker than before. Mobile apps might be written as Web Apps and / or have components that run in both the mobile platform and a pure browser play. This is not new. This is an ongoing trend. The idea of a pure monolithic application web application written in Java is a dinosaur. It became infeasible somewhere between 2008 and now. Java services can be the MC in the MVC world but Swift, JavaScript, ObjectiveC, Android, own the clients. Clients are getting fatter which means services are getting thinner. This is a major driving force in microservice proliferation. 


One thing well principle and fallacy of the monolith

The microservice architectural approach is to create smaller services that are focused on a small business domain or crosscutting concern. Microservices adopt the Unix single purpose utility approach to service development. They are small so they can be released often and are written to be malleable. They are easier to write. They are easier to change. Microservices go hand in hand with continuous integration and continuous delivery. The services are independent enough not to need a gigantic release train to release improvements or new features. In the Java world, this means you will be using other microservice like Jenkins to provide frequent releases.

Do not try explaining the microservice style by comparing it to the monolithic application. No one ever set out to purposely build a huge monolith. Yes it happens. But comparing microservices to a monolith is like comparing agile development to not having any process. The huge monolith is not an architecture style. It is usually a mistake. Collection of technical debt absorbed by a development team when the product team goes off the rails. Also even if someone was building a large web application, it is often the case (ok not that often) that they broke their code up into modules and have internal services that might be easier to break off into microservices. If their application is a big ball of spaghetti code, then that has nothing to do with microservices or them trying to develop a monolithic, their process, training, and culture is the issue. 

The first issue I have with calling something a monolith which gives it a negative connotation is that what you really describing is a web application. If you have a successful web application and it is getting so large that you have to break it up into many web applications or services, this is a good thing. You have a we call a successful application. There are tools that simplify writing basic web applications like Rails, Grails, Django, some PHP framework and their ilk. 

There is nothing wrong with the basic web application. If your application is growing a lot larger in features and functionality than you expected then using these tools to create a basic web application might be the wrong approach or you may have to go off the rails with these tools. If you know that many of your clients are going to be mobile clients and you have potentially hundred thousand or 1 million users then these tools are probably the wrong approach. If you're writing a department level application and these tools are exactly the right approach and you may not need to use microservices. Not every application has scalability concerns or the same scalability concerns. A microservice may benefit greatly by using some of these tools to provide admin visibility and diagnostics into the microservice. Don't throw the baby out with the bathwater. It's all about engineering trade-offs and knowing what are the driving factors that are going to form your architecture. Sometimes this is an easy thing to do. Other times you have to write that first version get it going and then come back and revisit the architecture.

Enterprise Applications

While it is true Enterprise Applications are often built with a three tier architecture: backend code, database code and a GUI written in HTML/JavaScript. This has more to do with the world changing than an active choice. Cloud, EC2, proliferation of mobile devices, cheaper memory, more virtualization, more cores, SSD, trend towards fatter clients, 10 GBE, 100 GBE, etc. made this style obsolete to a certain extent at least for large applications. It is not like we one day came up with a better idea, and then one day were like hey what if we could make our code more modular. The ground changed under our collective feet. The way we build, deploy, and consume has changed. 

Microservices and NoSQL are two trends that are more focused on how to address software development where deployments are increasingly cloud based and clients are increasingly mobile based. You can’t compare client / server development of the mid-90s to mainframe development from the 70s either. The world changes. We adjust. Microservice trend is course correction not a new religion. 

History of Enterprise Applications

Remember the reason why Enterprise Applications are written with three tiers was was to avoid DLL hell. Back in the day, we used to build apps that were two tiered. You had to actually go to each users machine and help them install the app. There was a damn good chance they downloaded some shareware that installed a DLL that screwed up the install, and you were in hell. It was not like we were, “Hey James!” .. “What Martin?” “Do you want to build a huge monolith?” “Sure Martin!”.

We tried Applets but Java GUI development back then sucked. I don't think it sucks so bad now, but it lost its window of opportunity for adoption. Then we were left with HTML/JavaScript clients and forcing everyone to use the same browser in the corporation at least for the corporate apps.  There are many reasons why this style of “Enterprise Development” does not work in the cloud and for mobile devices. The server-side application no longer need to handle HTTP requests,  get data from a database and execute all domain logic, and draw pretty pictures in HTML. Much pain, and great expense has been incurred trying get this three tier architecture to scale in the cloud for various devices written in a polyglot of languages. 


Server components, EAR files and WAR files.. may they rest in peace

If you have lived through COM, DCOM, CORBA, EJBs, OSGi, J2EE, etc. then you know the idea of services and components is not a new thing. One issue with enterprise components is they assume the use of hardware servers which are large monoliths and you want to run a lot of things on the same server. That is why we have WAR files and EAR files, and all sorts of nifty components and archives. Well turns out in 2015, that makes no sense. Operating systems and servers a ephemeral virtualized and can be shipped like a component. We have EC2 images AMIs, OpenStack, Vagrant and Docker. The world changed. Move on.

You can run a JVM in a Docker image which is just a process pretending to be an OS running in an OS that is running in the cloud which is running inside of a virtual machine. Got a busy season? Well then, spin up 100 more server instances for a few weeks or hours. This is why you run Java microservices as standalone processes and not run inside of a Java EE container. The Java EE container is no longer needed because servers are giant refrigerator boxes that you order form Sun and wait three months for. Don’t fight class path, class loader hell of Java EE. Hell you whole damn OS is now ephemeral, deliver an image with all the libs you need, don’t deploy to a Java EE server which has to be versioned and configured. You are only running one service in it anyway. Turns out you don’t have five war files running in the same Java EE container since oh about 2007. Let it go. 

Microservices architectures opt to break software not into components but into reusable, independently release-able services. Application and other services communicate with each other. So where we might have used a server side component, we use a microservice running in independent processes. Where we might have had WAR files or EAR files we have a Docker container or a Amazon AMI that has the entire app preloaded and configure with exactly the libraries it needs (Java and otherwise). 

JSON, HTTP, WebSocket

Now you just have to document the Microservices HTTP/JSON interface. I would say REST, and certainly you can use concepts from REST, but hey HTTP calls are enough to be considered a Microservice.  No XML. No SOAP. No WSDL. No WADL. JSON! Ok you can add some meta data and document how to talk to your service, but the idea is the docs should be documented with curl

Documents should sound more like: I give you this request with these headers and you respond with this JSON. Keep it simple. You can provide things in addition to JSON, but JSON is the minimum requirement. If you are not delivering up JSON and consuming JSON over HTTP/WebSocket then what you wrote is not a microservice.


Call speed, non-blocking calls

One of the issues with remote calls is speed. This is why you will want to organize services around a domain that will help keep the data for that service with that service and it will not need to interact with other services or a foreign database every time it gets a request for its data.  While Remote calls are expensive this can be accommodated for by using async calls, batching, and WebSocket/JSON. Remember WebSocket allow bi-directional communication. For speed, you should prefer RPC calls that are non-blocking and can be sent in batches.  

Another approach for increasing remote call speed is to go all SOA on your API. You can write coarser-grained HTTP APIs so more is delivered with each call. It is hard to write and use coarser-grained HTTP APIs as they often conflate many subdomain data in the same call in the name of speed and aggregation. It is easier to batch many smaller calls and create service aggregators. You will need to do both batching and aggregation of domains (coarser grained). Dumb fast pipes and batching calls are your friend. 

Depending on scalability needs services may need be sharded so while a service runs in a single process. That service may really be running in many processes on many virtual machine. Microservices are not stateless. Microservices should own their data. This may mean a private database. Or a private database shard per sharded service. We will talk more about this later. To learn more about how to scale microservices check out high-speed microservices. To learn more about what a Java microservice looks like read rise of the machine

Microservices do not negate the need for having libraries. If you are making many calls to a microservice, there is an indication that you maybe needed a library instead of a microservice. Adopting microservice architecture does not make you a better systems engineer. You will need some common sense, systems knowledge and/or a very good perf testing regiment. Many will fail and go back to a traditional three tier, web development version of services. 

If you are making a lot of blocking calls, then what you wrote is not a microservice. 



More to come.  I plan on doing this in phases. To make it easier than publishing the entire thing in one go. 

Check out this Java Microservice lib in the mean time... 




Kafka and Cassandra support, training for AWS EC2 Cassandra 3.0 Training