Spring Cloud : Routing with Zuul

A common challenge when building microservices is providing a unified interface to the consumers of your system. The fact that your services are split into small composable apps shouldn’t be visible to users or result in substantial development effort.

To solve this problem, Netflix (a major adopter of microservices) created and open-sourced its Zuul proxy server. Zuul is an edge service that proxies requests to multiple backing services. It provides a unified “front door” to your system, which allows a browser, mobile app, or other user interface to consume services from multiple hosts without managing cross-origin resource sharing – CORS (browser restrict this) and authentication for each one.
We have also potential reduce the number of trips to the backend if we can cosolidate a number of backend call into one call. We have the ability to implement cacheing the in the API gateway if we want to.

You can integrate Zuul with other Netflix projects like Hystrix for fault tolerance and Eureka for service discovery, or use it to manage routing rules, filters, and load balancing across your system.

We have the following setup. We have Eureka running on 8761. Product-service runs on 8200 and user-service runs on 8100.

spring-zuul1

Now Eureka is just a discovery service. It will not redirect to the services registered to it. Also, its possible that there are multiple instances of a particular service.

ts easy to make a Zuul server. Just make a boot application with sprng-cloud-starter-zuul dependencies. pom.xml:


<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath />
</parent>

<groupId>com.mynotes.spring.cloud</groupId>
<artifactId>zuul-server</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>zuul-server</name>
<description>Demo project for Spring Cloud cloud zuul-server</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
</project>

Just write @EnableZuulProxy over the starting main class and thats it. ZuulApplication.java


package com.mynotes.spring.cloud.zuul;

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

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {

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

}

application.yml

server:
port: 8050

eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

Zuul needs to know about Eureka server. It may or may not registers to it, but it should know where it is. That way it knows where to redirect based on the url.

Default behaviour of zuul is Eureka clients ids become URIs. For example
/product-service routes to the “product-service” service
/user-service routes to the “user-service” service

These defaults can be change by adding zuul.routes.* properties in config file.

Zull already includes Ribbon and Hystrix. Since Ribbon is involved here, the call is automatically to the best backend server whenever multiple instances of the backend server are running.
And since hystrix is involed, each call is made with the hystrix command and give a simple circuit breaker behaviour.

Lets test by hitting zuul server:

spring-zuul3 spring-zuul2

As you can see, client only hits one gateway. For production , you might want to keep behind nginx etc.

 

Advertisements
%d bloggers like this: