Spring Cloud Gateway Tutorial
Previously I got one job said that we need build one portal gateway. So... what is portal gateway? let's just make it as API Gateway, still confirming with manager.
Alright, let's say if that is API Gateway, what should I do.
First of all, I tried to google what is API Gateway, then I got blow choices:
- Zuul -> Developed by java, as a java developer, it's easier for me to do secondary development as I'm a Java developer.
- Kong -> Based on Nginx + Lua, high performance, stable.
- Traefik -> Developed by Go, light framework.
- Zuul2 -> Developed by java same as Zuul
- Spring Cloud Gateway -> Developed by Java.
...
Let's compare these API Gateways. Kong is a high performance and stable framework, however it only supports Http, and it's a little hard to develop as it is developed by Lua.
Zuul: performance is not as good as nginx, and it can not be configured dynamically ( well, Zuul2 fixed this, however the performance of Zuul2 is only 20% better then Zuul which said by their dev team( not confirmed))
Traefik: ...........leave it, I have no idea about go language right now.
Spring cloud gateway: almost same as Zuul and Zuul2, performance is better.
Let's copy something from spring.io
1) Built on Spring Framework 5, Project Reactor and Spring Boot 2.0
2) Able to match routes on any request attribute.
3) Predicates and filters are specific to routes.
4) Hystrix Circuit Breaker integration.
5) Spring Cloud DiscoveryClient integration.
6) Easy to write Predicates and Filters
7) Request Rate Limiting
8) Path rewriting
OK.... let's start coding. Oops, sorry, let's start downloading codes.
Then Demo is very simple.
let's see the pom.xml, Dependencies including spring-cloud-starter, spring-cloud-starter-netflix-hystrix, spring-cloud-starter-contract-stub-runner and spring-boot-starter-test
<?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>org.springframework</groupId>
<artifactId>gs-gateway</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
and then the Application class.
package gateway;
import reactor.core.publisher.Mono;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// tag::code[]
@SpringBootApplication
@EnableConfigurationProperties(UriConfiguration.class)
@RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// tag::route-locator[]
@Bean
public RouteLocatormyRoutes(RouteLocatorBuilder builder, UriConfiguration uriConfiguration) {
String httpUri = uriConfiguration.getHttpbin();
return builder.routes()
.route(p -> p
.path("/get")
.filters(f -> f.addRequestHeader("Hello", "World"))
.uri(httpUri))
.route(p -> p
.host("*.hystrix.com")
.filters(f -> f
.hystrix(config -> config
.setName("mycmd")
.setFallbackUri("forward:/fallback")))
.uri(httpUri))
.build();
}
// end::route-locator[]
// tag::fallback[]
@RequestMapping("/fallback")
public Monofallback() {
return Mono.just("fallback");
}
// end::fallback[]
}
// tag::uri-configuration[]
@ConfigurationProperties
class UriConfiguration {
private Stringhttpbin ="http://httpbin.org:80";
public StringgetHttpbin() {
return httpbin;
}
public void setHttpbin(String httpbin) {
this.httpbin = httpbin;
}
}
// end::uri-configuration[]
// end::code[]
if you run this application and ping http://localhost:9999/get , then you will get below results
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Cache-Control": "no-cache",
"Forwarded": "proto=http;host=\"localhost:9999\";for=\"0:0:0:0:0:0:0:1:57517\"",
"Hello": "World",
"Host": "httpbin.org",
"Postman-Token": "852dfbb1-5bae-4cac-9fb5-40305a894932",
"User-Agent": "PostmanRuntime/7.3.0",
"X-Forwarded-Host": "localhost:9999"
},
"origin": "0:0:0:0:0:0:0:1, 183.195.135.250, ::1",
"url": "https://localhost:9999/get"
}
it's means api gateway is already working.
Will keep updating this document in the future...