On Micro Services Architecture - Old Wine in a new Bottle?

Featured image

The Micro Services Architecture has emerged as yet another old wine packaged in a spanking new bottle. Thought Works and Netflix have published this architecture to the multitude with their blogs and frameworks. People have jumped into the bandwagon and have deployed Micro Services for multiple situations. Look at this video for instance. There are about 3500 person days of work which was divided into smaller pieces and executed using Micro services. It is the old unix style, divide and conquer yadda yadda yadda. 

But personally I was still confused. I did not understand how you would orchestrate so many services and make them do something that you want done. I started reading a little bit more and finally found that the recommendations were chiefly around using light weight messaging frameworks, keeping services less than 1000 lines long, independent deployment of services etc. Basically we can break the application into a zillion small pieces, orchestrate the small pieces (in fact they should choreograph themselves using a pub-sub model), slap a rudimentary canonical messaging model on top of them and voila - you have got a web application that is deployable in 1000 small chunks. Look mom no monoliths!

This is quite reminiscent of what we do when we design components. Components can be viewed as strategy classes that can collaborate with each other to form the entire application. Components would manifest themselves as beans in a spring XML configuration file for instance. Now what if the components were to develop wings and fly away into their own JVMs or equivalent? You would end up with Micro Services. In a spring file, the components would collaborate with each other using IN-VM communication. In case of Micro services they need some light weight protocol to accomplish the same kind of collaboration. This can include protocols as diverse as Hateoas to even ESBs.

But, how are you going to deploy so many tiny applications? Are you trading deployment complexity for development flexibility? Do you really need that  flexibility?  Do you envisage so many tiny teams developing so many services and bringing them all together during deployment?

Now, as a rule, I am not a big fan of this kind of game. It makes me uncomfortable to think that all these services which were hitherto rubbing shoulders in the same JVM as a close knit joint family, are suddenly forced to rough it on their own. Micro services architecture seems to have shifted the complexity to complex orchestrations.

I was faced with the same problem when I was working with a huge bank before. I wanted the ability to construct an SOA without going overboard about breaking the services. It was exactly as was claimed by Fowler in his  famous article about Micro services - using UNIX style filters to break the task down into pieces. Basically I needed to break my task into multiple pieces which were stitched together. I explored the possibility of using commons-chain to do this. Finally, I ended up writing a small light weight framework (see OWIZ). This simplified my application considerably and achieved it without using expensive SOA interactions across the wires.

On the whole the following points must be kept in mind when using Micro Services Architecture:

I would go with a logical separation of services rather than physically separate them. Use something lightweight to begin with. Get into micro services only if these services are coarse enough to be owned by their own product teams.

Comments

Gayathri Rao: Of late micro services is the buzz word, there are a few questions though which you have also mentioned in the blog. One is - what is a micro service boundary - Can i call a service, which accesses DB, updates cache and does a bit of business logic and then format the data as a micro service. Or is it limited to only one activity per service . As you have mentioned very fine grained services will be an orchestration night mare. Secondly, one of the interesting things I saw on Martin Fowler site was that you can have multiple databases. the example was - customer data view for support might be different from sales view, so the micro services can store data individually. Wont this be a nightmare to manage. Typical approach has been to enforce canonical data models and single source for data. But Micro services seems to be suggesting otherwise. What are your thoughts in this regard?

raja shankar kolluru: Thanks Gayathri for the comment. I think the definition of the micro service boundary would be the most interesting thing to do. You can go with the Bounded Context definition as explained in DDD (Domain Driven Design) and define that a micro service is restricted to a bounded context. In fact this is the way Fowler’s article demarcates between the Support View and Sales view of the customer. However, I don’t think that the implication is that this should necessarily go all the way to the database level i.e. you might have a Sales view and a Support view of a customer but this does not translate to having two databases to hold those individual views. The article itself does not clearly suggest one way or the other directionally. I think the best way to define a micro service is to understand Conway’s hypothesis and ensuring that the organization structure mirrors the micro service structure that we are thinking about defining. In a typical organization, we will have separate groups that are responsible for a set of business capabilities. These business capabilities must be at a lower level of granularity than the organization groups i.e. you cannot have one business capability spanning across multiple groups while the vice versa may still be very true. The best way to do is therefore to ensure that one micro service cannot be spanning multiple groups. Instead one group in an organization can own multiple micro services. Within that restriction we can design these in the way we wish. Will update and retrieve be combined as one micro service or multiple micro services? The answer is that it depends on the way we want to operate these services. For instance in one giant retail organization, we had a micro service that took care of retrieving some shipping options for a product. There was a separate micro service created to update the shipping options into the database. The rationale was that retrieves are much more frequent and need to be optimized whilst the updates are less frequent. Hence the deployments were kept separate. I know this is a very involved topic but I hope that my answer shed some more light into it.

Gaurav Malhotra: What is not clear to me - How to provide performant search capabilities in microservices architectural style? Let consider an example. Consider there are three application Claim, ProductDefinition, Policies. In all three application there is a notion of Relation (enrolment data). So rather then replicating the Relation in all three application. Relation is carved out as a separate service with its own database. But its very important to mention, Relation is not an application on its own. Never ever Relation are persisted along with Claim,ProductDefinition and Policies applications. Its worth mentioning, Relation is an enrolment data and imported into system once a month. So Relation is made as a separate service with it own database. Now all the application make a REST call to access Relation data (pay a little extra cost to avoid not repeat/replicate Relation data (DRY). Looks like a perfect fit for architectural design pattern - Mircorservices (atleast IMO) Every thing works fine but how to provide good performance search capabilities across microservices i.e.search a claim for given Relation, is a big challenge What options do I have now? What are the different possibilities

raja shankar kolluru: Great question Gaurav. This is a typical SOA problem where performance is sometimes sacrificed at the altar of encapsulation. I don’t understand your domain well enough. But I am assuming that Relation is a notion which links one Customer to another. And every Claim will be linked with one or more Customers. Right? Quite clearly, if Claim and Relation exist in the same database, it is a matter of issuing a query that joins the two tables to obtain the results whereas in this case, you would be forced to execute one query that obtains all “relations” for a given Customer and then re-issue a Claims query for every one of the relations. Is this correct? So if I get 5 relations for a Customer, I may end up issuing one query that returns the 5 relations and for every one of the 5 relations, I may need to issue one separate Claim query making the number of queries issued as 6 rather than one! Correct? If this is correct, then you have typically run into the “n+1” selects problem that is familiar to us in most SOA applications. (I discussed this in http://itmusings.com/architecture/the-n1-selects-problem) The solution in your case can be: 1. Strive for a middle ground. You can get all your relations in one query. All these relations can then be passed to the Claim micro-service which would then execute an IN query that has all the relations in it. So instead of executing “n+1” queries, you would end up executing 2 queries. A little sub-optimal since you would still be less efficient than the one query solution. But still not too bad. You can also further optimize this solution by using caches. But this approach is only possible if the “n” is not too big. If you get a million relations then quite clearly this won’t work. 2. A second approach is of course to replicate the Relation everywhere which then would break encapsulation but would gain performance. Both the approaches have trade-offs where you gain one desirable architectural property at the expense of another one. But as you know, the “art of architecture” is all about making these trade-offs appropriate for the occasion.

Gaurav Malhotra: Thanks Raja for the suggestion. You assumption were absolutely correct. I was also thinking about another solution. Using lucene indexes (Compass) to search in the claim app. So the idea is simple, build lucene indexes in the claim app so that for the query like below SELECT o FROM Claim o WHERE o.relation.zipcode = blah will be converted to lucene search query and get then go the db for fetch claim. The searched claim will contain HATEOAS link for relation. To optimize retrieval of relation we can introduce caching layer to avoid going Relation app always (refresh ahead caching). Ofcourse to keep the data/lucene indexes upto date/synched, Relation app has to send feed to claim app (application using it) What do you think about this idea Raja :-)?

raja shankar kolluru: Sounds good Gaurav. Your Lucene Index solution is actually a sub solution of the second approach that I mentioned above. You are using a different technology (Lucene) instead of a database to solve the problem. This is also a manifestation of what I call a data hub solution which is basically that you create a hub that contains all the data in one place so you can execute selects against them. Sounds great.

Gaurav Malhotra: Thanks Raja :-) I made prototype using Elasticsearch and putting indexes on the Coherence cache/or an other distributed cache (write behind cache, so rather then writing indexes to shared file, indexes are written to write behind cache which then flush it to database. This avoid recreation of indexes at startup, which can be time consuming as the volume of data increases. Also all Lucene indexes lookup happens using cache lookup in place of file lookup, this optimization also impacted performance positively), it outperform databased approach. Using distributed cache, was another positive for disaster recovery, as indexes were retrieved from the backup copy on other nodes. Further indexed object were cached, the benefits of this were folds:- 1) No object creation cost 2) Avoid round trip to db 3) Avoid marshalling and un-marshalling cost. Thanks again :-)