Chaos Engineering make disciplined Microservices

 

Chaos and discipline, These two words are Oxymoron, you might be thinking, How Chaos can make Disciplined Microservices?


But the universal truth is discipline means the absence of Chaos, so until you have not experienced chaos you can not be disciplined.


If we think about the Law of Entropy, then Chaos is the high entropy state, and a discipline is the low entropy state. Always disciplined services degrade to chaotic ones to make the system in equilibrium, as the flow of the direction is from high(Chaos) to low entropy(discipline) state. So chaos is inevitable.


Now, If we want to make sure our services remain in a low entropy state(discipline) throughout, we need to adopt a few special techniques. as per the Law of physics, this is an irreversible process(Flow from low to high entropy state), it is going against entropy we called it reverse entropy (watch Christopher Nolan Masterpiece TNET!!!)Refrigerator is a reverse entropy object(doing cooling), Crux is to maintain discipline in your services we need to adopt a Resilience strategy but the question is How to determine what resilience strategy needs to be adopted? For that, we have to experience Chaos in production and act accordingly.


This is the essence of Chaos engineering, by injecting mild fault into the system to experience the chaos and take preventive measures and self-healing against it.


Today I am talking about implementing chaos in production!!!!


After hearing this you might think what I am saying? Am I insane? I am encouraging implement chaos in production, which is the most emotional and sensitive area of a developer, We are all praying whatever the error comes, please those come before Production, In production, if something goes wrong your organization reputation at stake, your organization loose user base, Revenue, etc and I am encouraging to implement Fault/Chaos.


But the Irony is we are having the wrong mindset, our mindset should be “Failure is inevitable and we must prepare for it”. In this tutorial, I am advocating for this Culture.


A simple Microservice definition::


Microservice Architecture is distributed in nature and it consists of suites of small services which can be scaled and deployed independently. 


If we deduce the above statement we will find three important things.


As Microservice is distributed, it is communicated over the network, and the network is unreliable so How come your Microservice will be reliable?

Over the network, Microservices are communicated to each other so they are dependent on each other, so they can fail if their dependent services fails.

Microservices Scaled and deployed on infrastructure so if infrastructure fails your Microservices will fail.


These points justify the “Failure is inevitable and we must prepare for it” statement.

But the question is How do we prepare for it? 

The Answer is Chaos Engineering.


What is Chaos Engineering?


Chaos Engineering is a technique by which you can measure the resilience of your architecture. By Chaos Engineering we will inject Fault(Increase load, inject delay), and then we will check How the services react, how resilient the service is? We called it FIT (Failure Injection Testing) If the service is not resilient we will identify it and make the service resilient so it can handle real-time error in production.



Image courtesy : Netflix


Now Let’s Discuss In terms of Microservices what are the areas we should do the Chaos testing to see our Microservices are resilient and what are the resilience strategy we must follow to avoid downtime.

 
Network, Resilience, and Chaos Engineering::

Chaos in Network::

As Microservices are communicating over the network many types of failure we can encounter like the network is unstable, network load,DDoS attack. Delay during the call etc.

Resilience Technique::
Hystrix is a suitable tool. By hystrix, we can ensure if one service is down rather than hammering that service we can take a default route, and give time to that service to recover. 

Chaos Testing
We can introduce load/congestion or network delay in using Netflix FIT Framework in production to check how services are reacting, note that, In FIt we must have a separate Canary path for FIT testing where we can experiment roughly for 1% of the real-time user load and if service is not resilient we will terminate the test then there and reroute to the real path so that user does not experience any error.

    Image Courtesy: Google Search


Dependency, Resilience, and Chaos Engineering


Chaos in dependency

Microservice are calling each other to fulfill a business capability, so microservice dependency is a major factor, many types of failures we can predict like, dependent Service is not available, service not in a state to receive the request, one service fails as a cascading effect whole microservice service chain fail and crash, distributed cache unavailability, cache memory crash, single point of failure.


We will talk about the resilience strategy for all the above cases.


Resilience Technique::

Hystrix is a Netflix OSS tool by which we can implement Circuit breaker patterns in the services, so if one dependent service fails for several requests it is better to not call it and take a default route so that the whole Microservices calling chains, not breaks and the user experience not getting stopped.


Another Resilience technique is to identify the critical services which are the heart of the Business and make sure if other services fail these services can run and can give users a minimal experience to carry on rather than halting the whole user experience.

In Real-time architecture we don’t always call the persistence layer it creates latency also all business features are not stateless we need shared data across multiple microservices so we are using cache techniques and do some sorts of orchestration in our code where if a request comes then we first check cache then data not available we call persistence layer and add the result to the cache for further requests.


Now, If Cache fails or acts as a single point of failure our services will fail, to avoid the same, we are using distributed caching with replication and the data must be replicated to different available zones so if one zone fails data can be retrieved for another available zone.


We need to adopt a Multi-region strategy for the persistence layer as well Microservices, If your Business spread over the Geography then as per architectural style we must have different data centers over the Geography say US North, US East, Asia Pacific, Europe etc.


Now the interesting thing is if your one data center serves one region say Asia pacific serves Asia, now if that datacenter goes down your all Asia pacific users affected so we must have Multi-region and failover strategy so if one region goes down it's user request can be shared by another region to have a resilience system.  



Chaos Testing::

To check Service is unavailable to introduce latency in the call to see how services react, we can use the Chaos Monkey framework and chaos toolkit to achieve that testing.


To check whether your critical services are working or not you can blacklist other services and only white-listed critical services to see how it reacts when only critical services are up.


We can use Chaos Monkey and Chaos Gorilla to kill random nodes to see how services react assuming service multiple instances deployed in multiple nodes.


We have Chaos Kong which can takedown the entire region to check the Multi-region Failover strategy.



Scaling, Resilience, and Chaos Engineering::


Chaos in Scaling::

In Microservices we generally adopt XYZ axis scaling. Now in Scaling, we can face many types of issues like Zone unavailability, Server affinity, Sticky sessions, cache unavailability, etc.


Resilience Technique::


Generally, when we build a Microservices / distributed architecture, although we are saying to build stateless microservices it does not always happen we have to maintain statefulness due to business requirements like cart functionality, so we are adopting many techniques like server affinity or sticky session, once a request comes to a node load balancer makes sure that users further request will be processed by that node only, but this technique has some downsides, although your system is distributed you have multiple instances if that particular node goes down all the users served by that node will experienced error, which is not expected.


So we need to make sure our services should not have any server affinity. We can use distributed cache to store the stateful data or session also we can use request payload to append the state so data are available in the whole request cycle, which has been populated by different microservices.


In the case of cache also as I mentioned earlier data needs to be replicated in multiple regions if not then if one cache region went down all the users whose data stored by that region will be impacted, if we have replication, data can be available from other areas.


Another important thing is when we are adopting Horizontal scaling we must have to make sure it can auto-scale based on the load, we need to treat each node as cattle, not like pets, so if one node malfunctioned we can kill that node(I am against animal cruelty) and spawn another one automatically. Now If your services have server affinity or Load balancer works on sticky session strategy auto-scaling is not possible, so fix the same. Your organization's infrastructure must be capable of self-healing and spawning new nodes based on the load. So it is advisable to use containerization and container orchestrators like Kubernetes, Docker swarm to handle this.


Chaos Testing::

To check whether your service has server affinity or not, you can randomly kill nodes by Chaos Monkey and chaos tool kit to see the outcome.


Infrastructure, Resilience, and Chaos Engineering


Chaos in Infrastructure::

While adopting Microservices you have to have strong infrastructure support, most of the organizations either use cloud providers or they have their internal cloud or own data centers whatever the case, your Microservices architecture depends on Infrastructure if infrastructure fails you Microservice also fails. So we must think about infrastructure failure and design our architecture in such a way we can mitigate the failure.


Resilience Technique::


For infrastructure, we must need to have a Multi-Region strategy and failover mechanism, so that if one region's infrastructure goes down another region can serve that region's users.


Also, we need to choose Data center smartly so that two data center physical distance is not too much if it is so network hoping time increases so response time increases, but they Physically must be far apart so that natural calamities, Terrorist attack occur it should not impact both data centers.



Chaos Testing::


Using Chaos Kong we can take down the entire region to see how failover works.




Image Courtesy: Netflix

How to adopt Chaos Engineering?

Although Chaos engineering is a compelling idea it makes your developer ready to tackle real-time production incidents, but Chaos engineering is not a free lunch, it needs the proper DevOps pipeline, auto-scaling architecture, resilience system to make it successful.

So before adopting it you need to spend money on Infrastructure, DevOps, and building Scalable architecture.

Below are some pointers to think about while adopting Chaos engineering in your system.

  1. You must have a well-designed DevOps Pipeline where you can test Chaos engineering roughly 1% load to flow to Chaos engineering Path to test how your system reacts.
  2. You need to have well-designed container orchestration techniques, where you can manage the containers, autoscaling, failover, networking rule, etc 
  3. Chaos engineering is meant for a complex business system, if your system is simple enough don’t adopt chaos engineering it will increase the overhead and cost of your business.
  4. After adopting Chaos engineering you must conduct the Gameday concept, the day when you do the Chaos testing in productions and it has to be conducted at a regular interval.
  5. You need to have automation platforms and implement the chaos quality gates, which do all types for failure testing. If your team has to do it manually so then in the long run the team will lose interest and it will be out of control.
  6. If you identify a new failure in production during chaos engineering you need to terminate the test and reroute it to the original route so the user does not experience any error.
  7. In case of new bugs identified in chaos testing, the team must need to do RCA of that and try to solve it and then find a way to automate it and assimilate it in chaos quality gates.
  8.  The organization must have a Chaos Checklist, every service needs to pass that checklist then only it will be promoted to production.
  9. Chaos engineering in production is risky if your team is not skilled enough, it will be better to start with lower environments and once the team acquired the skill then try to do it in Production.
  10. While testing in production it is important to minimize the blast radius, unnecessary giving pain to customers is not a good way to experimenting chaos, so the chaos engineering team must ensure to keep the experience in the minimal blast radius and fall back to the original route if something went wrong.



Conclusion:

Chaos engineering advocating for checking how your system and developers are ready to handle real times issues. Often our system is not battle-tested against Load testing, region unavailable, critical services unavailability, although we are having some kind of load testing, integration testing done in the lower environment but that is not enough and the reason is,

“Our lower environment does not mimic production infrastructure”

So often developers have to battle against failure only in real-time without any preparation. There is no process in place, so developers are confused about what to do and that's why production failure is still a fear factor for all developers and infrastructure guys.

Having said that, by The Chaos Engineering, we are giving chance to developers and infrastructure guys to prepare themselves in real-time in Production itself, now they will be seasoned players and can handle the Production error without fear. This is the future mindset all organization needs to adopt as we are moving very fast, everyday new framework, tools are created every organization adopts them to break out from the old system, it gives organization enough flexibility in terms of scaling, resilience but on other hand, it complicates the architecture so without chaos engineering you can not be sustained.

“Chaos Engineering is the Vaccine of Complicated architecture, it helps to create antibodies and memorize them so in future if the same issues happen, those will be mitigated immediately.”







Dilemma on Utility module , making a jar or separate Microservice?

In my previous article, I talked about How you can come to a conclusion about what to choose for your new project Microservice or Monolith? 
As an architect may you follow the points what I mentioned in the previous article and come to a conclusion that you will be going to use Microservice Architecture, A big cheers for you, You promoted yourselves as a first-class citizens of the new era of  Digital world, but(when but is used it means the previous word is meaningless/no value until you solve the next part of but :)) what's next , you heard about Microservice Architecture demands Componentization of service but what is actually a component in Microservice world?
In this article, I briefly discuss What does it mean by Componentization, and when we need to do Componentization of a Utility module what problems we faced?
Componentization of service:: By the word "Microservice", we can understand it is a suite of small services, so the main objective is breaking a project into multiple services. But what does it mean by services, Which kind of services are those? Are we talking about a Service layer in a layered architecture, or a service wrap into the jar so-called "Library" or publish it through REST API, what is that?
To understand always remember "Microservices means an Independent thing(Component/Service whatever you call it) that can be deployed independently and update independently manage it lifecycle independently".
When you Create a Microservice very clear about that, There should not be any confusion, Maybe many tricky situations come but stick to basics "Microservice mean an independent deployable thing".
One of the best dilemmas is,  Suppose you have a utility module, now you are in a confusion what should you do,  wrap utility module into a jar and all other Miocroservice use the same as a jar , so that there should not be a code duplication or expose a utility service with API fiction(Separate Microservice)  so others can consume it.
One may think, making utility module as a jar   seems severely wrong in Microservice workspace as Microservice means several independent small services so Utility module  should be published as a service,  so Utility module must be a Microservice,
Why is the Utility module as a Jar a bad Idea?
when you import utility module as a jar you limit yourself, Now Your service is dependent on utility module which packaged as jar, If utility modules  java version upgrade you have to upgrade your service unless your program not able to use that jar, Now you both should stick in same language java(Although once service is written in one language, I saw rarely that is rewritten in another language), having said that,  you should not confined  your Microservice to a language(Java), Think your utility module is used by many microservices as a jar, so if you want to upgrade your version  it should be backward compatible, say you want to create functions which can easily be achieved by java9 but you can not upgrade your utility as other microservices not upgraded to java9.
Why Utility module as a Jar is a good Idea?
As a counter logic many can argue, To build a Microservice itself, we  import jars/Libraries like Sprint boot starter parent, or GSON, Jackson etc, so why we should not package our utility as jar why it is a bad idea , Even let me tell you, many architect think it is a brilliant idea as  it solves many purposes.
If we are not using utility module as a jar then we have two options
1. Duplicate the functionality of a utility module in all Microservices.
2. Create a Microservice called Utility service and publish an API to invoke utility methods.
These two options has there it's own demerits.
1.  Duplicate the functionality of utility module in all Microservices::Here the objective is duplicate the code to all Microservices who consumes Utility module, so that there is no utility module as such, all are the part of local codebase, but it is against the DRY principle and bad idea, If the utility module is holding some complex code which associates many classes, unnecessary that has been copied to all Microservices and any future changes in that, has to be copied over all Microservices. So there is a problem of maintainability, say we have a utility module which calls an External service and get a complex response then this module parsing the responses apply some business logic on it and create some analytical data which exposes as public methods (Java API), Now if you copied that complex algorithm written in Utility module in to multiple services certainly it is a very bad idea, think how many time duplication has been done, and if now a new analytical data is needed you have to add it in all Microservices , oops what a pain while I am writing this I am getting feared to imagine the scenario. So certainly it does not work unless you have a very small portion of utility code and which is not changeable say a generic code which deals with Date, TimeZone, and Format, ( A single class with multiple static methods), Copying that class in all Microservice is a onetime effort.
2. Create a Microservice called utility service and publish an API to invoke utility methods : 
So, you create one Microservice where all utility methods are dumped, as this is a Utility module all Microservice or most of the Microservice Communicate with it, So Every Microservice has a link with this Microservice, So just imagine the picture every Microservice dependent(HAS-A) on it , So If that service is down due to some erroneous code or all instances down due to some major causes, All service will be down Total Microservice architecture is doomed then How it is different than a monolith?
As per Microservice, Partial failure may happen but total Microservice will not down ever, It has 100% uptime.
So certainly creating a Utility Microservice not looking very promising.
As an Architect What should you do now It is like a double-edged sword, whatever the option you choose, You have to deal with demerits.
Taking a decision :: As an architect, we always dealt with Demerits and try to choose in which case, which one to choose so it has least demerits, So, As an architect our favourite answer is "It depends on scenario", and we are hated for that answer, even Juniors are mocking us he does not have direct answer always said it depends.
Here I also giving answer in a same way, It depends :) How your utility method is written, in a one liner if your utilty functions are statless use Jar , If your utility functions are dealing with State use Microservice.
If you observe minutely, you can divide your utility methods into two categories.
One type of utility modules takes and input doing some operation on it and returns a result so there are no side effects and it is independent of any parameter state, every time you pass the same parameter you got the same result, In this case do not publish those as separate Microservice, as this is not dealing with state , so no need to publish as REST resource, because no create, Put ,delete operation done by this, So, you can package this as a jar and use in every microservices, Think about Utility jars like Jackson,Gson thy take request do some operation returns some data structure, But if your utility takes and request fetch some data from database, do some operation and return it or save that state in database, then it would be ideal to publish it as Microservice.
Here also think about the failure, if you make a synchronous operation then your utility module fail means all chain of Microservices is failed, so think can you make utility operation as async, is the utility module require in sync fashion? As an example Event store or store Audit information, Those are cross-cutting concerns and a utility operation so it is not a part of main business flow so we can make that async so that if audit information or even storing operation fails it does not block the business flow and your service should not down for it.
If you have to use utility operation in sync fashion, then implement a circuit breaker and return a default path, so that if the operation fails it does not block all Microservices, at least if show a default path and show the user a message. or users can perform other operations rather that this function (Say your transaction function calling a utility function to check Transaction amount and based on that bank giving you some credit points, now if that function fails we can show a default message "at this time we can't process transaction" but user can do other options like balance check. So any moment of time the service will not totally down.
Conclusion:: There are also different shades of Utility some are mostly read-only but has database operation, some may use in-memory caching so take decision wisely How you want to write your utility one,  jars or Microservice.

MicroServices with Devops Example



MicroServices with DevOps  Example






In this post, I show you How to create Micro service application and Manage it through Dev-ops.

To understand MicroServices please look at my blog post 

To understand DevOps please look at my blog post


Tools are Used to implement Microservice
1.       Eclipse as Editor
2.       Java as Language
3.       Using REST Service to communicate between Microservices
4.       Maven as build tool
5.       Tomcat as the Web server.


Tool are Used to Manage Microservices using DevOps
1.       Jenkins as CI (Continous integration server).
2.       GitHub as SCM(Source control Management).


My intent is creating two Microservices


1.       An Order Service

2.       A Billing service

If client order for a product, Order Service project will communicate with Billing service project by REST API. Billing Service returns Product price if exists in the Product Catalog Otherwise It returns a Message Product not found.

Order service accepts this response and generates a new response to Client.


To Manage these Microservice, I using DevOps

So that Two can be deployed independently, and Two projects are hosted in
GitHub. If someone does a change the code and push it to Github a build has been triggered by Jenkins and Once build is completed, Jenkins install the artifact that is the war file in Local Repo (maven Local REPO) then deploy it to Tomcat Server.

No Manual intervention is needed.


I have made it very simple but in real time there will be much more complexity than two simple services and we need Monitoring tool for the health check for different projects which is absent in this example.

I have used Java for Two services but real time one could be in java another in PHP or Node JS any language.


Installation:

Java:  Install java from
Set JAVA_HOME in environment variables to java installation path.


Download Tomcat 6 Zip Version and extract it to your local drive that will your Tomcat installation directory.
Maven:
Extract the zip in your local file Set M2_Home as maven Installation path in your local directory.


Go to Git Command prompt after installation
Change Directory to C: Using Cd ../../
Now apply command (Need Internet connection)

after completing

again hit

Import two projects into Eclipse by import from the local option.

If you want to create your new repositories, please go to Jenkins setup section and follow the step.

I prefer you create your new repositories to work independently. Unless if you clone it you will be dependent on me. If I gave you permission, then only you can push change on my project.







Jenkins :
 http://mirrors.jenkins-ci.org/war-stable/  (Take stable release. I use 1.65). Download war and deploy it to <Tomcat_installation_path>/webapps. In tomcat console when a message shows
“Jenkins full up and running” go to browser hit


First thing you need to require add plugins into your local Jenkins Server

So Follow the steps
Go to Manage Jenkins from left panel
Go to manage Plugin
In Available Tab Search  with “git” and check git plugin and GitHub plugin
Hit install without restart button
Wait until installation finished.


Go to configure system from manage plugin







Create an account in GitHub and then add your username and your email Id.


Then Go to new Item create a Maven project.

Create a Job Name as “BuildandDeploy MicroOrderService”

Please see the following Screenshot





In the Source code management section set your Git repository URL
If you download source code from Git by download Zip and create your new repository and push the code

Steps are
After Download project from

and
using “ CloneorDownload”  button on GitHub
Extract Zip files

Create a project on Github using “+” button (Create new)
You will get a url like https://github.com/shami83/<projectname>.git


Execute following commands for two projects in your local computer

Go to  Git cmd
Go to the homefolder of the Extract project
a.       git init
b.      git add .
c.       git commit -m “demo”
d.      git push origin master

Please do the steps for two projects that will create two repositories in Git (require internet connection).

In jenkins on repository url put the url


If you clone it then you need my permission to push code to my stream, please send me a mail the at
mitrashamik@gmail.com or add a comment in blog.


Then put your credentials in credential section your username and password of Git repository.


Follow next step



In Build triggers section Check ” BuildWhen a change pushed to Git hub”

And poll SCM

Put value as * * * * * in schedule text-area


This will detect if any changes pushed on GitHub repository. If so this Jenkins target will run

Now Go to Build section
Set Root POM as pom.xml as you can see a workspace folder create under your Jenkins target where Jenkins pull the codebase from Git server and build it locally.

Set Goals and Option as clean install.
Install step is requires as it maintains your artifacts in your local maven repository.


Last I want to deploy it on Tomcat server

To do that follow the following steps

First go to Tomcat installation directory under conf folder
Open tomcat-users.xml in edit mode
Add following lines under <tomcat-users> tag.

<role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="admin,manager-script,manager-gui"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>


Then go to Jenkins job configure section

 





In War/EAR files put target\MicroOrderService.war as maven generates artifacts in target directory.



After that Set user name as tomcat in Tomcat6.x section password is tomcat
Tomcat Url is http://localhost:8080

Click save button that will create MicroOrderService job.


To check hit BuildNow button and go to console output, you will see
Jenkins pull code from GitHub then build it using maven install the artifacts then deploy it in your Tomcat Server



Perform Same thing for Billingservice, create a new Job and configure that.


Now to Check just make a change in Source code
Push it to Git using Git Cmd
Steps
git add .
git commit -m ”change”
git push origin master

go to Jenkins dashboard you will see a build is initiated and deployed.






Main Classes in Micro Order Source Code


OrderService.java


package com.microservice.order;
 import java.io.IOException;
import java.io.StringReader;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.microservice.model.BillingStatus;
import com.microservice.model.OrderStatus;

@Path("/order")
public class OrderService {

    @GET
    @Path("{name}")
    @Produces(MediaType.TEXT_XML)
    public OrderStatus getOrderStatus(@PathParam("name") String name)
            throws ClientProtocolException, IOException {
        System.out.println("Orerd Item name is ==>" + name);
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet getRequest = new HttpGet(
                "http://localhost:8080/billingservice/billingservice/billing/"
                        + name);

        String response = getResponse(httpClient, getRequest);
        BillingStatus stat = new BillingStatus();
        stat = this.converStringToObject(stat, response);
        System.out.println("Return Object from JAXB "  + stat);

        OrderStatus status = new OrderStatus();
        status.setOrderName(stat.getItem());
        status.setOrderCost(stat.getPrice());
        return status;
    }

    public String getResponse(DefaultHttpClient client, HttpGet request) {

        HttpResponse response = null;
        String apiOutput = null;

        try {

            response = client.execute(request);

            // verify the valid error code first
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new RuntimeException("Failed with HTTP error code : "
                        + statusCode);
            }

            HttpEntity httpEntity = response.getEntity();
            apiOutput = EntityUtils.toString(httpEntity);
           
           

            System.out.println(apiOutput);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return apiOutput;

    }

    public <T> T converStringToObject(T t, String res) {

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(t.getClass());
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            t = (T) jaxbUnmarshaller.unmarshal(new StringReader(res));
        } catch (JAXBException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return t;

    }

}




Main Class in Billing service Module


package com.microservice.billing.service;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.microservice.billing.model.BillStatus;
import com.microservice.billing.utility.PriceCatalog;



@Path("/billing")
public class BillingService {
   
   
    @GET
    @Path("{name}")
    @Produces(MediaType.TEXT_XML)
    public BillStatus getOrderStatus(@PathParam("name")String name)
    {
       
        System.out.println("Check Item in Inventory ==>" + name);
        return PriceCatalog.getCatalog().getStatus(name.toLowerCase());
    }

}


PriceCatalog.java

package com.microservice.billing.utility;

import java.util.HashMap;   
import java.util.Map;

import com.microservice.billing.model.BillStatus;

public class PriceCatalog {
   
    private static PriceCatalog calalog=new PriceCatalog();
    private Map<String,String> priceMap=new HashMap<String,String>();
    private PriceCatalog()
    {
        init();
    }
   
    private void init()
    {
        priceMap.put("pen", "10");
        priceMap.put("shirt", "1000");
        priceMap.put("televison", "20000");
        priceMap.put("ac", "30000");
        priceMap.put("smartphone", "14000");
        priceMap.put("radio", "2000");
        priceMap.put("musicbox", "20000");
        priceMap.put("bike", "66000");
        priceMap.put("scooter", "26000");
        priceMap.put("pant", "100");
        priceMap.put("harddisc", "3000");
        // end of map
       
       
    }
   
    public static PriceCatalog getCatalog()
    {
        return calalog;
    }
   
    public BillStatus getStatus(String key)
    {
        BillStatus status= new BillStatus();
        if(key == null || priceMap.get(key)==null)
        {
            status.setItem("Sorry" + key + " Not found in Inventory!!");
            status.setPrice("Not Applicable");
            return status;
        }
        status.setItem(key.toUpperCase());
        String price =  priceMap.get(key) + " Rupees only.";
        status.setPrice(price);
        return status;
    }
   
   
   

}
Please Dowload Code base from


https://github.com/shami83/MicroOrderService
and 
https://github.com/shami83/BillingService
 


MicroServices with Devops Example



MicroServices with Devops  Example






In this post I show you How to create Micro service application and Manage it through Dev-ops.

To understand MicroServices please look at my blog post 

To understand Devops please look at my blog post


Tools are Used to implement Microservice
1.       Eclipse as Editor
2.       Java as Language
3.       Using REST Service to communicate between Microservices
4.       Maven as build tool
5.       Tomcat as Web server.


Tool are Used to Manage Microservices using Devops
1.       Jenkins as CI (Continous integration server).
2.       GitHub as SCM(Source control Management).


My intent is creating two Micro services


1.       An Order Service

2.       A Billing service

If client order for a product, Order Service project will communicate with Billing service project by REST API. Billing Service returns Product price if exists in the Product Catalog Otherwise It return a Message Product not found.

Order service accept this response and generate a new response to Client.


To Manage these Microservice, I using Devops

So that Two can be deployed independently, and Two projects are hosted in
GitHub. If someone do a change the code and push it in Github a build has been triggered by Jenkins and Once build is completed, Jenkins install the artifact that is the war file in Local Repo (maven Local REPO) then deploy it to Tomcat Server.

No Manual intervention is needed.


I have made it very simple but in real time there will be much more complexity than two simple services and we need Monitoring tool for health check for different projects which is absent in this example.

I have used Java for Two services but real time one could be in java another in PHP or Node JS any language.


Installation:

Java:  Install java from
Set JAVA_HOME in environment variables to java installation path.


Download Tomcat 6 Zip Version and extract it in your local drive that will your Tomcat installation directory.
Maven:
Extract the zip in your local file Set M2_Home as maven Installation path in your local directory.


Go to Git Command prompt after installation
Change Directory to C: Using Cd ../../
Now apply command (Need Internet connection)

after completing

again hit

Import two project in to Eclipse by import from local option.

If you want to create your new repositories, please go to Jenkins setup section and follow the step.

I prefer you create your new repositories to work independently. Unless if you clone it you will be dependent on me. If I gave you permission, then only you can push change on my project.







Jenkins :
 http://mirrors.jenkins-ci.org/war-stable/  (Take stable release. I use 1.65). Download war and deploy it to <Tomcat_installation_path>/webapps. In tomcat console when a message shows
“Jenkins full up and running” go to browser hit


First thing you need to require add plugins in to your local Jenkins Server

So Follow the steps
Go to Manage Jenkins from left panel
Go to manage Plugin
In Available Tab Search  with “git” and check gitplugin and github plugin
Hit install without restart button
Wait until installation finished.


Go to configure system from manage plugin
 






Create an account in GitHub and then add your username and your email Id.


Then Go to new Item create a Maven project.

Create a Job Name as “BuildandDeploy MicroOrderService”

Please see the following Screen shot




 
In the Source code management section set your Git repository URL
If you download source code from Git by download Zip and create your new repository and push the code

Steps are
After Download project from

and
using “ CloneorDownload”  button on GitHub
Extract Zip files

Create a project on Github using “+” button (Create new)
You will get a url like https://github.com/shami83/<projectname>.git


Execute following commands for two projects in your local computer

Go to  Git cmd
Go to the homefolder of the Extract project
a.       git init
b.      git add .
c.       git commit -m “demo”
d.      git push origin master

Please do the steps for two projects that will create two repositories in Git (require internet connection).

In jenkins on repository url put the url


If you clone it then you need my permission to push code to my stream, please send me a mail the at
mitrashamik@gmail.com or add a comment in blog.


Then put your credentials in credential section your username and password of Git repository.


Follow next step



In Build triggers section Check ” BuildWhen a change pushed to Git hub”

And poll SCM

Put value as * * * * * in schedule text-area

This will detect if any changes pushed on GitHub repository. If so this Jenkins target will run

Now Go to Build section
Set Root POM as pom.xml as you can see a workspace folder create under your Jenkins target where Jenkins pull the codebase from Git server and build it locally.

Set Goals and Option as clean install.
Install step is requires as it maintains your artifacts in your local maven repository.


Last I want to deploy it on Tomcat server

To do that follow the following steps

First go to Tomcat installation directory under conf folder
Open tomcat-users.xml in edit mode
Add following lines under <tomcat-users> tag.

<role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="tomcat" roles="admin,manager-script,manager-gui"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="role1" password="tomcat" roles="role1"/>


Then go to Jenkins job configure section

 





In War/EAR files put target\MicroOrderService.war as maven generates artifacts in target directory.


After that Set user name as tomcat in Tomcat6.x section password is tomcat
Tomcat Url is http://localhost:8080

Click save button that will create MicroOrderService job.


To check hit BuildNow button and go to console output, you will see
Jenkins pull code from GitHub then build it using maven install the artifacts then deploy it in your Tomcat Server



Perform Same thing for Billingservice, create a new Job and configure that.


Now to Check just make a change in Source code
Push it to Git using Git Cmd
Steps
git add .
git commit -m ”change”
git push origin master

go to Jenkins dashboard you will see a build is initiated and deployed.






Main Classes in Micro Order Source Code


OrderService.java


package com.microservice.order;
 import java.io.IOException;
import java.io.StringReader;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.microservice.model.BillingStatus;
import com.microservice.model.OrderStatus;

@Path("/order")
public class OrderService {

    @GET
    @Path("{name}")
    @Produces(MediaType.TEXT_XML)
    public OrderStatus getOrderStatus(@PathParam("name") String name)
            throws ClientProtocolException, IOException {
        System.out.println("Orerd Item name is ==>" + name);
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet getRequest = new HttpGet(
                "http://localhost:8080/billingservice/billingservice/billing/"
                        + name);

        String response = getResponse(httpClient, getRequest);
        BillingStatus stat = new BillingStatus();
        stat = this.converStringToObject(stat, response);
        System.out.println("Return Object from JAXB "  + stat);

        OrderStatus status = new OrderStatus();
        status.setOrderName(stat.getItem());
        status.setOrderCost(stat.getPrice());
        return status;
    }

    public String getResponse(DefaultHttpClient client, HttpGet request) {

        HttpResponse response = null;
        String apiOutput = null;

        try {

            response = client.execute(request);

            // verify the valid error code first
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                throw new RuntimeException("Failed with HTTP error code : "
                        + statusCode);
            }

            HttpEntity httpEntity = response.getEntity();
            apiOutput = EntityUtils.toString(httpEntity);
           
           

            System.out.println(apiOutput);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return apiOutput;

    }

    public <T> T converStringToObject(T t, String res) {

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(t.getClass());
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            t = (T) jaxbUnmarshaller.unmarshal(new StringReader(res));
        } catch (JAXBException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return t;

    }

}




Main Class in Billing service Module


package com.microservice.billing.service;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.microservice.billing.model.BillStatus;
import com.microservice.billing.utility.PriceCatalog;



@Path("/billing")
public class BillingService {
   
   
    @GET
    @Path("{name}")
    @Produces(MediaType.TEXT_XML)
    public BillStatus getOrderStatus(@PathParam("name")String name)
    {
       
        System.out.println("Check Item in Inventory ==>" + name);
        return PriceCatalog.getCatalog().getStatus(name.toLowerCase());
    }

}


PriceCatalog.java

package com.microservice.billing.utility;

import java.util.HashMap;   
import java.util.Map;

import com.microservice.billing.model.BillStatus;

public class PriceCatalog {
   
    private static PriceCatalog calalog=new PriceCatalog();
    private Map<String,String> priceMap=new HashMap<String,String>();
    private PriceCatalog()
    {
        init();
    }
   
    private void init()
    {
        priceMap.put("pen", "10");
        priceMap.put("shirt", "1000");
        priceMap.put("televison", "20000");
        priceMap.put("ac", "30000");
        priceMap.put("smartphone", "14000");
        priceMap.put("radio", "2000");
        priceMap.put("musicbox", "20000");
        priceMap.put("bike", "66000");
        priceMap.put("scooter", "26000");
        priceMap.put("pant", "100");
        priceMap.put("harddisc", "3000");
        // end of map
       
       
    }
   
    public static PriceCatalog getCatalog()
    {
        return calalog;
    }
   
    public BillStatus getStatus(String key)
    {
        BillStatus status= new BillStatus();
        if(key == null || priceMap.get(key)==null)
        {
            status.setItem("Sorry" + key + " Not found in Inventory!!");
            status.setPrice("Not Applicable");
            return status;
        }
        status.setItem(key.toUpperCase());
        String price =  priceMap.get(key) + " Rupees only.";
        status.setPrice(price);
        return status;
    }
   
   
   

}
Please Dowload Code base from


https://github.com/shami83/MicroOrderService
and 
https://github.com/shami83/BillingService