[JAVA] Configure microservices with Spring Cloud (4): API Gateway

This is the 4th installment of the Spring Cloud series.

Overview

This time, I will set up API Gateway using "Spring Cloud Gateway".

services.png

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". krakend_gateway.pnt.PNG

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.

environment

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.

Work steps

In this article, we will proceed with the following steps.

  1. API Gateway template creation
  2. Implementation (addition of annotation and description of configuration file)
  3. Docker imaging and addition to docker-component

Step 1: Create API Gateway template

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

gateway.png

After that, you can download the skeleton gateway.zip by clicking GENERATE.

Step 2: Implementation (addition of annotation and description of configuration file)

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".

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).

Step 3: Docker imaging and addition to docker-component

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

at the end

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

Configure microservices with Spring Cloud (4): API Gateway
Oauth2 authentication with Spring Cloud Gateway
Microservices in Spring Cloud
Link API with Spring + Vue.js
Create microservices with Spring Boot
Let's write a proxy integrated Lambda function of Amazon API Gateway with Spring Cloud Function
Spring with Kotorin --4 REST API design
Google Cloud Platform with Spring Boot 2.0.0
Microservices With Docker and Cloud Performance
Send a request to the backend after authenticating with Spring Cloud Gateway
Configure Spring Boot application with maven multi module
Create a web api server with spring boot
Create Spring Cloud Config Server with security with Spring Boot 2.0
I created an api domain with Spring Framework. Part 2
Automatically map DTOs to entities with Spring Boot API
[Spring Boot] Get user information with Rest API (beginner)
Implement a simple Rest API with Spring Security with Spring Boot 2.0
Customize REST API error response with Spring Boot (Part 2)
I created an api domain with Spring Framework. Part 1
Customize REST API error response with Spring Boot (Part 1)
Compatible with Android 10 (API 29)
Spring with Kotorin --- 5. Actuator
API Gateway ↔ Lambda ↔ Dynamo
Self-made Validation with Spring
Spring with Kotorin ―― 1. SPRING INITIALIZR
Download with Spring Boot
Search AWS S3 resources with Spring Cloud AWS Resource Handling feature
Handle Java 8 date and time API with Thymeleaf with Spring Boot
Implement REST API with Spring Boot and JPA (Application Layer)
Implement REST API with Spring Boot and JPA (Infrastructure layer)
Let's make a simple API with EC2 + RDS + Spring boot ①
Create a SlackBot with AWS lambda & API Gateway in Java
Try hitting the zip code search API with Spring Boot
Implement REST API with Spring Boot and JPA (domain layer)
Oauth2 authentication with Spring Cloud Gateway
Configure microservices with Spring Cloud (4): API Gateway
Let's write a proxy integrated Lambda function of Amazon API Gateway with Spring Cloud Function
Microservices in Spring Cloud
Spring Cloud Stream demo released
Implement a simple Rest API with Spring Security & JWT with Spring Boot 2.0