API Gateways: Whats and Hows with implementation

Lovepreet Singh
7 min readApr 17, 2024

--

Photo by Walkator on Unsplash

✅ When we deal with micro services architecture, we often end up building some number of services and those services we run on different ports. Because we can’t use the same port multiple times in the same machine 🥲

So, When your app/website calls any service it will hit the IP address of that machine in which your service is running and will fetch the info 🥱

Let’s see an example

In this case our app wants to check if

  • user is authenticated or logged in properly (using auth micro-service)
  • then it tries to fetch the user details like name, profile pic etc (from the user service)
  • and then it checks the payment status of the user.

So, to do this app needs to call different API endpoints with base url let’s say 13.127.80.110:9019/authService/checkUserAuth?userId=abna1-ak411

and similarly for user service and payment service the base url will remain same (IP_address:port/api_end_point)

  • where IP_address will be the public IP of the machine in which our service’s docker containers are running
  • and port is the port exposed by that docker container
  • and api_end_point is the endpoint specific to different services.

🚀 Isn’t this tiresome, there should be some easy way. Isn’t it

Here is where our saviour comes into the picture

API GATEWAYS, wohooo 🎉

API gateways in simple terms are nothing but a gate that is a centralized place for all the clients to make any request to any of the service. So, clients don’t have to change the baseUrl everytime (port) or url mapping can be done inside this API Gateway only.

At the End, API gateway is itself a program (service) that will run in a machine (or managed by any cloud provider like AWS).

🚀 Before moving to API gateways functionalities and implementing it, let’s see a real world scenario that How exactly things travel….

  • Let’s say a client makes a request to https://singhdevhub.com and this request needs to have some IP address to travel to the right server
  • So, request goes to DNS first and in case of static files response directly comes from the CDN itself (CDN stands for content delivery network and it can serve static files effectively like images, HTML, CSS etc)
  • But if it is not a static file for which the request is, then it travels to the API gateway. Now this API gateway could be self managed like we showed a docker container running inside our virtual machine earlier or a managed service by any cloud provider like AWS, GCP etc
  • Now, API gateway has some functionality (that we’ll see further) and it redirects the request and sends the response.

😎 Now, Let’s say what API Gateway can do

API Traffic Management

API gateway routes incoming requests to different services depending on the request path, query params and headers. It also allows proper distribution of the load between target endpoints.

Protocol Translation

It can translate protocol easily like from HTTPS to HTTP. When app is requesting our gateway it should use secure protocoal like HTTPS and our internal services which are not exposed to the outer world could be requested with HTTP only

Caching and Load balancing

In API Gateway itself, one can use its caching which is to cache the most accessed response and as stated before api gateway is responsible for load balancing too if one wanted.

API security and Prevention from DDOS attacks

API Gateways are more secure as compared to exposing all service’s apis to the outer world (from our machine point of view) as it can carry authentication validations and also it can limit the requests from a source which prevents any kind of DDOS attacks. DDOS attack stands Distributed Denial of Service, which means sending so many requests or overloading a server until it becomes unhealthy.

📌 Implementing Kong as an API Gateway for our Auth and User Service

Kong documentation can be found at:- Kong’s official site

We have implemented few services in Spring boot which are Auth service and User service. You can clone the master branches if interested to deploy them in docker containers as:-

AuthService, UserService

What we want to do (refer to the above fig):-

  • We want to run docker containers of our auth-service and user-service and setup their APIs in kong.
  • So that whenever someone calls kong (our API gateway) then kong can call user/auth service internally.
  • Note:- 9810:9810 is the port mapping, which means 9810 is the port to use in a docker network to be used by other containers and 9810 is exposed for the outer world too who wants to request this container
  • In other words it means:- (outerWorldPort:dockerNetworkPort)
  • Note:- every container like auth, user-service and kong service they by default will run under docker network like bridge network that you can see using docker network ls Containers can communicate with each other using container’s IP if they are in the same docker network (either default or a custom network made by you)

✨ Now, to spin up the containers we make a docker compose file which is nothing but a config file telling docker how to spin up the container.

  • Making a docker compose file named “expensetrackerapp.yml”
version: '3'

services:
zookeeper:
image: confluentinc/cp-zookeeper:7.4.4
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ports:
- 2181:2181

kafka:
image: confluentinc/cp-kafka:7.4.4
depends_on:
- zookeeper
ports:
- 9092:9092
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://13.127.99.104:9092
KAFKA_LISTENERS: PLAINTEXT://:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

mysql:
image: mysql:8.3.0
container_name: mysql-8.3.0
restart: always
environment:
MYSQL_USER: test
MYSQL_ROOT_USER: root
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- '3306:3306'
expose:
- '3306'
volumes:
- mysql-db:/var/lib/mysql

user-service:
image: user-service
container_name: user-service
ports:
- '9810:9810'
depends_on:
- kafka
- mysql

auth-service:
image: auth-service
container_name: auth-service
ports:
- '9898:9898'
depends_on:
- kafka
- mysql

volumes:
mysql-db:
driver: local

📍 As, our services require kafka, zookeeper and mysql so that should start first, hence `depends_on` is mentioned. Images like “ image: user-service” & “ image: user-service” are built using jars (refer to the optional section below to see how to make docker images from jars).

— — — — — — — —

# [Optional] How to make a Docker Image of a spring boot application

  • Run ./gradlew clean buildwhich will build a jar in build/libs/xyz.jar that you can move to your Virtual machine (VPS) and using that jar (assuming name of the jar is xyz.jar) you can make an image
  • to copy from your local machine to your virtual machine you can use command like
scp -i ~/.ssh/aws_lightsail.cer /Users/lovepreetsingh/Desktop/ExpenseTracker/AuthService/app/build/libs/app.jar  ubuntu@13.127.99.104:~/
  • now ssh into your VM, and make a dockerfile like
FROM amazoncorretto:21-alpine-jdk
MAINTAINER SinghDevHub
COPY app.jar auth-service.jar
ENTRYPOINT ["java", "-jar", "/auth-service.jar"]
  • It will make an image of name auth-service

— — — — — — — —

Now, to make a kong config we can make folder like

docker
|
|
---> config
| |
| |
| ---> kong-config.yml
|
|
---> kong-compose.yml
  • kong-config.yml
_format_version: "2.1"

services:
- name: auth-service
url: http://172.20.0.5:9898
routes:
- name: sign-up
paths:
- /auth/v1/signup

- name: user-service
url: http://172.20.0.6:9810
routes:
- name: get-user
paths:
- /user/v1/getUser
  • kong-compose.yml
version: '3.3'

services:
kong:
image: kong
volumes:
- "./config:/usr/local/kong/declarative"
environment:
KONG_DATABASE: off
KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong-config.yml
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
KONG_LOG_LEVEL: debug
KONG_PLUGINS: bundled
ports:
- "8005:8000/tcp"
- "127.0.0.1:7990:8001/tcp"
- "8443:8443/tcp"
- "127.0.0.1:8444:8444/tcp"

Process to start docker containers and use kong:-

  • start services using docker compose -f expensetrackerapp.yml up -d
  • now start kong using docker compose -f kong-compose.yml up -d
  • Note:- in kong-config.yml ips of user-service and auth service (say http://172.20.0.5) are found using docker inspect <container-id> | grep IPAddress
  • Now to hit an API you have to hit your_vm_ip:kong_port/rest_api_path
  • for ex:
curl --location --request GET 'https://13.127.99.104:8443/user/v1/getUser' \
--header 'Content-Type: application/json' \
--header 'Cookie: JSESSIONID=32ABCDEF406GHIJKLE9C78C65EDB67' \
--data-raw '{
"user_id":"6034a397-e502-4997-a7a4-0d1ddbd68a25",
"username": "lovepreetsingh",
"password": "sinagh#1123",
"first_name": "lovepreet",
"phone_number": 1112233455,
"last_name": "singh",
"email": "abc@gmail.com"
}'

Here, you go. For more you can refer to our Youtube channel:- Link (Language:- Hindi 🇮🇳)

THANKS, Give a clap, and follow for more……

--

--