Gateway Service using Spring Cloud Netflix Zuul


Hi, I am Malathi Boggavarapu working at Volvo Group and i live in Gothenburg, Sweden. I have been working on Java since several years and had vast experience and knowledge across various technologies.

 In this post we will see how to map our MicroServices in the Cloud using Intelligent Routing via Netflix Api. So what is meant by Intelligent Routing? Let's jump start into the details.

Intelligent Routing

Each of the individual services would be running on different port, different addresses or a combination of both. And they also likely have different paths and different API's to interact with. As a user or a client of those services such as mobile app or web app, interacting with each of the individual services which could easily be in double or triple digits would be a nightmare. Instead we can use Intelligent Routing to make our application appear as it was a single system. 

Intelligent Routing via a Gateway Service

Routing is implemented via Gateway service or API Gateway. It is defined as single point of entry for all clients. Gateway Service is lot like a front door to our system. Each of the individual services is then located behind this door and all the requests must inter-through it. 

Gateway Service provides the following functionalities.

Dynamic Routing and Delivery: It means at runtime it can decide where it should route a request and if it should even route a request at all

Security: It provides the ability to authenticate all the incoming requests and filter out bad requests. 

Auditing and Logging:  It also provide auditing and logging request since all the requests must inter-through the gateway. 

Request enhancement: It allows you to add some additional information to the request. A concrete example of this is the way Netflix uses their gateway. They use gateway service to do geo-location lookup for all  incoming requests and add that additional information as additional request header so that it is available for all downstream services. 

Load Balancer: The gateway service can also acts as load balancer  for individual services. 

Different APIs for different clients: Another feature of gateway service is ability to provide different APIs for different clients. Different clients such as mobile or web clients have different needs in the way they call API's . For instance, it is Okay for web client to interact with several endpoints to accomplish certain functionality. But the same may not be true for mobile client which may be better served with a single endpoint.


Intelligent Routing with Spring cloud and Netflix zuul

Let's start with demo application. Head on over to start.spring.io and we are gonna create 3 different projects now.

1) gateway-service

Group: com.malathiboggavarapu
Artifact:  gateway-service
Dependencies: Zuul, Eureka Discovery

Go ahead and click Generate Project and that would create a gateway-service.zip file for you.

2) hello-service

Group: com.malathiboggavarapu
Artifact:  hello-service
Dependencies: Web, Eureka Discovery

Go ahead and click Generate Project and that would create a hello-service.zip file for you.

3) goodbye-service

Group: com.malathiboggavarapu
Artifact:  goodbye-service
Dependencies: Web, Eureka Discovery

Go ahead and click Generate Project and that would create a goodbye-service.zip file for you.
Unzip all of those ZIP files and head over to your IDE and import all the projects. You also need the ServiceDiscovery server. So if you don't already have that, import it into IDE from my github account. Please follow the link

https://github.com/MalathiBoggavarapu/SpringCloud

Inorder to import from github, right click on empty space of Project Explorer, go to New -> Other. Choose the option Maven -> "Checkout Maven Projects from SCM" and click Next. Copy the above github url and paste it there and click Next and click Finish. We now have everything that we need to build MicroServices application using Gateway Sevrice.

Expand the gateway-service project and locate the main application class GatewayServiceApplication.java.

1) Add annotation @EnableZuulProxy
2) Add annotation @EnableDiscoveryClient



Next open up the application.properties and configure the gateway-service. Add the following properties

spring.application.name=gateway-service
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

Now expand the hello-service application and locate the main application class HelloServiceApplication. Add the following annotations to the class.

1) @EnableDiscoveryClient
2) @RestController


Normally it is a bad idea to make this class annotated as Restcontroller. We need to actually create a seperate class for this. But to make it simple i am doing it. So it is OK for now. Add a handler method hello() as shown above which returns a simple string "Hello!" and annotate it with @RequestMapping.

Now it's time to configure hello-service application using application.properties. Go ahead and add the following properties. The last property is the location of the ServiceDiscovery server.

spring.application.name=hello
server.port=1111
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

Now expand the goodbye-service application and locate the main application class GoodbyeServiceApplication. Add the following annotations to the class.

1) @EnableDiscoveryClient
2) @RestController


Now it's time to configure goodbye-service application using application.properties. Go ahead and add the following properties. The last property is the location of the ServiceDiscovery server.

spring.application.name=goodbye
server.port=2222
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

Now it's time to start all the services. We need to start ServiceDiscovery Server, gateway-service, hello-service, goodbye-service.

1) Open DiscoveryServerApplication. Right click and select Run As -> Spring Boot App.
2) Open GatewayServiceApplication. Right click and select Run As -> Spring Boot App.
3) Open HelloServiceApplication. Right click and select Run As -> Spring Boot App.
4) Open GoodbyeServiceApplication. Right click and select Run As -> Spring Boot App.

Let's open up the browser and try things out. From the browser hit the following urls and check

http://localhost:8080/hello
http://localhost:8080/goodbye

These exampels are very simplistic but a lot is going on in the background. Whenwe visit the above urls, the gateway-service looked up the service with the name goodbye from the Servicediscovery server and proxied th etraffic to that service and proxied the response back to the browser.

Creating Filters with Netflix Zuul and Spring Cloud

One of the key features in Netflix zuul is the ability to define Filters. Filters allows you to intercept and control the requests and responses that pass through the gateway. Zuul has support for several different kind of Filters.


Filter Types

1) pre - It is executed before the request i routes
2) route - It allows to direct the request in anyway you want. Earlier when we defined the @EnableZuulProxy annotation in the main application class, we are telling spring to setup some predefined route filters to proxy our request to backend services.
3) post - As the name suggest, the filters are executed after the request is routed
4) error - It is responsible for handling if any of the previous filter types results in an error

Now let's create a demo application to implement Zuul filter to add an additional header to the incoming request so that it is available for downstream services to consume. In our previous sections we have created 4 different services. One is ServiceDiscovery server to discover services, gateway-service and two application services goodbye service and hello service. Since we are building a filter we start with gateway-service.

So go ahead to gateway-service application and create a new package com.malathiboggavarapu.filters. Create a class called AddRequestHeaderFilter that extends ZuulFilter. See below.


Inorder to add request header to the request, we need access to RequestContext. Imagine that our usecase is to add location of the incoming request. So set header x-location and set the value as USA.

Now go to our main application class GatewayServiceApplication, add @Configuration annotation at class level. Create a new method addRequestHeaderFilter. See below.



Now it's time to do changes in hello-service. Open the main application class HelloServiceApplication and do changes to the handler method hello(). See below.



If you notice the above code, we added a new parameter location to the method and annotated it with @RequestHeader and pass x-location parameter which gateway-service adds to the request header when it receives the request. Print the location as shown in the above example.

Now go ahead and start the servers. You need to start servers of discovery-server, gateway-service and hello-service. Go to the browser and hit http://localhost:8080 and check.

So that's all about Mapping Services using Intelligent Routing via Gateway service.
Hope it is helpful. Please post your comments below for any questions.
Happy learning!

Comments

Post a Comment

Popular posts from this blog

Bash - Execute Pl/Sql script from Shell script

Gradle Fundamentals

Load Balancing using Spring Cloud Netflix Ribbon