แจแแกแแแแแ
แแแแแ แฏแแแ, แแก แแ แแก แฉแแแ แแแ แแแแ แกแขแแขแแ แฅแแ แแฃแ แแแแแ แแ แ แแแแ แช แกแแแแฃแ แแแแ แฉแแแก, แแ แกแขแแขแแแจแ แแแแแ แแแกแแฃแแ แ dynamic load balancer
-แแ แแ แจแแแแแ แแ แแแ
แแแแฌแแ แแ nodejs
-แแก แแแแแงแแแแแแ.
Dynamic horizontal Scaling
แแ แ-แแ แแ แแแแจแแแแแแแแแ แฃแแแ แแขแแกแแแ, แ แแช แฅแแแฃแแแ แแแคแฃแซแแแแฃแ แแแคแ แแกแขแ แฃแฅแขแฃแ แแก แแฅแแก แแ แแก แแก แ แแ, แแแ แจแแฃแซแแแแ แแแแแแแฃแ แแ แแแแแฃแงแแ แ แแแฎแแแ แ แแกแฃแ แกแแช
แกแญแ แแแแแ แแแแแแแชแแแแก, แแแแก แแแฎแแแแแ แแฃ แ แ แขแ แแคแแแ แแแแแก แแแกแแ. Dynamic scaling
-แแแแช แแ แแก แชแแแแแแ แแก แกแแแแแฎแ. แแฃ แกแฌแแ แแ แแแแแแแแแแแแแขแแ แแแ, แแ แแแแแแแแ
แจแแกแแซแแแ แกแแแ แซแแแแแแ แจแแแแชแแ แแก IT
แแแคแ แแกแขแ แฃแฅแขแฃแ แแก แคแแกแ, แแกแ แ แแ แแแแแแแชแแ แแกแแ highly available - แแแฆแแ แฎแแแแแกแฌแแแแแแ
แแแ แฉแแก.
Idea
แแแแ แแ แแก แแแ แขแแแ: แแฃ แแแแแแแชแแแก แแฅแแก แแแ แคแแ แแแแกแแก แแแ แแแ แแแฆแแแ แขแ แแคแแแแก แแแแ, แกแแกแขแแแ แแแขแแแแขแฃแ แแ แแแ แแแแแแก แแแก แแแกแขแแแกแขแแแก แแฎแแ แกแแ แแแ แแ, แ แแ แแแฃแแแแแแแแก แแแขแแแ แแแแก. แแแแแแแแฃแ แแ, แแฃ แแแแแงแแคแแแ แ แแกแฃแ แกแแแ แแแ แแแแแแงแแแแแ, แแแแแแขแแ, แแแจแแ แฃแแแ แแแแแแ แแแ แแแแแแ แแ แแแแแแแ, แ แแ แจแแแแแชแแ แแ แฎแแ แฏแ.
แแก แกแแแแแ แแแ แจแแแซแแแแ แแแฅแแแแแก แแแจแแแฃแแแแฃแแ, แ แแช แแแแก แแแจแแแแก, แ แแ แ แแฆแแช แกแแแแแแจแ แจแแแซแแแแ แแแแแแ แแแ แ แแแแแแฆแแช แกแแ แแแกแแแ, แ แแแแแ แแแชแแ แ แแ แแ แแแ แแแแจแ แแแขแแแ แแแ แซแแแแแ แแแแแแก แแ แแแแแ แแกแขแแ แขแแ แ แแแแ แช แแ แแแแฌแงแแแ แแก แกแแแแแแ, แ แแชแ แแแฌแแแ แแแฆแแแแ.
Service Registry
แแแแแแ แแแขแแ แแ, แ แแ แแก แแ แแแแแแ แแแแแแญแ แแ แแ แแก, แ แแ แแแแแแแงแแแแ แชแแแขแ แแแฃแ แ แ แแแแแแขแแ แ - service registry
, แ แแแแแแช แจแแแแแฎแแแก แแ แแแขแ แแแแแก, แ แแแแแ แกแแ แแแ แแ แแแจแแแแฃแแ แแ
แ แแแแแ แกแแ แแแกแแแ แแ แกแแ แแแ แแ.
แ แแแแ แช แแแแแ แแแแแแ แฉแแแก, แ แแชแ แ แแฅแแแฅแกแขแ แแแแ example.com
-แแ, แแแแ แแแแแแกแแ แ แแแแฌแแแแก แ แแฅแแแกแขแแก แแ แแคแแฅแกแก, แแฃ แแฌแงแแแ /api
-แแ แแกแแแ แ แแฅแแแกแขแ
แฃแแแ แแแแแแแแกแแแก API service
แแแกแขแแแกแแแแ, แ แแแแ แช แแฎแแแแแ แกแฃแ API
-แกแแแแก แแแแฅแแก แแ แ แแแกแขแแแกแ, แแ แแแ แแแแฅแแก แแแจแแแแฃแแ แแก แแ แแชแแกแ, api1
-แแ แแ api2
-แแ.
Implementing a dynamic load balancer with http-proxy and Consul
แกแแ แแแก แ แแแแกแขแ แแขแแ แแ แแแงแแแแ Consul-แก, แแฅ แแแขแก แแฆแแ แจแแแแ แแแขแแแแแจแ, แจแแแแซแแแแ แแแฎแแ แแแแฃแแแแขแแชแแ. แแแแกแฃแแแก แแแแแงแแแแแแก แแแแแแ แ แแแ แแ, แ แแ แแแแแแแแ แแ แแก แแฃแแขแแกแแ แแแกแฃแแ แแ แฅแแขแแฅแขแฃแ แ, แ แแแแแแช แแแแแ แแฆแฌแแ แแ แแแแแ แแแแแแ. แกแฃแ แแแแแแแงแแแแ 3 แแแแแแแแแแแก:
แแแแ แแแแแแแแแ แแแแแแแแแขแแชแแแก แแแฌแแแแ แฃแจแฃแแแแ.
Setting up the Service For Registration
แแแแฌแแ แแ แกแแ แแแก แ แแแแกแขแ แแขแแ แ, แแ แจแแแแฎแแแแแจแ แกแแ แแแกแแก แกแแฎแแแก แแแแแฆแแแ command-line
-แแแ.
แแแแ แแแแแฌแงแแ แแ แแแ แแแฎแกแแแ.
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
.
แแแแ แแแแแแ แซแแแแ...
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`);
}
);
}
แแฎแแ แแแแฌแแ แแ แแ แกแแ แแแกแ แแแแฆแแแ/แฌแแจแแ แแแแกแฃแแแก แ แแแแกแขแ แแแแ.แแแแแแ แ แแแแแแ แแ แคแฃแแชแฅแแแก แแแแแงแแแแแแก แแฅแแแแ แแก,แ แแ แแฃ แกแแญแแ แ แแแฎแแ แกแแ แแแกแ แแแแแ แแแ แแ แแฃ แแ แแ แ แแแฎแแ,แแ แ แแแแ แแฅแกแแคแจแแแ แแแแกแ แแแ แฉแแแแ แกแแ แแแกแแก แแ แแชแแกแแ, แฃแแแ แฌแแแจแแแแก แแก แกแแ แแแกแ แแแแกแฃแแแแแ แกแแแแ แแแแแ แแ แแชแแกแ แแแแแแแแ.
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
แแแแฃแแแก แแแแแงแแแแแแ, แแแแกแแแ แฉแแแแก แแแ แขแแ แแ แแแกแแแแ แแแ, แแ แกแแแฃแแแชแแ แแแแแแแแแ
แแแแฅแแก แ แแฅแแแกแขแแแ แจแแแแแแก แแ แแแกแแแแ แแแ.
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
แแแ แแแ แ แแแจแ, แแแแแ แแแแกแขแ แแ แแ แ แแฃแขแแแ, แแแฃ แ แแแแ แแแกแแแแ แแแ, แ แแแแ แกแแ แแแก แฃแแแ แแแแแ แแแก แแแแ แแแแแแกแแ แแ.
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
-แแก แแแแแแขแ, แจแแแแแแแแแ แ แแฅแแแกแขแแก แ แแฃแขแแก แแ แแคแแฅแกแแก
แแแฎแแแแแ,แ แแช แแแแแ แฃแแแ แแแฎแกแแแแ.
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"));
แแกแแแแ แ แ แแแแแแแขแแ,
-
1๏ธโฃแแแแฎแแ แแก แ แแฃแขแ, แ แแแแแแช แแฌแงแแแ แจแแแแแแแแแ แ แแฅแแกแแขแแก แฃแ แ-is
path
-แแ. -
2๏ธโฃ แฌแแแแแแฆแแ แงแแแแ แกแแ แแแกแแก แแแกแขแ, แแ แฃแจแฃแแแแ แแ แกแแ แแแกแแ แแแแคแแแขแ แแ แ แแแแแแช แ แแฃแขแแก แกแแ แแแกแก แแแแฎแแแแ.แแ แจแแแแฎแแแแแจแ แแคแแแขแ แแ แขแแแแ, แแกแ แจแแแแแซแแแ แฉแแแแก แจแแแแฎแแแแแจแ
name
-แแแแช แแแแแแคแแแขแ แ. แ แแแแ แช แแแฎแกแแแ แแแแแ, แขแแแแแ แแแแแแงแแแแแ แ แแ แแแขแแแแ แแแแแ แแแแงแแ, แ.แฌ.แแแแแแแแ แแแแแแแ แกแแ แแแกแแแก, แแ แแแแแ แแแคแแแขแแ แ แฃแคแ แ แแแขแแ แแแแแแจแแฌแแแแแแ. แแฃ แแแแแ แกแแ แแแกแแก แแแกแขแแแกแ/แแแกแขแแแกแแแ แแ แแ แกแแแแแก แแแกแแ แแ 502 แแ แแ แก,แแแฃ แแ แแกแฌแแ แ แแฃแขแก แแแแแ แแแแแ. -
3๏ธโฃ แแฎแแ แ แแช แจแแแฎแแแ, แแฃ แแแแแแแแ แแแกแขแแแกแแแ แแ แขแแแแก แกแแ แแแกแแก, แ แแแแ แแแแแฌแแแแแ แแ แจแแแแฎแแแแแจแ แแแขแแแ แแแแก. แแ แแแงแแแแ แแฅ แ แแฃแแ-แ แแแแแแก แแแแแ แแแแก. แแฃ แแแฅแแก แแ แแ แกแแ แแแกแแก 7 แแแกแขแแแกแ, แแแแแแฃแ แฏแแ แแ
route.index = (route.index + 1)% 7)
, แแกแ แแแแฎแแแ แแแแแฅแก, แแ แแแแซแ แแแแ แฌแ แแแ แฌแ แแแ: 1,2,3,4,5,6,0,1,2... แจแแกแแแแแแกแแ แขแ แแคแแแแก แแแแแแแฌแแแแแ แแแฅแแแแ แแแแแแแ แ.
แแแแแก แแ แฉแแแแ แแแแ แแแแแแกแแ แ แแแแฃแจแแ, 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
แแแแแแแ แงแฃแ แแแฆแแแแกแแแแก. แกแ แฃแแ แแแแแก แแแแแ