In this article, we are going to learn about microservice architecture in Java. Microservice is a popular architecture used to build software applications. In a microservice architecture, each service can be developed, deployed, and scaled independently. This can be useful to build applications much faster as compared to monoliths as it gets complicated over time. Each service in microservices communicates with each other using REST API or messaging queue.
Microservices, as the name implies, refer to a software architecture approach where an application is broken down into a collection of small, self-contained services. These services are designed to perform specific functions or tasks within the larger application context. What distinguishes microservices from traditional monolithic architectures is their emphasis on modularity and independence.
Eureka Server is an application that contains information about all micro services including the name of the service, port, and IP address. Each microservice has to register itself with the Eureka Server. Each service sends a heartbeat to the Eureka Server that helps the Eureka Server to check if the service is running or not.
As you can see in this image we have 2 microservices registered with the Eureka Server i.e. API Gateway and Auth Service.
Create an Eureka Server project that includes this dependency;
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
In the Application.properties file add this property;
spring.application.name=eureka-server server.port=8761 eureka.client.register-with-eureka=false eureka.client.fetch-registry=false
The Eureka Server will run on port 8761.
register-with-eureka=false and client.fetch-registry=false
This means we do not want to register Eureka with itself.
Then we have to add @EnableEurekaServer annotation like this;
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
Related read: Spring Boot Microservices and Eureka Server: Setup and Benefits
Each microservice runs on a different port so if we have 12 microservices running on different ports. We have different URLs for each service. Instead of having different URLs and ports, what if we have only one URL which will then take care of routing the request to that service.
This can be achieved using API Gateway. API Gateway provides features like routing and filtering the request. API Gateway uses reactive, non-blocking architecture which means it will take all requests sent to it asynchronously and then route the request to service and then return the response back to the client. It acts as a proxy between clients and microservices.
Create an API Gateway application which includes the following dependencies;
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
Add @EnableDiscoveryClient which will help the service to connect with Eureka Server;
@SpringBootApplication @EnableDiscoveryClient public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
To add routing to different microservices in the API Gateway we will make use of RouteLocator;
@Configuration public class ApiGatewayConfiguration { @Autowired private ApiFilter apiFilter; @Bean public RouteLocator gatewayRouter(RouteLocatorBuilder builder) { return builder.routes() .route(p->p.path("/auth/*").uri("lb://auth-service") .route(p->p.path("/test").filters(f->f.filter(apiFilter)).uri("lb://auth-service")).build(); } }
Every request to the API Gateway will come to the routing locator. The route locator will try to match the request pattern and then transfer the request to the respective services. We can also use filters before transferring the request to service which can include authorization of users.
@Component public class ApiFilter implements GatewayFilter { private static RestTemplate restTemplate; static { restTemplate = new RestTemplate(); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request= exchange.getRequest(); List<String> unsecuredAPIs = List.of("/auth/signup","/auth/login","/auth/validate"); Predicate<ServerHttpRequest> isAPISecured = r-> unsecuredAPIs.stream().noneMatch(uri->r.getURI().getPath().contains(uri)); if(isAPISecured.test(request)) { if(!request.getHeaders().containsKey("Authorization")) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } String token = getJwtTokenFromRequest(request); ResponseEntity<Map> responseEntity = restTemplate.getForEntity("http://localhost:5001/auth/validate/"+token,Map.class); Map<String,Object> validationResponse=(Map<String, Object>) responseEntity.getBody(); boolean isValid = Boolean.parseBoolean(validationResponse.getOrDefault("isValid", "false").toString()); if (!isValid) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); } } return chain.filter(exchange); } private String getJwtTokenFromRequest(ServerHttpRequest request) { List<String> headers = request.getHeaders().getOrEmpty("Authorization"); if(headers.isEmpty()) { return null; } String bearerToken = headers.get(0); if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer")) { return bearerToken.substring(7,bearerToken.length()); } return null; } }
We have to implement GatewayFilter. It has a method named filter which has two parameters named ServerWebExchange exchange, and GatewayFilterChain. We will take request information from the exchange.getRequest();
Then will take out headers from the request. To verify the user we will send a request to the Auth Service which will validate the token. If it is invalid we return the request from Filter with an UnAuthorized Error otherwise we will transfer the request to the service.
Each service in the architecture diagram is a microservice built using Spring boot and Spring cloud-config. Each service should follow the Single Responsibility principle. One service failure should not affect the other services. Each service can have its own database.
They should be deployed independently. Services can be written in different languages. They may have different databases one service may use MySQL and another may use MongoDB.
To create a service it should have the following dependencies;
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
To enable the service to connect to the Eureka Server add annotation @EnableEurekaClient.
Service can communicate with others using Rest Template or by using any messaging queue.
We can divide the communication between synchronous and asynchronous.
In synchronous communication we can use;
In asynchronous communication we can use;
In this blog, we learned about microservice architecture using Eureka Server. By using this architecture developers can break down monolithic applications into smaller services that communicate through API. Spring Cloud, with its rich ecosystem of tools and libraries, simplifies the implementation of microservices by providing essential features like service discovery, load balancing, configuration management, and distributed tracing.
How to Effectively Hire and Manage A Remote Team of Developers.
Download NowThe Mindbowser team's professionalism consistently impressed me. Their commitment to quality shone through in every aspect of the project. They truly went the extra mile, ensuring they understood our needs perfectly and were always willing to invest the time to...
CTO, New Day Therapeutics
I collaborated with Mindbowser for several years on a complex SaaS platform project. They took over a partially completed project and successfully transformed it into a fully functional and robust platform. Throughout the entire process, the quality of their work...
President, E.B. Carlson
Mindbowser and team are professional, talented and very responsive. They got us through a challenging situation with our IOT product successfully. They will be our go to dev team going forward.
Founder, Cascada
Amazing team to work with. Very responsive and very skilled in both front and backend engineering. Looking forward to our next project together.
Co-Founder, Emerge
The team is great to work with. Very professional, on task, and efficient.
Founder, PeriopMD
I can not express enough how pleased we are with the whole team. From the first call and meeting, they took our vision and ran with it. Communication was easy and everyone was flexible to our schedule. I’m excited to...
Founder, Seeke
Mindbowser has truly been foundational in my journey from concept to design and onto that final launch phase.
CEO, KickSnap
We had very close go live timeline and Mindbowser team got us live a month before.
CEO, BuyNow WorldWide
If you want a team of great developers, I recommend them for the next project.
Founder, Teach Reach
Mindbowser built both iOS and Android apps for Mindworks, that have stood the test of time. 5 years later they still function quite beautifully. Their team always met their objectives and I'm very happy with the end result. Thank you!
Founder, Mindworks
Mindbowser has delivered a much better quality product than our previous tech vendors. Our product is stable and passed Well Architected Framework Review from AWS.
CEO, PurpleAnt
I am happy to share that we got USD 10k in cloud credits courtesy of our friends at Mindbowser. Thank you Pravin and Ayush, this means a lot to us.
CTO, Shortlist
Mindbowser is one of the reasons that our app is successful. These guys have been a great team.
Founder & CEO, MangoMirror
Kudos for all your hard work and diligence on the Telehealth platform project. You made it possible.
CEO, ThriveHealth
Mindbowser helped us build an awesome iOS app to bring balance to people’s lives.
CEO, SMILINGMIND
They were a very responsive team! Extremely easy to communicate and work with!
Founder & CEO, TotTech
We’ve had very little-to-no hiccups at all—it’s been a really pleasurable experience.
Co-Founder, TEAM8s
Mindbowser was very helpful with explaining the development process and started quickly on the project.
Executive Director of Product Development, Innovation Lab
The greatest benefit we got from Mindbowser is the expertise. Their team has developed apps in all different industries with all types of social proofs.
Co-Founder, Vesica
Mindbowser is professional, efficient and thorough.
Consultant, XPRIZE
Very committed, they create beautiful apps and are very benevolent. They have brilliant Ideas.
Founder, S.T.A.R.S of Wellness
Mindbowser was great; they listened to us a lot and helped us hone in on the actual idea of the app. They had put together fantastic wireframes for us.
Co-Founder, Flat Earth
Ayush was responsive and paired me with the best team member possible, to complete my complex vision and project. Could not be happier.
Founder, Child Life On Call
The team from Mindbowser stayed on task, asked the right questions, and completed the required tasks in a timely fashion! Strong work team!
CEO, SDOH2Health LLC
Mindbowser was easy to work with and hit the ground running, immediately feeling like part of our team.
CEO, Stealth Startup
Mindbowser was an excellent partner in developing my fitness app. They were patient, attentive, & understood my business needs. The end product exceeded my expectations. Thrilled to share it globally.
Owner, Phalanx
Mindbowser's expertise in tech, process & mobile development made them our choice for our app. The team was dedicated to the process & delivered high-quality features on time. They also gave valuable industry advice. Highly recommend them for app development...
Co-Founder, Fox&Fork