Microservices Communication: Zuul API Gateway

In the previous Microservice tutorial, we have learned How Microservices handling Client side Load balancing.

Here, we will discuss Zuul proxy.

What is a Zuul Proxy ?

The Crux of Microservices pattern is to create an Independent service which can be scaled, deployed independently. So in a complex Business Domain-- more than  50-100 Microservices is very common. Let's Imagine a System where we have fifty Microservices now we have to implement a UI which is kind of a dashboard -- So it calls Multiple services to fetch the important information and show that in UI.

From UI developer perspective --  to collect information from fifty underlying Microservices it has to call fifty Rest API as each Microservice exposes a Rest API for Communication. So the client has to know the details of all Rest API and URL pattern /port to call them. Certainly, it is not sound like a good design. It is kind of a breaching of  Encapsulation, UI has to know all Microservices server/port details to query the services.

Moreover think about the Common aspects of a Web programming like CORS, Authentication, Security, Monitoring in terms of this design -- Each Microservice team has to develop all these aspects into its own service so same code has been replicated over fifty Microservices, Change in the Authentication requirements or CORS policy rippled overall services. It is against of DRY principle. So This type of design is very error prone and rigid. To make it robust It has to be changed in such way so that we have only one entry point where all common aspects code are written and client communicates with that common service. Here the Zuul(The Gatekeeper/demigod ) Concept pops up.


microservices architecture-Zuul




Edge Service: Zuul acts as an API gateway or Edge service. It receives all the request comes from UI and then delegates the request to internal Microservices. So we have to create a brand new Microservice which is Zuul enabled and this service sits on top of all other Microservices. It acts as an Edge service or Client facing service. Its Service API should be exposed to client/UI, Client calls this service as a proxy for Internal Microservice then this service delegates the request to appropriate service.

The advantage of this type of design is common aspects like CORS, Authentication, Security can be put into a centralized service, so all common aspects will be applied on each request, and if any changes occur in the future we just have to update the business logic of this Edge Service.


Also, we can implement any Routing rules or any Filter implementation says we want to append a special tag into the request header before it reaches to internal Microservices we can do it in the Edge service.

As Edge service itself is a Microservice so it can be independently scalable, deployable. So we can perform some load testing also.





edge services








Coding Time:

Create a project using http://start.spring.io/ named it as EmployeeZuluService select Zuul and Eureka Discovery module as Edge service itself a Eureka client.

The pom.xml  will look like following


<?xml version="1.0" encoding="UTF-8"?>
<project 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">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.example</groupId>
   <artifactId>EmployeeZuulService</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>EmployeeZuulService</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.6.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-cloud.version>Dalston.SR2</spring-cloud.version>
   </properties>

   <dependencies>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-eureka</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-zuul</artifactId>
      </dependency>

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
      </dependency>
   </dependencies>

   <dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>${spring-cloud.version}</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
   </dependencyManagement>

   <build>
      <plugins>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
      </plugins>
   </build>


</project>



Next, rename the application.properties to bootstrap.properties and write down the following configuration there.




spring.application.name=EmployeeAPIGateway
eureka.client.serviceUrl.defaultZone:http://localhost:9091/eureka
server.port=8084
security.basic.enable: false   
management.security.enabled: false
zuul.routes.employeeUI.serviceId=EmployeeDashBoard
zuul.host.socket-timeout-millis=30000

As this is a Microservice so its need to be registered in Eureka server so it can be aware of other services.

Also, this service runs on port 8084.

Pay attention to lats two properties
zuul.routes.employeeUI.serviceId=EmployeeDashBoard

By this, we say if any request comes to API gateway in form of

/employeeUI it will redirect to EmployeeDashBoard Microservice

So if you hit the following URL

It will redirect to


Note that UI developer only aware of the Gateway service port, it is Gateway service responsibility to route the service to appropriate Microservice.

NB: Zuul can be implemented without Eureka server, In that case, you have to provide the exact URL of the service where it will be redirected.



zuul.host.socket-timeout-millis=30000 -- by this we instruct Spring boot to wait response for 30000 ms unless Zuuls internal Hystrix timeout will kickoff and showing you the error.

Now add @EnableZuulproxy and @EnableDiscoveryClient on top of  EmployeeZuulServiceApplication class

package com.example.EmployeeZuulService;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class EmployeeZuulServiceApplication {

   public static void main(String[] args) {
      SpringApplication.run(EmployeeZuulServiceApplication.class, args);
   }
}



Our API gateway service is ready.

Noe starts the config server, Eureka server, EmployeeSearchService, EmployeeDasboradService and, EmployeeZuulService respectively.

If you hit the following URL


You will see the following output

{
 "employeeId": 1,
 "name": "Shamik  Mitra",
 "practiceArea": "Java",
 "designation": "Architect",
 "companyInfo": "Cognizant"
}

Post a Comment