- Spring Cloud - Discussion
- Spring Cloud - Useful Resources
- Spring Cloud - Quick Guide
- Distributed Logging using ELK and Sleuth
- Streams with Apache Kafka
- Spring Cloud - Gateway
- Circuit Breaker using Hystrix
- Spring Cloud - Load Balancer
- Synchronous Communication with Feign
- Service Discovery Using Eureka
- Dependency Management
- Spring Cloud - Introduction
- Spring Cloud - Home
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Spring Cloud - Gateway
Introduction
In a distributed environment, services need to communicate with each other. However, this is interservice communication. We also have use-cases where a cpent outside our domain wants to hit our services for the API. So, either we can expose the address of all our microservices which can be called by cpents OR we can create a Service Gateway which routes the request to various microservices and responds to the cpents.
Creating a Gateway is much better approach here. There are two major advantages −
The security for each inspanidual services does not need to maintained.
And, cross-cutting concerns, for example, addition of meta-information can be handled at a single place.
Netfpx Zuul and Spring Cloud Gateway are two well-known Cloud Gateways which are used to handle such situations. In this tutorial, we will use Spring Cloud Gateway.
Spring Cloud Gateway – Dependency Setting
Let us use the case of Restaurant which we have been using. Let us add a new service (gateway) in front of our two services, i.e., Restaurant services and Customer Service. First, let us update the pom.xml of the service with the following dependency −
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netfpx-eureka-cpent</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> </dependencies>
And then, annotate our Spring apppcation class with the correct annotation, i.e., @EnableDiscoveryCpent.
package com.tutorialspoint; import org.springframework.boot.SpringApppcation; import org.springframework.boot.autoconfigure.SpringBootApppcation; import org.springframework.cloud.cpent.discovery.EnableDiscoveryCpent; @SpringBootApppcation @EnableDiscoveryCpent pubpc class RestaurantGatewayService{ pubpc static void main(String[] args) { SpringApppcation.run(RestaurantGatewayService.class, args); } }
We are annotating with @EnableDiscoveryCpent because we want to use Eureka service discovery to get the pst of hosts which are serving a particular use-case
Dynamic Routing with Gateway
The Spring Cloud Gateway has three important parts to it. Those are −
Route − These are the building blocks of the gateway which contain URL to which request is to be forwarded to and the predicates and filters that are appped on the incoming requests.
Predicate − These are the set of criteria which should match for the incoming requests to be forwarded to internal microservices. For example, a path predicate will forward the request only if the incoming URL contains that path.
Filters − These act as the place where you can modify the incoming requests before sending the requests to the internal microservices or before responding back to the cpent.
Let us write a simple configuration for the Gateway for our Restaurant and Customer service.
spring: apppcation: name: restaurant-gateway-service cloud: gateway: discovery: locator: enabled: true routes: - id: customers uri: lb://customer-service predicates: - Path=/customer/** - id: restaurants uri: lb://restaurant-service predicates: - Path=/restaurant/** server: port: ${app_port} eureka: cpent: serviceURL: defaultZone: http://localhost:8900/eureka
Points to note about the above configuration −
We have enabled the discovery.locator to ensure that the gateway can read from the Eureka server.
We have used Path predicated here to route the request. What this means is that any request which begins with /customer would be routed to Customer Service and for /restaurant, we will forward that request to Restaurant Service.
Now let us setup other services prior to the Gateway service −
Start the Eureka Server
Start the Customer Service
Start the Restaurant Service
Now, let us compile and execute the Gateway project. We will use the following command for the same −
java -Dapp_port=8084 -jar . argetspring-cloud-gateway-1.0.jar
Once this is done, we have our Gateway ready to be tested on port 8084. Let’s first hit http://localhost:8084/customer/1 and we see the request is correctly routed to Customer Service and we get the following output −
{ "id": 1, "name": "Jane", "city": "DC" }
And now, hit our restaurant API, i.e., http://localhost:8084/restaurant/customer/1 and we get the following output −
[ { "id": 1, "name": "Pandas", "city": "DC" }, { "id": 3, "name": "Little Italy", "city": "DC" } ]
This means that both the calls were correctly routed to the respective services.
Predicates & Filters Request
We had used Path predicate in our above example. Here are a few other important predicates −
Predicate | Description |
---|---|
Cookie predicate (input: name and regex) | Compares the cookie with the ‘name’ to the ‘regexp’ |
Header predicate (input: name and regex) | Compares the header with the ‘name’ to the ‘regexp’ |
Host predicate (input: name and regex) | Compares the ‘name’ of the incoming to the ‘regexp’ |
Weight Predicate (input: Group name and the weight) | Weight Predicate (input: Group name and the weight) |
Filters are used to add/remove data from the request before sending the data to the downstream service or before sending the response back to the cpent.
Following are a few important filters for adding metadata.
Filter | Description |
---|---|
Add request header filter (input: header and the value) | Add a ‘header’ and the ‘value’ before forwarding the request downstream. |
Add response header filter (input: header and the value) | Add a ‘header’ and the ‘value’ before forwarding the request upstream that is to the cpent. |
Redirect filter (input: status and URL) | Adds a redirect header along with the URL before passing over o the downstream host. |
ReWritePath (input: regexp and replacement) | This is responsible for rewriting the path by replacing the ‘regexp’ matched string with the input replacement. |
The exhaustive pst for filters and predicates is present at
Monitoring
For monitoring of the Gateway or for accessing various routes, predicates, etc., we can enable the actuator in the project. For doing that, let us first update the pom.xml to contain the actuator as a dependency.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
For monitoring, we will use a separate apppcation property file which would contain flags to enable the actuator. So, here is how it would look pke −
spring: apppcation: name: restaurant-gateway-service cloud: gateway: discovery: locator: enabled: true routes: - id: customers uri: lb://customer-service predicates: - Path=/customer/** - id: restaurants uri: lb://restaurant-service predicates: - Path=/restaurant/** server: port: ${app_port} eureka: cpent: serviceURL: defaultZone: http://localhost:8900/eureka management: endpoint: gateway: enabled: true endpoints: web: exposure: include: gateway
Now, to pst all the routes, we can hit: http://localhost:8084/actuator/gateway/routes
[ { "predicate": "Paths: [/customer/**], match traipng slash: true", "route_id": "customers", "filters": [], "uri": "lb://customer-service", "order": 0 }, { "predicate": "Paths: [/restaurant/**], match traipng slash: true", "route_id": "restaurants", "filters": [], "uri": "lb://restaurant-service", "order": 0 } ]
Other important APIs for monitoring −
API | Description |
---|---|
GET /actuator/gateway/routes/{id} | Get information about a particular route |
POST /gateway/routes/{id_to_be assigned} | Add a new route to the Gateway |
DELETE /gateway/routes/{id} | Remove the route from Gateway |
POST /gateway/refresh | Remove all the cache entries |