DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Databases
  4. Microservices Communication: Zuul API Gateway

Microservices Communication: Zuul API Gateway

Learn how to use a Zuul proxy in microservices development to create more fluid, robust design that is less prone to errors.

Shamik Mitra user avatar by
Shamik Mitra
·
Aug. 25, 17 · Tutorial
Like (22)
Save
Tweet
Share
218.10K Views

Join the DZone community and get the full member experience.

Join For Free

In the previous microservice tutorial, we learned about microservices handling client side load balancing.

Here, we will discuss Zuul proxy.

What Is a Zuul Proxy?

The crux of the microservices pattern is to create an independent service which can be scaled and 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 and show the important information in the UI.

From a UI developer perspective, to collect information from fifty underlying microservices, it has to call fifty REST APIs, as each microservice exposes a REST API for communication. So the client has to know the details of all REST API and URL patterns/ports to call them. Certainly, it does not sound like a good design. It is kind of a breach of encapsulation; the UI has to know all microservices server/port details to query the services.

Moreover, think about the common aspects of a web program, like CORS, authentication, security, and monitoring in terms of this design- each microservice team has to develop all these aspects into its own service, so the same code has been replicated over fifty microservices. Changes in the authentication requirements or CORS policy will ripple over all services. It is against the 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 is written and the client communicates with that common service. Here, the Zuul (The Gatekeeper/Demigod) concept pops up.

Image title

Zuul acts as an API gateway or Edge service. It receives all the requests coming from the UI and then delegates the requests 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 the client/UI. The client calls this service as a proxy for an internal microservice, then this service delegates the request to the appropriate service.

The advantage of this type of design is that common aspects like CORS, authentication, and 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. Say we want to append a special tag into the request header before it reaches the internal microservices, we can do it in the Edge service.

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

Image title

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 the 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, it needs to be registered in the Eureka server so it can be aware of other services. Also, this service runs on port 8084.

Pay attention to the last two properties:
 zuul.routes.employeeUI.serviceId=EmployeeDashBoard 

By this, we are saying if any request comes to the API gateway in form of /employeeUI, it will redirect to the EmployeeDashBoard microservice. So, if you hit the following URL: http://localhost:8084/employeeUI/dashboard/1, it will redirect to http://localhost:8081/dashboard/1.

Note that the UI developer is only aware of the Gateway service port; it is the Gateway service's responsibility to route the service to the 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.

With  zuul.host.socket-timeout-millis=30000 -- , we instruct Spring Boot to wait for the response for 30000 ms until Zuul's internal Hystrix timeout will kick off and show 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.

Now start the config server, Eureka server, EmployeeSearchService, EmployeeDashboardService, and EmployeeZuulService respectively.

If you hit the following URL: http://localhost:8084/employeeUI/dashboard/1, you will see the following output:

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


microservice API zuul Web Service

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • OpenID Connect Flows
  • How Do the Docker Client and Docker Servers Work?
  • 2023 Software Testing Trends: A Look Ahead at the Industry's Future
  • Understanding gRPC Concepts, Use Cases, and Best Practices

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: