We have discussed the Microservices concepts like What are Microservices? Why use it? When to use it? in our previous article x An Introduction to Microservices Architecturex
In this article, we will discuss the pros/cons of microservices so that you can make a better decision and after that, we will see how to implement microservices with Spring Boot.
So be with us to learn that is the Future!!
Hardware has chased down applications but it is not getting better any more in comparison to internet traffic which is huge and unpredictable. So, there should be a change in architecture and web interface to handle such compatibility
Thus we have an architecture along with many other supporting technologies to tackles this and accept now monolithic applications are nearly gone.
Everything has its pros and cons in all aspect so here we will also discuss the same about Microservices.
Pros:
- You can have heterogeneous and latest types of technology stacks.
- A bulkhead application can be handled efficiently and its implantation is not cascaded so that if one system fails others can live resiliently.
- A huge and dynamic application will be scalable
- An application will be composed. Release cycles will not be costly.
- An application will be a group of isolated systems and deployment will not be overheard.
- Organized implementation helps to use human and technical resources efficiently.
Cons:
- It is very expensive for small applications; the initial cost is very high.
- Application and deployment will be distributed so integration and testing effort could be high.
- Sometimes developer complains about the duplication of efforts.
- Increasing service APIs could be very complex to refactor. Memory consumption could be high
Just quoting from Martin Fowler:
One reasonable argument wexve heard is that you shouldnxt start with a microservices architecture. Instead begin with a monolith, keep it modular, and split it into microservices once the monolith becomes a problem
So notably itxs good if you are starting, go with the monolith and keep it modular later if application grows to huge and complex then move to the Microservices as it is very expensive in terms of technology, efforts, and level of architecture design.
Further here we will create a project to show demo for this. Microservices is an architectural style whose implementation is supported by many frameworks i.e. Dropwizard, Vertx, Spring Boot, Restlet, Spark + Unirest (REST client, Spark doesnât provide a REST client itself), etc.
Over here to show the demo we will use Spring boot. This is the most popular framework for microservices as we know it is powered by Spring.
Implementation Of Microservices with Spring Boot
In this project, we will use Eureka server which is nothing but a service discovery pattern implementation. In this, every microservice is registered and a client looks up the Eureka server to access dependent microservice to complete the job.
We are trying to mimic the real world scenario here, wherein Eureka Server and different microservices are hosted separately.
Initialize Eureka Server
For our demo purpose, we are simply using Eureka as our service registration server. For that, you just need to use correct dependencies and specify Eureka properties in your applicationxs yaml or properties file.
Eureka Server POM
x?xml version="1.0" encoding="UTF-8"?x xproject xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"x xmodelVersionx4.0.0x/modelVersionx xgroupIdxcom.opencodez.microservicex/groupIdx xartifactIdxspring-discovery-serverx/artifactIdx xversionx0.0.1-SNAPSHOTx/versionx xpackagingxjarx/packagingx xnamexspring-discovery-serverx/namex xdescriptionxDemo project for Microservices with Spring Bootx/descriptionx xparentx xgroupIdxorg.springframework.bootx/groupIdx xartifactIdxspring-boot-starter-parentx/artifactIdx xversionx2.0.2.RELEASEx/versionx xrelativePath /x x!-- lookup parent from repository --x x/parentx xpropertiesx xproject.build.sourceEncodingxUTF-8x/project.build.sourceEncodingx xproject.reporting.outputEncodingxUTF-8x/project.reporting.outputEncodingx xjava.versionx1.8x/java.versionx xspring-cloud.versionxFinchley.BUILD-SNAPSHOTx/spring-cloud.versionx x/propertiesx xdependenciesx xdependencyx xgroupIdxorg.springframework.cloudx/groupIdx xartifactIdxspring-cloud-starter-netflix-eureka-serverx/artifactIdx x/dependencyx xdependencyx xgroupIdxorg.springframework.bootx/groupIdx xartifactIdxspring-boot-starter-testx/artifactIdx xscopextestx/scopex x/dependencyx x/dependenciesx xdependencyManagementx xdependenciesx xdependencyx xgroupIdxorg.springframework.cloudx/groupIdx xartifactIdxspring-cloud-dependenciesx/artifactIdx xversionx${spring-cloud.version}x/versionx xtypexpomx/typex xscopeximportx/scopex x/dependencyx x/dependenciesx x/dependencyManagementx xbuildx xpluginsx xpluginx xgroupIdxorg.springframework.bootx/groupIdx xartifactIdxspring-boot-maven-pluginx/artifactIdx x/pluginx x/pluginsx x/buildx xrepositoriesx xrepositoryx xidxspring-snapshotsx/idx xnamexSpring Snapshotsx/namex xurlxhttps://repo.spring.io/snapshotx/urlx xsnapshotsx xenabledxtruex/enabledx x/snapshotsx x/repositoryx xrepositoryx xidxspring-milestonesx/idx xnamexSpring Milestonesx/namex xurlxhttps://repo.spring.io/milestonex/urlx xsnapshotsx xenabledxfalsex/enabledx x/snapshotsx x/repositoryx x/repositoriesx x/projectx
application.yaml
Below is the main configuration that will make your application as Eureka Server
server: port: ${PORT:8761} # Indicate the default PORT where this service will be started eureka: client: registerWithEureka: false #telling the server not to register himself in the service registry fetchRegistry: false server: waitTimeInMsWhenSyncEmpty: 0 #wait time for subsequent sync
Once we start our application, the Eureka Server will display details about all services registered and available to use.
At this moment, we donxt have any service registered hence you see the warning in red.
Microservices Clients
We will define two simple projects as Employee Service and Employer Service. These will register with Eureka Server and become available. The core of these projects would be its application properties, in which they will define the name and other parameters with which they will register with the server.
Employee Service
server: port: 8098 #default port where the service will be started eureka: #tells about the Eureka server details and its refresh time instance: leaseRenewalIntervalInSeconds: 1 leaseExpirationDurationInSeconds: 2 client: serviceUrl: defaultZone: http://127.0.0.1:8761/eureka/ healthcheck: enabled: true lease: duration: 5 spring: application: name: employee-service #current service name to be used by the eureka server
Employer Service
server: port: 9098 #port number eureka: instance: leaseRenewalIntervalInSeconds: 1 leaseExpirationDurationInSeconds: 2 client: serviceUrl: defaultZone: http://127.0.0.1:8761/eureka/ healthcheck: enabled: true lease: duration: 5 spring: application: name: employer-service #service name logging: level: com.opencodez.microservice: DEBUG
Once we start both the client project, they will get registered with Eureka.
Note that the red warning has gone.
Using the Published Microservice
Both the client has registered themselves with distinct names. These names will be used to find the service in other clients. In our example, the EMPLOYEE-SERVICE returns static data. This data is fetched in EMPLOYER SERVICE and displayed.
EMPLOYEE-SERVICE
@RequestMapping(value = "/getEmployeeDetail/" , method = RequestMethod.GET) public Employee getEmployeeDetail(@RequestParam("id") int id) { System.out.println("Getting employee detail..."); ListxEmployeex list = new ArrayListxEmployeex(); //sample data list.add(new Employee(1, "Alex")); list.add(new Employee(2, "Robin")); return list.get(id-1); }
We have only 2 predefined data set, we will return from this set only.
EMPLOYER SERVICE
private static String SERVICE = "http://EMPLOYEE-SERVICE/getEmployeeDetail/?id="; @RequestMapping(value = "/getEmployeeDetailForEmployer/{empID}", method = RequestMethod.GET) public String getEmployeeDetailForEmployer(@PathVariable int empID) { String response = restTemplate.exchange(SERVICE + empID, HttpMethod.GET, null, new ParameterizedTypeReferencexStringx() { }).getBody(); System.out.println("Response Received as " + response); return "Employee id - " + empID + " \n Employee Details " + response; }
Note how the employer service is accessing employee service. It doesnxt have any host or port. Based on only service name, it managed to locate and use the service.
Output Conclusion
Here we have seen the probably tiniest implementation of microservices based on Spring boot. Here services are very isolated to the server configuration and deployment.
You can download complete code from out GitHub Repository
Download Code