๐Ÿ”ฅ โš”๏ธ Build Dynamic Load Balancer

2023-10-28

แƒจแƒ”แƒกแƒแƒ•แƒแƒšแƒ˜

แƒ’แƒแƒ›แƒแƒ แƒฏแƒแƒ‘แƒ, แƒ”แƒก แƒแƒ แƒ˜แƒก แƒฉแƒ”แƒ›แƒ˜ แƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ˜ แƒกแƒขแƒแƒขแƒ˜แƒ แƒฅแƒแƒ แƒ—แƒฃแƒš แƒ”แƒœแƒแƒ–แƒ” แƒ“แƒ แƒ แƒแƒ’แƒแƒ แƒช แƒกแƒแƒ—แƒแƒฃแƒ แƒ˜แƒ“แƒแƒœ แƒฉแƒแƒœแƒก, แƒแƒ› แƒกแƒขแƒแƒขแƒ˜แƒแƒจแƒ˜ แƒ›แƒ˜แƒœแƒ“แƒ แƒ•แƒ˜แƒกแƒแƒฃแƒ‘แƒ แƒ dynamic load balancer-แƒ–แƒ” แƒ“แƒ แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ”แƒ แƒ—แƒแƒ“ แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— nodejs-แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—.

Dynamic horizontal Scaling

แƒ”แƒ แƒ—-แƒ”แƒ แƒ—แƒ˜ แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ•แƒแƒœแƒ˜ แƒฃแƒžแƒ˜แƒ แƒแƒขแƒ”แƒกแƒแƒ‘แƒ, แƒ แƒแƒช แƒฅแƒšแƒแƒฃแƒ“แƒ–แƒ” แƒ“แƒแƒคแƒฃแƒซแƒœแƒ”แƒ‘แƒฃแƒš แƒ˜แƒœแƒคแƒ แƒแƒกแƒขแƒ แƒฃแƒฅแƒขแƒฃแƒ แƒแƒก แƒแƒฅแƒ•แƒก แƒแƒ แƒ˜แƒก แƒ˜แƒก แƒ แƒแƒ›, แƒ›แƒแƒ— แƒจแƒ”แƒฃแƒซแƒšแƒ˜แƒแƒ— แƒ“แƒ˜แƒœแƒแƒ›แƒ˜แƒฃแƒ แƒแƒ“ แƒ’แƒแƒ›แƒแƒฃแƒงแƒแƒœ แƒ แƒแƒ›แƒฎแƒ”แƒšแƒ แƒ แƒ”แƒกแƒฃแƒ แƒกแƒ˜แƒช แƒกแƒญแƒ แƒ˜แƒ“แƒ”แƒ‘แƒ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒแƒก, แƒ˜แƒ›แƒ˜แƒก แƒ›แƒ˜แƒฎแƒ”แƒ“แƒ•แƒ˜แƒ— แƒ—แƒฃ แƒ แƒ แƒขแƒ แƒ”แƒคแƒ˜แƒ™แƒ˜ แƒ›แƒแƒ“แƒ˜แƒก แƒ›แƒแƒกแƒ–แƒ”. Dynamic scaling-แƒ˜แƒ—แƒแƒช แƒแƒ แƒ˜แƒก แƒชแƒœแƒแƒ‘แƒ˜แƒšแƒ˜ แƒ”แƒก แƒกแƒแƒ™แƒ˜แƒ—แƒฎแƒ˜. แƒ—แƒฃ แƒกแƒฌแƒแƒ แƒแƒ“ แƒ“แƒแƒ•แƒแƒ˜แƒ›แƒžแƒšแƒ”แƒ›แƒ”แƒœแƒขแƒ˜แƒ แƒ”แƒ‘แƒ—, แƒแƒ› แƒ›แƒ˜แƒ“แƒ’แƒแƒ›แƒแƒ› แƒจแƒ”แƒกแƒแƒซแƒšแƒแƒ แƒกแƒแƒ’แƒ แƒซแƒœแƒแƒ‘แƒšแƒแƒ“ แƒจแƒ”แƒแƒ›แƒชแƒ˜แƒ แƒแƒก IT แƒ˜แƒœแƒคแƒ แƒแƒกแƒขแƒ แƒฃแƒฅแƒขแƒฃแƒ แƒ˜แƒก แƒคแƒแƒกแƒ˜, แƒ˜แƒกแƒ” แƒ แƒแƒ› แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ แƒ˜แƒกแƒ”แƒ• highly available - แƒ›แƒแƒฆแƒแƒš แƒฎแƒ”แƒšแƒ›แƒ˜แƒกแƒฌแƒแƒ•แƒ“แƒแƒ›แƒ˜ แƒ“แƒแƒ แƒฉแƒ”แƒก.

Idea

แƒ˜แƒ“แƒ”แƒ แƒแƒ แƒ˜แƒก แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜: แƒ—แƒฃ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒแƒก แƒแƒฅแƒ•แƒก แƒžแƒ”แƒ แƒคแƒแƒ แƒ›แƒแƒœแƒกแƒ˜แƒก แƒ•แƒแƒ แƒ“แƒœแƒ แƒ›แƒแƒฆแƒแƒšแƒ˜ แƒขแƒ แƒ”แƒคแƒ˜แƒ™แƒ˜แƒก แƒ’แƒแƒ›แƒ, แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ แƒแƒ•แƒขแƒแƒ›แƒแƒขแƒฃแƒ แƒแƒ“ แƒแƒ›แƒ แƒแƒ•แƒšแƒ”แƒ‘แƒก แƒ›แƒ˜แƒก แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒขแƒ”แƒ‘แƒก แƒแƒฎแƒแƒš แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ”, แƒ แƒแƒ› แƒ’แƒแƒฃแƒ›แƒ™แƒšแƒแƒ•แƒ“แƒ”แƒก แƒ“แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒแƒก. แƒแƒœแƒแƒšแƒแƒ’แƒ˜แƒฃแƒ แƒแƒ“, แƒ—แƒฃ แƒ’แƒแƒ›แƒแƒงแƒแƒคแƒ˜แƒšแƒ˜ แƒ แƒ”แƒกแƒฃแƒ แƒกแƒ”แƒ‘แƒ˜ แƒ•แƒ”แƒ  แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ, แƒ–แƒ”แƒ“แƒ›แƒ”แƒขแƒ˜แƒ, แƒ›แƒแƒจแƒ˜แƒœ แƒฃแƒœแƒ“แƒ แƒ’แƒแƒ›แƒแƒ•แƒ แƒ—แƒแƒ— แƒ–แƒแƒ’แƒ˜แƒ”แƒ แƒ—แƒ˜ แƒ›แƒแƒ—แƒ’แƒแƒœแƒ˜, แƒ แƒแƒ› แƒจแƒ”แƒ•แƒแƒ›แƒชแƒ˜แƒ แƒแƒ— แƒฎแƒแƒ แƒฏแƒ˜.

แƒ”แƒก แƒกแƒ™แƒแƒšแƒ˜แƒ แƒ”แƒ‘แƒ แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ’แƒ•แƒฅแƒแƒœแƒ“แƒ”แƒก แƒ“แƒแƒจแƒ”แƒ“แƒฃแƒšแƒ”แƒ‘แƒฃแƒšแƒ˜, แƒ แƒแƒช แƒ˜แƒ›แƒแƒก แƒœแƒ˜แƒจแƒœแƒแƒ•แƒก, แƒ แƒแƒ› แƒ แƒแƒฆแƒแƒช แƒกแƒแƒแƒ—แƒ”แƒ‘แƒจแƒ˜ แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ’แƒแƒ›แƒแƒ•แƒ แƒ—แƒแƒ— แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒฆแƒแƒช แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ˜, แƒ แƒแƒ“แƒ’แƒแƒœ แƒ•แƒ˜แƒชแƒ˜แƒ— แƒ แƒแƒ› แƒแƒ› แƒžแƒ”แƒ แƒ˜แƒแƒ“แƒจแƒ˜ แƒ“แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ แƒซแƒแƒšแƒ˜แƒแƒœ แƒ˜แƒ™แƒšแƒ”แƒ‘แƒก แƒ“แƒ แƒ“แƒแƒ•แƒแƒ แƒ”แƒกแƒขแƒแƒ แƒขแƒแƒ— แƒ แƒแƒ’แƒแƒ แƒช แƒ™แƒ˜ แƒ“แƒแƒ˜แƒฌแƒงแƒ”แƒ‘แƒ แƒ˜แƒก แƒกแƒแƒแƒ—แƒ”แƒ‘แƒ˜, แƒ แƒแƒชแƒ แƒ“แƒแƒฌแƒแƒšแƒ แƒ›แƒแƒฆแƒแƒšแƒ˜แƒ.

Service Registry

แƒ–แƒแƒ’แƒแƒ“แƒ˜ แƒžแƒแƒขแƒ”แƒ แƒœแƒ˜, แƒ แƒแƒ› แƒ”แƒก แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ แƒ’แƒแƒ“แƒแƒ•แƒญแƒ แƒแƒ— แƒแƒ แƒ˜แƒก, แƒ แƒแƒ› แƒ’แƒแƒ›แƒแƒ•แƒ˜แƒงแƒ”แƒœแƒแƒ— แƒชแƒ”แƒœแƒขแƒ แƒแƒšแƒฃแƒ แƒ˜ แƒ แƒ”แƒžแƒแƒ–แƒ˜แƒขแƒแƒ แƒ˜ - service registry, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒจแƒ”แƒ˜แƒœแƒแƒฎแƒแƒ•แƒก แƒ“แƒ แƒ“แƒแƒขแƒ แƒ”แƒ™แƒแƒ•แƒก, แƒ แƒแƒ›แƒ”แƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ˜แƒ แƒ’แƒแƒจแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ“แƒ แƒ แƒแƒ›แƒ”แƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ˜ แƒแƒ› แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ”.

Functional Programming Paradigm

แƒ แƒแƒ’แƒแƒ แƒช แƒ“แƒ˜แƒแƒ’แƒ แƒแƒ›แƒ˜แƒ“แƒแƒœ แƒฉแƒแƒœแƒก, แƒ แƒแƒชแƒ แƒ แƒ”แƒฅแƒ•แƒ”แƒฅแƒกแƒขแƒ˜ แƒ›แƒ˜แƒ•แƒ example.com-แƒ–แƒ”, แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜ แƒแƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒก แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜แƒก แƒžแƒ แƒ”แƒคแƒ˜แƒฅแƒกแƒก, แƒ—แƒฃ แƒ˜แƒฌแƒงแƒ”แƒ‘แƒ /api-แƒ˜แƒ— แƒ”แƒกแƒ˜แƒ’แƒ˜ แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒฃแƒœแƒ“แƒ แƒ“แƒแƒ‘แƒแƒšแƒแƒœแƒกแƒ“แƒ”แƒก API service แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ”แƒ‘แƒ–แƒ”, แƒ แƒแƒ’แƒแƒ แƒช แƒ•แƒฎแƒ”แƒ“แƒแƒ•แƒ— แƒกแƒฃแƒš API-แƒกแƒ—แƒ•แƒ˜แƒก แƒ’แƒ•แƒแƒฅแƒ•แƒก แƒแƒ แƒ˜ แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ˜, แƒแƒ แƒ’แƒแƒœ แƒ’แƒ•แƒแƒฅแƒ•แƒก แƒ’แƒแƒจแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ”แƒก แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜, api1-แƒ–แƒ” แƒ“แƒ api2-แƒ–แƒ”.

Implementing a dynamic load balancer with http-proxy and Consul

แƒกแƒ”แƒ แƒ•แƒ˜แƒก แƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒแƒขแƒแƒ แƒแƒ“ แƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘ Consul-แƒก, แƒแƒฅ แƒ›แƒ”แƒขแƒก แƒแƒฆแƒแƒ  แƒจแƒ”แƒ•แƒแƒš แƒ“แƒ”แƒขแƒแƒšแƒ”แƒ‘แƒจแƒ˜, แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒœแƒแƒฎแƒแƒ— แƒ“แƒแƒ™แƒฃแƒ›แƒ”แƒœแƒขแƒแƒชแƒ˜แƒ. แƒ™แƒแƒœแƒกแƒฃแƒšแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ—แƒแƒ•แƒแƒ แƒ˜ แƒแƒ–แƒ แƒ˜แƒ, แƒ แƒแƒ› แƒ’แƒแƒ•แƒ˜แƒ›แƒ”แƒแƒ แƒแƒ— แƒ˜แƒก แƒ›แƒฃแƒšแƒขแƒ˜แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒฃแƒšแƒ˜ แƒแƒ แƒฅแƒ˜แƒขแƒ”แƒฅแƒขแƒฃแƒ แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ–แƒ”แƒ›แƒแƒ— แƒแƒฆแƒฌแƒ”แƒ แƒ˜แƒš แƒ“แƒ˜แƒแƒ’แƒ แƒแƒ›แƒแƒ–แƒ”แƒ. แƒกแƒฃแƒš แƒ’แƒแƒ›แƒแƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘ 3 แƒ‘แƒ˜แƒ‘แƒšแƒ˜แƒแƒ—แƒ”แƒ™แƒแƒก:

แƒ‘แƒ˜แƒ‘แƒšแƒ˜แƒแƒ—แƒ”แƒ™แƒ”แƒ‘แƒ˜, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒกแƒแƒช แƒ’แƒแƒ›แƒแƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘
http-proxy - แƒ’แƒแƒ•แƒแƒ›แƒแƒ แƒขแƒ˜แƒ•แƒแƒ— reverse-proxy/load-balancer-แƒ˜แƒก แƒจแƒ”แƒฅแƒ›แƒœแƒ แƒœแƒแƒฃแƒ“แƒ–แƒ”
portfinder: แƒแƒ›แƒแƒก แƒแƒฎแƒกแƒœแƒ แƒแƒ  แƒฃแƒœแƒ“แƒ,แƒกแƒแƒฎแƒ”แƒšแƒ˜ แƒ’แƒ•แƒ”แƒฃแƒ‘แƒœแƒ”แƒ‘แƒ
consul: แƒ˜แƒœแƒขแƒ”แƒ แƒแƒฅแƒชแƒ˜แƒ แƒ แƒแƒ› แƒ’แƒ•แƒฅแƒแƒœแƒ“แƒ”แƒก Consul-แƒ—แƒแƒœ

แƒ›แƒแƒ“แƒ˜ แƒ’แƒแƒ“แƒแƒ•แƒ˜แƒ“แƒ”แƒ— แƒ˜แƒ›แƒžแƒšแƒ”แƒ›แƒ”แƒœแƒขแƒแƒชแƒ˜แƒ˜แƒก แƒœแƒแƒฌแƒ˜แƒšแƒ–แƒ” แƒฃแƒจแƒฃแƒแƒšแƒแƒ“.

Setting up the Service For Registration

แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒก แƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒแƒขแƒแƒ แƒ˜, แƒแƒ› แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒกแƒแƒฎแƒ”แƒšแƒก แƒ›แƒ˜แƒ•แƒ˜แƒฆแƒ”แƒ‘แƒ— command-line-แƒ“แƒแƒœ. แƒ›แƒแƒ“แƒ˜ แƒ“แƒแƒ•แƒ˜แƒฌแƒงแƒแƒ— แƒ“แƒ แƒ—แƒแƒœ แƒแƒ•แƒฎแƒกแƒœแƒแƒ—.

app.js
import { createServer } from 'http';
import Consul from 'consul';
import portfinder from 'portfinder';
import { nanoid } from 'nanoid';
 
 
// แƒ“แƒแƒ•แƒ˜แƒญแƒ˜แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒขแƒ˜แƒžแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒ”แƒ‘แƒ—
const serviceType = process.argv[2];
 
const { pid } = process;
 

แƒแƒฎแƒšแƒ แƒ’แƒ•แƒ˜แƒœแƒ“แƒ, แƒ แƒแƒ› แƒ“แƒแƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜, แƒ แƒแƒ›แƒšแƒ˜แƒก แƒขแƒ˜แƒžแƒ˜ แƒ•แƒ˜แƒชแƒ˜แƒ—(แƒกแƒแƒฎแƒ”แƒšแƒ˜แƒช แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ แƒ•แƒ—แƒฅแƒ•แƒแƒ—), แƒ’แƒ•แƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ แƒฃแƒ™แƒ•แƒ” แƒ˜แƒœแƒ˜แƒชแƒ˜แƒแƒšแƒ˜แƒ–แƒแƒชแƒ˜แƒ แƒ’แƒแƒ•แƒฃแƒ™แƒ”แƒ—แƒแƒ— แƒ™แƒแƒœแƒกแƒฃแƒšแƒก,แƒ’แƒแƒ•แƒแƒขแƒแƒœแƒแƒ— แƒฃแƒœแƒ˜แƒ™แƒแƒšแƒฃแƒ แƒ˜ id, แƒกแƒแƒฎแƒ”แƒšแƒ˜ แƒแƒ› แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก, แƒ›แƒแƒ•แƒซแƒ”แƒ‘แƒœแƒแƒ— แƒ—แƒแƒ•แƒ˜แƒกแƒฃแƒคแƒแƒšแƒ˜ แƒžแƒแƒ แƒขแƒ˜ แƒ แƒแƒ›แƒ”แƒšแƒ–แƒ”แƒช แƒ’แƒ•แƒ˜แƒœแƒ“แƒ แƒฉแƒ•แƒ”แƒœแƒ˜ แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ˜ แƒ’แƒแƒ”แƒจแƒ•แƒแƒก, แƒ“แƒ แƒขแƒ”แƒ’แƒ”แƒ‘แƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒแƒ  แƒแƒ แƒ˜แƒก แƒแƒฃแƒชแƒ˜แƒšแƒ”แƒ‘แƒ”แƒšแƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ,แƒ›แƒแƒ’แƒ แƒแƒ› แƒฉแƒ•แƒ”แƒœ แƒขแƒ”แƒ’แƒ”แƒ‘แƒจแƒ˜ แƒ›แƒแƒ•แƒซแƒ”แƒ‘แƒœแƒ˜แƒ— แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ›แƒจแƒ˜ แƒฃแƒ™แƒ•แƒ” แƒกแƒแƒญแƒ˜แƒ แƒ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒก. แƒซแƒ˜แƒ แƒ˜แƒ—แƒแƒ“แƒแƒ“ แƒขแƒ”แƒ’แƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒ–แƒแƒœแƒ˜แƒ แƒ™แƒแƒขแƒ”แƒ’แƒแƒ แƒ˜แƒ–แƒแƒชแƒ˜แƒ แƒ’แƒแƒ แƒ™แƒ•แƒ”แƒฃแƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ˜แƒก, แƒ’แƒแƒคแƒ˜แƒšแƒขแƒ•แƒ แƒ แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ› แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒแƒ“ แƒ“แƒ แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ˜แƒ—แƒ˜ แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒ˜แƒก แƒ’แƒแƒขแƒแƒœแƒ, แƒ แƒ แƒ’แƒแƒ แƒ”แƒ›แƒแƒจแƒ˜แƒ แƒ’แƒแƒจแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ”แƒก แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ“แƒ แƒ.แƒจ. แƒแƒฆแƒแƒ  แƒฉแƒแƒ•แƒแƒš แƒกแƒ˜แƒฆแƒ แƒ›แƒ”แƒ”แƒ‘แƒจแƒ˜. แƒ”แƒกแƒ”แƒ˜แƒ’แƒ˜ แƒฉแƒ•แƒ”แƒœแƒก แƒ’แƒแƒกแƒแƒจแƒ•แƒ”แƒ‘ แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒก แƒ›แƒแƒ•แƒฃแƒซแƒ”แƒ‘แƒœแƒ”แƒ— แƒžแƒแƒ แƒขแƒ˜, แƒฎแƒแƒšแƒ แƒ™แƒแƒœแƒกแƒฃแƒšแƒก แƒ’แƒแƒ•แƒแƒแƒขแƒœแƒ”แƒ— แƒ›แƒ˜แƒกแƒ˜, แƒ แƒแƒ’แƒแƒ แƒช แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒกแƒแƒฎแƒ”แƒšแƒ˜, id, address, port,tags. แƒ›แƒแƒ“แƒ˜ แƒ’แƒแƒ•แƒแƒ’แƒ แƒซแƒ”แƒšแƒแƒ—...

app.js
import { createServer } from 'http';
import Consul from 'consul';
import portfinder from 'portfinder';
import { nanoid } from 'nanoid';
 
// แƒ“แƒแƒ•แƒ˜แƒญแƒ˜แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒขแƒ˜แƒžแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒ”แƒ‘แƒ—
const serviceType = process.argv[2];
 
const { pid } = process;
 
async function main() {
	const consulClient = new Consul();
 
	// โ‘  Discover a free port in the system and generate a unique service ID
	const port = await portfinder.getPortPromise();
	const address = process.env.ADDRESS || "localhost";
	const serviceId = nanoid();
	function registerService() {
		consulClient.agent.service.register(
			{
				id: serviceId,
				name: serviceType,
				address,
				port,
				tags: [serviceType],
			},
			() => {
				console.log(`${serviceType} registered successfully`);
			}
		);
	}
 

แƒ”แƒฎแƒšแƒ แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— แƒแƒ› แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒแƒ›แƒแƒฆแƒ”แƒ‘แƒ/แƒฌแƒแƒจแƒšแƒ แƒ™แƒแƒœแƒกแƒฃแƒšแƒ˜แƒก แƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ“แƒแƒœ.แƒ›แƒ—แƒแƒ•แƒแƒ แƒ˜ แƒ›แƒ˜แƒ–แƒแƒœแƒ˜ แƒแƒ› แƒคแƒฃแƒœแƒชแƒฅแƒ˜แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ˜แƒก,แƒ แƒแƒ› แƒ—แƒฃ แƒกแƒแƒญแƒ˜แƒ แƒ แƒ’แƒแƒฎแƒ“แƒ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ’แƒแƒ›แƒแƒ แƒ—แƒ•แƒ แƒแƒœ แƒ—แƒฃ แƒ”แƒ แƒแƒ แƒ˜ แƒ›แƒแƒฎแƒ“แƒ,แƒแƒœ แƒ แƒแƒ˜แƒ›แƒ” แƒ”แƒฅแƒกแƒ”แƒคแƒจแƒ”แƒœแƒ˜ แƒ’แƒแƒ˜แƒกแƒ แƒแƒšแƒ แƒฉแƒ•แƒ”แƒœแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒžแƒ แƒแƒชแƒ”แƒกแƒ›แƒ, แƒฃแƒœแƒ“แƒ แƒฌแƒแƒ˜แƒจแƒแƒšแƒแƒก แƒ”แƒก แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ™แƒแƒœแƒกแƒฃแƒšแƒ˜แƒ“แƒแƒœ แƒกแƒแƒœแƒแƒ› แƒ—แƒแƒ•แƒแƒ“ แƒžแƒ แƒแƒชแƒ”แƒกแƒ˜ แƒ›แƒแƒ™แƒ•แƒ“แƒ”แƒ‘แƒ.

app.js
import { createServer } from 'http';
import Consul from 'consul';
import portfinder from 'portfinder';
import { nanoid } from 'nanoid';
 
// แƒ“แƒแƒ•แƒ˜แƒญแƒ˜แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒขแƒ˜แƒžแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒ”แƒ‘แƒ—
const serviceType = process.argv[2];
 
const { pid } = process;
 
async function main() {
	const consulClient = new Consul();
 
	// โ‘  Discover a free port in the system and generate a unique service ID
	const port = await portfinder.getPortPromise();
	const address = process.env.ADDRESS || "localhost";
	const serviceId = nanoid();
	function registerService() {
		consulClient.agent.service.register(
			{
				id: serviceId,
				name: serviceType,
				address,
				port,
				tags: [serviceType],
			},
			() => {
				console.log(`${serviceType} registered successfully`);
			}
		);
	}
 
	function unregisterService(err) {
		err && console.error(err);
		onsole.log(`deregistering ${serviceId}`);
		consulClient.agent.service.deregister(serviceId, () => {
			process.exit(err ? 1 : 0);
		});
	}
 
 
	// แƒ“แƒแƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒแƒ—
	process.on("exit", unregisterService);
	process.on("uncaughtException", unregisterService);
	process.on("SIGINT", unregisterService);
 

แƒแƒฎแƒšแƒ แƒ™แƒ˜ แƒ‘แƒแƒšแƒ แƒ”แƒขแƒแƒžแƒ˜, แƒจแƒ”แƒ•แƒฅแƒ›แƒœแƒแƒ— HTTP แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ˜, แƒœแƒแƒฃแƒ“แƒ˜แƒก http แƒ›แƒแƒ“แƒฃแƒšแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—, แƒ“แƒแƒ•แƒกแƒ•แƒแƒ— แƒฉแƒ•แƒ”แƒœแƒก แƒžแƒแƒ แƒขแƒ–แƒ” แƒ“แƒ แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ–แƒ”, แƒ“แƒ แƒกแƒ˜แƒ›แƒฃแƒšแƒแƒชแƒ˜แƒ แƒ’แƒแƒ•แƒแƒ™แƒ”แƒ—แƒแƒ— แƒ—แƒ˜แƒ—แƒฅแƒแƒก แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ”แƒ‘แƒ˜ แƒจแƒ”แƒ›แƒแƒ“แƒ˜แƒก แƒแƒ› แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ–แƒ”.

app.js
import { createServer } from 'http';
import Consul from 'consul';
import portfinder from 'portfinder';
import { nanoid } from 'nanoid';
 
// แƒ“แƒแƒ•แƒ˜แƒญแƒ˜แƒ แƒแƒ— แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒขแƒ˜แƒžแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒ”แƒ‘แƒ—
const serviceType = process.argv[2];
 
const { pid } = process;
 
async function main() {
	const consulClient = new Consul();
 
	// โ‘  Discover a free port in the system and generate a unique service ID
	const port = await portfinder.getPortPromise();
	const address = process.env.ADDRESS || "localhost";
	const serviceId = nanoid();
	function registerService() {
		consulClient.agent.service.register(
			{
				id: serviceId,
				name: serviceType,
				address,
				port,
				tags: [serviceType],
			},
			() => {
				console.log(`${serviceType} registered successfully`);
			}
		);
	}
 
	function unregisterService(err) {
		err && console.error(err);
		onsole.log(`deregistering ${serviceId}`);
		consulClient.agent.service.deregister(serviceId, () => {
			process.exit(err ? 1 : 0);
		});
	}
 
 
	// แƒ“แƒแƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒแƒ— แƒ“แƒ”แƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒ”แƒ”แƒ‘แƒ˜แƒก แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ
	process.on("exit", unregisterService);
	process.on("uncaughtException", unregisterService);
	process.on("SIGINT", unregisterService);
 
 
	const server = createServer((req, res) => {
		let i = 1e7;
		while (i > 0) {
		  i--;
		}
		console.log(`Handling request from ${pid}`);
		res.end(`${serviceType} response from ${pid}\n`);
	});
 
	server.listen(port, address, () => {
		registerService();
		console.log(`Started ${serviceType} at ${pid} on port ${port}`);
	});

แƒ”แƒก แƒ˜แƒงแƒ แƒฉแƒ•แƒ”แƒœแƒ˜ แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ˜แƒก แƒ แƒแƒ’แƒแƒ แƒช แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒแƒชแƒ˜แƒแƒ แƒ“แƒ แƒ›แƒ˜แƒกแƒ˜ แƒ“แƒแƒฏแƒ”แƒœแƒ แƒ’แƒแƒ›แƒแƒงแƒแƒคแƒ˜แƒš แƒฃแƒœแƒ˜แƒ™แƒแƒšแƒฃแƒ  แƒžแƒแƒ แƒขแƒกแƒ แƒ“แƒ แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ–แƒ”.

แƒแƒฎแƒšแƒ, แƒ’แƒแƒ“แƒแƒ•แƒ˜แƒ“แƒ”แƒ— แƒ›แƒ”แƒแƒ แƒ” แƒœแƒแƒฌแƒ˜แƒšแƒ–แƒ”. แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒแƒ— แƒšแƒแƒแƒ“-แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒจแƒ”แƒ›แƒแƒ›แƒแƒ•แƒแƒš แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ”แƒ‘แƒก แƒ’แƒแƒ“แƒแƒแƒœแƒแƒฌแƒ˜แƒšแƒ”แƒ‘แƒก แƒกแƒฎแƒ•แƒแƒ“แƒแƒกแƒฎแƒฎแƒ•แƒ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ–แƒ”,แƒ˜แƒ›แƒ˜แƒก แƒ›แƒ˜แƒฎแƒ”แƒ“แƒ•แƒ˜แƒ— แƒ—แƒฃ แƒ แƒ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ แƒแƒฃแƒขแƒ˜แƒก แƒžแƒ แƒ”แƒคแƒ˜แƒฅแƒกแƒ˜.

Setting up the Load-Balancer

แƒžแƒ˜แƒ แƒ•แƒ”แƒš แƒ แƒ˜แƒ’แƒจแƒ˜, แƒ“แƒแƒ•แƒแƒ แƒ”แƒ’แƒ˜แƒกแƒขแƒ แƒ˜แƒ แƒแƒ— แƒ แƒแƒฃแƒขแƒ”แƒ‘แƒ˜, แƒแƒœแƒฃ แƒ แƒแƒ›แƒ”แƒš แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ–แƒ”, แƒ แƒแƒ›แƒ”แƒš แƒกแƒ”แƒ แƒ•แƒ˜แƒก แƒฃแƒœแƒ“แƒ แƒ›แƒ˜แƒ›แƒแƒ แƒ—แƒแƒก แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ›แƒ.

load-balancer.js
import { createServer } from 'http';
import httpProxy from 'http-proxy';
import Consul from 'consul';
 
 
// โ‘  แƒ’แƒแƒœแƒ•แƒกแƒแƒ–แƒ•แƒ แƒแƒ— แƒ แƒแƒฃแƒขแƒ”แƒ‘แƒ˜ แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก
const routing = [
	{
	  path: "/api", //แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒก แƒ“แƒแƒ˜แƒฌแƒงแƒ”แƒ‘แƒ /api แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜แƒ—, แƒ’แƒแƒ“แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ“แƒ”แƒ‘แƒ api-service-แƒ–แƒ”
	  service: "api-service",
	  index: 0,
	},
	{
	  path: "/", // แƒแƒ› แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜แƒ— แƒ“แƒแƒฌแƒงแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒ™แƒ˜ แƒ’แƒแƒ“แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ“แƒ”แƒ‘แƒ webapp-service-แƒ–แƒ”.
	  service: "webapp-service",
	  index: 0,
	},
];
 

แƒแƒฎแƒšแƒ แƒฃแƒ™แƒ•แƒ” แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ, แƒ™แƒแƒœแƒกแƒฃแƒšแƒ˜แƒก แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒ˜แƒก แƒ˜แƒœแƒ˜แƒชแƒ˜แƒแƒšแƒ˜แƒ–แƒ˜แƒ, แƒ แƒแƒ› แƒ›แƒ˜แƒ•แƒฌแƒ“แƒ”แƒ— แƒฉแƒ•แƒ”แƒœแƒ—แƒ•แƒ˜แƒก แƒกแƒแƒกแƒฃแƒ แƒ•แƒ”แƒš แƒกแƒ”แƒ แƒ•แƒ˜แƒก แƒ“แƒ httpProxy แƒ‘แƒ˜แƒ‘แƒšแƒ˜แƒแƒ—แƒ”แƒ™แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—, แƒ’แƒแƒ“แƒแƒ•แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒแƒ— แƒจแƒ”แƒ›แƒแƒ›แƒแƒ•แƒแƒšแƒ˜ แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒจแƒ”แƒกแƒแƒ‘แƒแƒ›แƒ˜แƒก แƒ˜แƒœแƒกแƒขแƒแƒœแƒ–แƒ”, แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ“แƒแƒแƒ‘แƒ แƒฃแƒœแƒ”แƒ‘แƒก แƒฉแƒ•แƒ”แƒœแƒ˜ Consule-แƒ˜แƒก แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒ˜, แƒจแƒ”แƒ›แƒแƒ›แƒแƒ•แƒแƒšแƒ˜ แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜แƒก แƒ แƒแƒฃแƒขแƒ˜แƒก แƒžแƒ แƒ”แƒคแƒ˜แƒฅแƒกแƒ˜แƒก แƒ›แƒ˜แƒฎแƒ”แƒ“แƒ•แƒ˜แƒ—,แƒ แƒแƒช แƒ–แƒ”แƒ›แƒแƒ— แƒฃแƒ™แƒ•แƒ” แƒ•แƒแƒฎแƒกแƒ”แƒœแƒ”แƒ—.

load-balancer.js
import { createServer } from 'http';
import httpProxy from 'http-proxy';
import Consul from 'consul';
 
// โ‘  แƒ’แƒแƒœแƒ•แƒกแƒแƒ–แƒ•แƒ แƒแƒ— แƒ แƒแƒฃแƒขแƒ”แƒ‘แƒ˜ แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก
const routing = [
  {
    path: '/api', //แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒก แƒ“แƒแƒ˜แƒฌแƒงแƒ”แƒ‘แƒ /api แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜แƒ—, แƒ’แƒแƒ“แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ“แƒ”แƒ‘แƒ api-service-แƒ–แƒ”
    service: 'api-service',
    index: 0,
  },
  {
    path: '/', // แƒแƒ› แƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ˜แƒ— แƒ“แƒแƒฌแƒงแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ˜ แƒ™แƒ˜ แƒ’แƒแƒ“แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ“แƒ”แƒ‘แƒ webapp-service-แƒ–แƒ”.
    service: 'webapp-service',
    index: 0,
  },
];
 
const consulClient = new Consul();
 
const proxy = httpProxy.createProxyServer();
const server = createServer(async (req, res) => {
	//1๏ธโƒฃ
	const route = routing.find((route) => req.url.startsWith(route.path));
 
	try {
		//2๏ธโƒฃ
		const serviseList = await consulClient.agent.service.list();
		const instances = Object.values(serviseList).filter((service) =>
			service.Tags.includes(route.service)
		);
		if (!instances.length) {
			res.writeHead(502);
			return res.end("Bad gateway");
		}
 
		//3๏ธโƒฃ
		route.index = (route.index + 1) % instances.length;
		const instance = instances[route.index];
		const target = `http://${instance.Address}:${instance.Port}`;
		proxy.web(req, res, { target });
	} catch (error) {
		// If there's an error or no servers are found, return a "Bad gateway" error
		console.error("Error fetching services", error);
		res.writeHead(502);
		return res.end("Bad gateway");
	}
});
 
 
// Start the load balancer on port 8080
server.listen(8080, () => console.log("Load balancer started on port 8080"));
 

แƒ”แƒกแƒ”แƒ˜แƒ’แƒ˜ แƒ แƒ แƒ“แƒแƒ•แƒแƒ›แƒแƒขแƒ”แƒ—,

แƒ‘แƒแƒšแƒแƒก แƒ™แƒ˜ แƒฉแƒ•แƒ”แƒœแƒ˜ แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜ แƒ’แƒแƒ•แƒฃแƒจแƒแƒ—, 8080 แƒžแƒแƒ แƒขแƒ–แƒ” แƒ“แƒ แƒ•แƒฃแƒกแƒ›แƒ˜แƒœแƒแƒ— แƒจแƒ”แƒ›แƒแƒ›แƒแƒ•แƒแƒš แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ”แƒ‘แƒก.

แƒ›แƒแƒ“แƒ˜ แƒ’แƒแƒ•แƒขแƒ”แƒกแƒขแƒแƒ— แƒ แƒแƒฆแƒแƒชแƒ”แƒ”แƒ‘แƒ˜,แƒ“แƒแƒ•แƒกแƒขแƒแƒ แƒขแƒแƒ— แƒฏแƒ”แƒ  แƒšแƒแƒแƒ“-แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜:

forever start -f --killSignal=SIGINT src/load-balancer.js

แƒแƒฎแƒšแƒ,แƒ›แƒแƒ“แƒ˜ แƒ’แƒแƒ•แƒฃแƒจแƒ•แƒแƒ— แƒžแƒแƒ แƒแƒšแƒ”แƒšแƒฃแƒ แƒแƒ“ 2 แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ api-service-แƒกแƒ—แƒ•แƒ˜แƒก แƒ“แƒ 1 แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ webapp-service-แƒกแƒ—แƒ•แƒ˜แƒก, แƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ— forever แƒ‘แƒ˜แƒ‘แƒšแƒ˜แƒแƒ—แƒ”แƒ™แƒแƒก:

	forever start -f --killSignal=SIGINT src/app.js api-service    
	forever start -f --killSignal=SIGINT src/app.js api-service    
	forever start -f --killSignal=SIGINT src/app.js webapp-service

แƒšแƒแƒแƒ“ แƒ‘แƒแƒšแƒแƒœแƒกแƒ”แƒ แƒ˜ แƒแƒ•แƒขแƒแƒ›แƒแƒขแƒฃแƒ แƒแƒ“ แƒ“แƒแƒ˜แƒœแƒแƒฎแƒแƒ•แƒก แƒแƒฎแƒแƒš แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ”แƒ‘แƒก, แƒ แƒแƒช แƒ“แƒแƒ˜แƒกแƒขแƒแƒ แƒขแƒ แƒ“แƒ แƒ“แƒแƒ˜แƒฌแƒงแƒ”แƒ‘แƒก แƒ แƒ”แƒฅแƒ•แƒ”แƒกแƒขแƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒ“แƒแƒœแƒแƒฌแƒ˜แƒšแƒ”แƒ‘แƒแƒก.

แƒแƒฎแƒšแƒ, แƒ แƒแƒ› แƒ’แƒแƒ•แƒฃแƒจแƒ•แƒแƒ— แƒแƒ แƒฏแƒ”แƒ  api-แƒ–แƒ” แƒ แƒ”แƒฅแƒ”แƒ•แƒกแƒขแƒ˜, แƒ“แƒแƒ•แƒ˜แƒœแƒแƒฎแƒแƒ•แƒ— แƒ แƒแƒ› แƒกแƒฎแƒ•แƒแƒ“แƒแƒกแƒฎแƒ•แƒ แƒ˜แƒœแƒกแƒขแƒแƒœแƒกแƒ˜ แƒ“แƒแƒ˜แƒญแƒ”แƒ แƒก.

curl localhost:8080/api

แƒ›แƒแƒ“แƒšแƒแƒ‘แƒ แƒงแƒฃแƒ แƒแƒ“แƒฆแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก. แƒกแƒ แƒฃแƒšแƒ˜ แƒ™แƒแƒ“แƒ˜แƒก แƒšแƒ˜แƒœแƒ™แƒ˜