전체 코드는 다음과 같습니다.

    코드 8-4 HTTP 게이트웨이 전체 코드

    예제 파일 : gate.js

    'use strict'
    
    const http = require('http');
    const url = require('url');
    const querystring = require('querystring');
    const tcpClient = require('./client');
    
    var mapClients = {};
    var mapUrls = {};
    var mapResponse = {};
    var mapRR = {};
    var index = 0;
    
    // HTTP 서버를 만듦
    var server = http.createServer((req, res) => {
        var method = req.method;
        var uri = url.parse(req.url, true);
        var pathname = uri.pathname;
    
        if (method === "POST" || method === "PUT") {
            var body = "";
    
            req.on('data', function(data) {
                body += data;
            });
            req.on('end', function() {
                var params;
                if (req.headers['content-type'] == "application/json") {
                    params = JSON.parse(body);
                } else {
                    params = querystring.parse(body);
                }
    
                onRequest(res, method, pathname, params);
            });
        } else {
            onRequest(res, method, pathname, uri.query);
        }
    }).listen(8000, () => {
        console.log('listen', server.address());
    
        // Distributor와 통신 처리
        var packet = {
            uri: "/distributes",
            method: "POST",
            key: 0,
            params: {
                port: 8000,
                name: "gate",
                urls: []
            }
        };
        var isConnectedDistributor = false;
        this.clientDistributor = new tcpClient(
            "127.0.0.1"
            , 9000
            , (options) => { // 접속 이벤트
                isConnectedDistributor = true;
                this.clientDistributor.write(packet);
            }
            , (options, data) => { onDistribute(data); }        // 데이터 수신 이벤트
            , (options) => { isConnectedDistributor = false; }  // 접속 종료 이벤트
            , (options) => { isConnectedDistributor = false; }  // 에러 이벤트
        );
    
        // 주기적인 Distributor 접속 상태 확인
        setInterval(() => {
            if (isConnectedDistributor != true) {
                this.clientDistributor.connect();
            }
        }, 3000);
    });
    
    // API 호출 처리
    function onRequest(res, method, pathname, params) {
        var key = method + pathname;
        var client = mapUrls[key];
        if (client == null) {
            res.writeHead(404);
            res.end();
            return;
        } else {
            params.key = index;  // API 호출에 대한 고유키 값 설정
            var packet = {
                uri: pathname,
                method: method,
                params: params
            };
    
            mapResponse[index] = res;
            index++;
            if (mapRR[key] == null)  // 라운드 로빈 처리
                mapRR[key] = 0;
            mapRR[key]++;
            client[mapRR[key] % client.length].write(packet);
        }
    }
    
    // Distributor 접속 처리
    function onDistribute(data) {
        for (var n in data.params) {
            var node = data.params[n];
            var key = node.host + ":" + node.port;
            if (mapClients[key] == null && node.name != "gate") {
                var client = new tcpClient(node.host, node.port, onCreateClient,
                                           onReadClient, onEndClient, onErrorClient);
    
                mapClients[key] = {
                    client: client,
                    info: node
                };
                for (var m in node.urls) {
                    var key = node.urls[m];
                    if (mapUrls[key] == null) {
                        mapUrls[key] = [];
                    }
                    mapUrls[key].push(client);
                }
                client.connect();
            }
        }
    }
    
    // 마이크로서비스 접속 이벤트 처리
    function onCreateClient(options) {
        console.log("onCreateClient");
    }
    
    // 마이크로서비스 응답 처리
    function onReadClient(options, packet) {
        console.log("onReadClient", packet);
        mapResponse[packet.key].writeHead(200, { 'Content-Type': 'application/json' });
        mapResponse[packet.key].end(JSON.stringify(packet));
        delete mapResponse[packet.key];  // http 응답 객체 삭제
    }
    
    // 마이크로서비스 접속 종료 처리
    function onEndClient(options) {
        var key = options.host + ":" + options.port;
        console.log("onEndClient", mapClients[key]);
        for (var n in mapClients[key].info.urls) {
            var node = mapClients[key].info.urls[n];
            delete mapUrls[node];
        }
        delete mapClients[key];
    }
    
    // 마이크로서비스 접속 에러 처리
    function onErrorClient(options) {
        console.log("onErrorClient");
    }

    마이크로서비스 아키텍처에 필요한 게이트웨이, 분산 처리 서버, 마이크로서비스를 모두 만들었습니다. 다음 장에서는 마이크로서비스를 실행해 봅시다.

    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.