You may or may not have noticed slight differences on the site, but NixMash.com has been rewritten from the ground up. It was a Monolithic Spring Boot application, but is now a Microservices application based on the Bootique Framework and comprised of four modules, a Web Module and 3 Microservice Modules. Here's the layout in IntelliJ Project View.
All blog post data you see in the Web Module originates from REST Resources in the Post Service Microservice. All searching and indexing is performed in the Solr Service Microservice. Finally, the Util Service Microservice performs tasks like visitor logging, email services, generating Twitter Metadata, that sort of thing.
NixMash Microservice Wiring
Here is the layout of how the components of NixMash Microservice communicate with each other. Both the Web and Post Service Modules run Jetty, and the Web Module communicates with the Post Service REST Microservice with Jersey. The Web Module communicates only with the Post Microservice, the Post Service Module in turn hands off requests to Solr Service and Util Service through AMQP, or RabbitMQ Message Queues.
One of the reasons I moved from Spring to Bootique is because some time ago I put together a quick and dirty Spring Cloud application which I blogged about here. I don't have the memory stats anymore, but the Bootique modules I'm building now are much smaller than their Spring Boot counterparts. I know Spring loyalists would argue the point, but that's been my observation.
With that said, NixMash Microservices actually consumes more memory than NixMash Monolith. Here's the Spring Version, 445MBs of Resident RAM on launch and after a few page loads.
Here's the Microservice memory picture. The application modules are highlighted, with the Post Microservice topping the list at 294MBs RAM. It performs most of the work and does a good bit of data caching. The Web Module comes in at 202MBs, followed by the Util Microservice and Solr Microservice at @170MBs each. So as I said, the Microservice design takes up more memory than the single Fat Jar approach.
A Few Thoughts
Before signing off, here are some issues that aren't fabulous about Microservices Design:
- Everything in a distributed process is harder, more complicated. You're not just calling a Class Method to get a job done, you're wrapping up the data either before the Microservice Call or after or both. Then you're sending it to a REST Resource Endpoint in Jersey or pushing it onto a Message Queue with RabbitMQ.
- More server memory is consumed in a distributed application as we've observed.
- In theory Microservices are supposed to shine for development because if you need to fix something or add a new feature you only have to update a single Module. I can tell you that this is rarely if ever the case. You are updating multiple Modules, making updates and maintenance of distributed apps more complicated.
Here are a few things from the top of my head that I like about Microservice Design:
- The JAR size of the NixMash Microservices Web Module is 33MBs, the size of the NixMash Monolith JAR was 130MBs. So obviously it is much easier to make some changes to the Website, build the JAR and push it to the server.
- Partly because Bootique is such a "minimally opinionated framework" compared to Spring, and in part due to a distributed design, firing up the Web Module takes less than 5 seconds. Firing up NixMash Monolith Spring could take upwards to a minute or more.
- Isolated logic and testing is a cleaner approach to coding with more separation of application functions.
- Passing JSON to REST Endpoints and JSON ByteArrays to Message Queues day-in and day-out makes it easier to add features from external services.
- RabbitMQ Messaging is just good fun! To have that type of module separation, yet with one- and two-way data exchange capability is great stuff, and it's incredibly fast.
I'll be blogging about the particulars of NixMash Microservices in the future, so if you're interested in Microservices and Distributed Architecture Design, see you then!