This is the 4th installment of the Spring Cloud series.
This time, I will set up API Gateway using "Spring Cloud Gateway".
Traditionally, "Zuul" was used in the Spring Clound family, but Zuul is now in maintenance mode, "WebFlux & Netty based" and "Spring Gloud Gateway". Is an alternative product.
API Gateway acts as a reverse proxy built before the API. The role of API Gateway is to get between the client and the API and handle the concerns that you don't want to bring to the API side.
The figure below is borrowed from the documentation for another product for API Gateway, "KrakenD".
Typical examples are filtering, input / output return, API aggregation, log and statistical information acquisition, authentication (unlocking SSL, checking and adding tokens), and Throtting (is flow control okay?). ..
Personally, I attach great importance to two things, and I'm looking forward to Spring Cloud Gateway, which is based on Spirng.
It is assumed that the following works.
Since it is a continuation of Posts up to the last time, prepare the source of the previous goal point at hand and use it as a base.
In this article, we will proceed with the following steps.
This is where Spring Initializr comes into play.
Specify only ** Artifact ** and ** Name ** in gateway
, and the rest
Add Gateway
and ʻEureka Client,
Spring Cloud LoadBalancer, and
SpringBoot Actuator` to ** Dependencies **.
Actuator is not required for Gateway, but I will add it because it is necessary.
Dependencies | Description |
---|---|
Gateway | Added to deploy Spring Cloud Gateway |
Eureka Discovery Client | Added to get a list of services from Eureka |
Spring Cloud Loadbalancer | Added client-side load balancing library |
Spring Boot Actuator | Added to refer to Spring Boot internal information |
After that, you can download the skeleton gateway.zip by clicking GENERATE
.
I don't have much to do this time either. Only two.
First one. Annotate the Application class. You can now browse Service Discovery.
gateway/src/main/java/com/example/gateway/GatewayApplication.java
package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; //★ Add
@SpringBootApplication
@EnableDiscoveryClient //★ Add
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
The second thing to do. Write the configuration file "application.yml".
src / main / resources / application.properties
as it is no longer needed.gateway/src/main/resources/application.yml
server:
port: ${PORT:5000}
spring:
main:
banner-mode: "off"
application:
name: gateway
cloud:
gateway:
routes:
- id: account
uri: lb://ACCOUNT-API
predicates:
- Path=/api/**
filters:
- RewritePath=/api(?<segment>/?.*), $\{segment}
loadbalancer:
ribbon:
enabled: false
management:
endpoints:
web:
exposure:
include: "*"
eureka:
instance:
prefer-ip-address: false
client:
registerWithEureka: false
serviceUrl:
defaultZone: ${DISCOVERY:http://localhost:8761/eureka}
The Routes
section is the definition of routing.
This time, only one Route is defined, and the following is specified.
Also, for ʻeureka.client.serviceUrl.defaultZone`, specify the URL of Service Discovery (Eureka server).
Let's create a Docker image so that it can be manipulated with docker-compose.
Place the gateway
directory in the previous directory structure as shown below.
After that, create a Dockerfile and add it to docker-compose.yml.
spring-msa
├── account
│ └── ・ ・ ・
├── db
│ └── init
├── docker-compose.yml <--★ Add
├── gateyway <--★ Place
│ └── Dockerfile <--★ Create
└── sd
└── ・ ・ ・
discovery/Dockerfile
FROM openjdk:11-jdk-slim
ADD target/gateway-*.jar /gateway.jar
ENV CONTAINER_NAME=localhost \
PORT=5000 \
OPTS_ARGS=''
ENTRYPOINT ["java", "-jar", "/gateway.jar", "${OPTS_ARGS}"]
docker-compose.yml
version: '3'
・ ・ ・
services:
db:
・ ・ ・
adminer:
・ ・ ・
gateway:
image: spring-msa/gateway
container_name: gw
build:
context: ./gateway
dockerfile: Dockerfile
environment:
- CONTAINER_NAME=gw
- PORT=5000
- DISCOVERY=http://sd:3001/eureka/,http://sd2:3002/eureka/
ports:
- "5000:5000"
sd:
・ ・ ・
account:
・ ・ ・
Now you are ready. After creating the JAR with mvn wrapper, create a Docker image.
$ cd discovery
$ .mvnw clean package
$ cd ..
$ docker-compose build gw
Now you can start / stop gw with docker-compose.
(Start all services)
$ docker-compose up -d
(GW stop)
$ docker-compose stop gw
(Stop and destroy all services)
$ docker-compose down
(Stop all services and destroy including Volume)
$ docker-compose down -v
Since we are binding 5000 ports on the container to 5000 ports on the host, You can access it at http: // localhost: 5000 / api / info.
If you call / api / info repeatedly as shown below, use the list of service instances returned by Service Discovery. You can see that the called ACCOUNT-API is load-balanced. Since the default algorithm of the built-in load balancer is Round Robin, the request destinations are assigned in order.
$ curl localhost:5000/api/info
{"containerName":"account","port":"9001","hostAddress":"172.18.0.9","hostName":"c1f0f98a3859"}
$ curl localhost:5000/api/info
{"containerName":"account2","port":"9002","hostAddress":"172.18.0.7","hostName":"27d40318d8bc"}
$ curl localhost:5000/api/info
{"containerName":"account3","port":"9003","hostAddress":"172.18.0.8","hostName":"7c2abf523dcf"}
$ curl localhost:5000/api/info
{"containerName":"account","port":"9001","hostAddress":"172.18.0.9","hostName":"c1f0f98a3859"}
$ curl localhost:5000/api/info
{"containerName":"account2","port":"9002","hostAddress":"172.18.0.7","hostName":"27d40318d8bc"}
$ curl localhost:5000/api/info
{"containerName":"account3","port":"9003","hostAddress":"172.18.0.8","hostName":"7c2abf523dcf"}
If something goes wrong, look at the docker log.
$ docker-compose logs -f gw
The source so far is placed below.
https://github.com/SHIRAKI-Takayoshi/spring-msa/tree/add_gateway
At this point, the foundation is finally being laid.
What I would like to try from now on is to try adding features to API Gateway. I would like to customize the load balancing algorithm and add access flow control so as not to overload the API.
When it comes to Before that, we need to prepare a little more.
I would like to be able to apply a load with a load test tool while being able to trace access and monitor containers / services.
From the next time, I would like to move forward in that area.
See you soon.
Recommended Posts