IoT용 NGINX Plus: 로드 밸런싱 MQTT

이 포스트에서는 NGINX Plus를 사용하여 MQTT 트래픽의 로드 밸런싱 하는 방법을 보여줍니다. MQTT는 원래 원격 유전과의 통신을 위해 1999년에 게시되었습니다. 2013년에 IoT 사용 사례를 위해 업데이트되었으며 이후 많은 IoT 배포에서 선택되는 프로토콜이 되었습니다. 수백만 대의 디바이스가 있는 프로덕션 IoT 배포에는 로드 밸런서의 고성능 및 고급 기능이 필요합니다. 이 2부작 포스트 시리즈에서는 다음과 같은 고급 사용 사례에 대해 설명합니다.

인터넷에서 가장 바쁜 웹사이트의 경우 NGINX와 NGINX Plus가 시장을 지배하고 있습니다. 실제로 NGINX는 다른 어떤 웹 서버보다 세계에서 가장 바쁜 100만 개의 사이트를 지원합니다. 단일 서버에서 100만 개 이상의 동시 연결을 처리할 수 있는 기능은 Airbnb, Netflix 및 Uber와 같은 “하이퍼스케일” 사이트 및 앱에서 채택을 주도했습니다.

NGINX Plus는 웹 서버, HTTP 리버스 프록시 및 로드 밸런서로 가장 일반적으로 알려져 있지만 TCP 및 UDP 애플리케이션을 지원하는 완벽한 기능을 갖춘 ADC(애플리케이션 딜리버리 컨트롤러)이기도 합니다. 이벤트 기반 아키텍처와 HTTP 사용 사례에 성공하게 만든 다른 모든 특성은 사물 인터넷(IoT)에도 동일하게 적용할 수 있습니다.

목차

1. 테스트 환경
2. 고가용성을 위한 활성 상태 확인으로 MQTT 로드 밸런싱
3. 구성 확인
4. NGINX JavaScript 모듈을 사용하여 세션 지속성을 위한 로드 밸런싱 MQTT
5. MQTT ClientId 기반 세션 지속성
6. 세션 지속성을 위한 NGINX Plus 구성
7. 세션 지속성을 위한 NGINX JavaScript 코드
8. 세션 지속성 확인
9. 결론
부록

1. 로드 밸런싱 테스트 환경

NGINX Plus의 기능을 탐색하기 위해 MQTT 브로커 클러스터와 함께 IoT 환경의 핵심 구성 요소를 나타내는 간단한 테스트 환경을 사용합니다. 이 환경의 MQTT 브로커는 Docker 컨테이너 내에서 실행되는 HiveMQ 인스턴스입니다.

MQTT 로드 밸런싱 및 세션 지속성을 위한 테스트 환경은 NGINX Plus를 MQTT 클라이언트와 Docker 컨테이너의 HiveMQ 서버 3개 사이의 TCP 로드 밸런서로 배치합니다.

MQTT 로드 밸런싱 및 세션 지속성을 위한 테스트 환경

NGINX Plus는 기본 MQTT 포트 1883에서 수신 대기하는 MQTT 브로커의 리버스 프록시 및 로드 밸런서 역할을 합니다. 백엔드 MQTT 노드를 확장할 수 있는 동안 클라이언트에 간단하고 일관된 인터페이스를 제공합니다(오프라인으로 전환할 수도 있음). 어떤 식으로든 클라이언트에 영향을 주지 않고. 테스트 환경에서 IoT 디바이스를 나타내는 Mosquitto command line tool를 클라이언트로 사용합니다.

이 포스트와 파트 2의 모든 사용 사례는 이 테스트 환경을 사용하며 모든 구성은 그림에 표시된 아키텍처에 직접 적용됩니다. 테스트 환경 구축에 대한 전체 지침은 부록을 참조하십시오.

2. 고가용성을 위한 활성 상태 확인으로 MQTT 로드 밸런싱

로드 밸런서의 주요 기능은 클라이언트에 영향을 주지 않고 백엔드 서버를 추가, 제거 또는 오프라인 상태로 전환할 수 있도록 애플리케이션에 고가용성을 제공하는 것입니다. 이를 안정적으로 수행하기 위해서는 각 백엔드 서버의 가용성을 사전에 조사하는 상태 확인이 필요합니다. 활성 상태 확인을 통해 NGINX Plus는 실제 클라이언트 요청이 도달하기 전에 로드 밸런싱 그룹에서 실패한 서버를 제거할 수 있습니다.

상태 확인의 유용성은 실제 애플리케이션 트래픽을 얼마나 정확하게 시뮬레이션하고 응답을 분석하는지에 따라 달라집니다. ping과 같은 간단한 서버 활동성 검사는 백엔드 서비스가 실행 중인지 확인하지 않습니다. TCP 포트 개방 검사는 애플리케이션 자체가 정상인지 확인하지 않습니다. 여기서는 각 백엔드 서버가 새 MQTT 연결을 수락할 수 있는지 확인하는 상태 확인을 통해 테스트 환경에 대한 기본 로드 밸런싱을 구성합니다.

두 가지 구성 파일을 주로 변경하고 있습니다.

기본 nginx.conf 파일에는 NGINX와 동일한 디렉터리에 있는 stream_conf.d 하위 디렉터리에 있는 하나 이상의 파일에서 TCP 로드 밸런싱을 위한 구성에서 NGINX Plus를 읽도록 다음 stream 블록 및 지시문을 포함합니다. 회의 nginx.conf에 실제 구성을 포함하는 대신 이 작업을 수행합니다.

stream {
    include stream_conf.d/*.conf;
}

그런 다음 nginx.conf와 동일한 디렉터리에 TCP 및 UDP 구성 파일을 포함할 stream_conf.d 디렉터리를 만듭니다. 기존 conf.d 디렉토리는 기본적으로 http 구성 컨텍스트용으로 예약되어 있고 여기에 stream 구성을 추가하면 실패하기 때문에 사용하지 않습니다.

log_format mqtt '$remote_addr [$time_local] $protocol $status $bytes_received ' 
                '$bytes_sent $upstream_addr';

upstream hive_mq {
    server 127.0.0.1:18831; #node1
    server 127.0.0.1:18832; #node2
    server 127.0.0.1:18833; #node3
    zone tcp_mem 64k;
}

match mqtt_conn {
        # Send CONNECT packet with client ID "nginx health check"
        send \x10\x20\x00\x06\x4d\x51\x49\x73\x64\x70\x03\x02\x00\x3c\x00\x12\x6e\x67\x69\x6e\x78\x20\x68\x65\x61\x6c\x74\x68\x20\x63\x68\x65\x63\x6b;
        expect \x20\x02\x00\x00; # Entire payload of CONNACK packet
}

server {
    listen 1883;
    proxy_pass hive_mq;
    proxy_connect_timeout 1s;
    health_check match=mqtt_conn;

    access_log /var/log/nginx/mqtt_access.log mqtt;
    error_log  /var/log/nginx/mqtt_error.log; # Health check notifications
}

stream_mqtt_healthcheck.conf에서 먼저 MQTT 트래픽에 대한 Access Log 포멧을 정의합니다(1-2행). 결과 로그를 로그 분석 도구로 가져올 수 있도록 의도적으로 HTTP 일반 로그 형식과 유사합니다.

다음으로 3개의 MQTT 서버를 포함하는 hive_mq(라인 4–9)라는 upstream 그룹을 정의합니다. 테스트 환경에서는 각각 고유한 포트 번호를 사용하여 localhost에서 액세스할 수 있습니다. zone 지시문은 로드 밸런싱 상태 및 상태 정보를 유지하기 위해 모든 NGINX Plus Worker 프로세스에서 공유되는 메모리 양을 정의합니다.

match 블록(11–15행)은 MQTT 서버의 가용성을 테스트하는 데 사용되는 상태 확인을 정의합니다. send 지시문은 NGINX 상태 확인의 클라이언트 식별자(ClientId)가 있는 완전한 MQTT CONNECT 패킷의 16진수 표현입니다. 상태 확인이 실행될 때마다 upstream 그룹에 정의된 각 서버로 전송됩니다. 해당 expect 지시문은 NGINX Plus가 정상이라고 간주하기 위해 서버가 반환해야 하는 응답을 설명합니다. 여기서 4바이트 16진수 문자열 20 02 00 00은 완전한 MQTT CONNACK 패킷입니다. 이 패킷을 수신하면 MQTT 서버가 새 클라이언트 연결을 수신할 수 있음을 보여줍니다.

server 블록(17–25행)은 NGINX Plus가 클라이언트를 처리하는 방법을 구성합니다. NGINX Plus는 기본 MQTT 포트인 1883에서 수신 대기하고 모든 트래픽을 hive_mq upstream 그룹(19행)으로 전달합니다. health_check 지시문은 상태 검사가 upstream 그룹에 대해 수행되고(기본 빈도 5초) mqtt_conn match 블록에 의해 정의된 검사가 사용되도록 지정합니다.

3. 로드 밸런싱 구성 확인

이 기본 구성이 작동하는지 테스트하기 위해 Mosquitto 클라이언트를 사용하여 일부 테스트 데이터를 테스트 환경에 게시할 수 있습니다.

$ mosquitto_pub -d -h mqtt.example.com -t "topic/test" -m "test123" -i "thing001"
Client thing001 sending CONNECT
Client thing001 received CONNACK
Client thing001 sending PUBLISH (d0, q0, r0, m1, 'topic/test', ... (7 bytes))
Client thing001 sending DISCONNECT
$ tail --lines=1 /var/log/nginx/mqtt_access.log
192.168.91.1 [23/Mar/2017:11:41:56 +0000] TCP 200 23 4 127.0.0.1:18831

Access Log의 라인은 NGINX Plus가 총 23바이트를 수신했고 4바이트가 클라이언트(CONNACK 패킷)로 전송되었음을 보여줍니다. 또한 MQTT node1이 선택된 것을 볼 수 있습니다(포트 18831). Access Log의 다음 행에서 볼 수 있듯이 테스트를 반복하면 기본 라운드 로빈 로드 밸런싱 알고리즘이 node1, node2node3을 차례로 선택합니다.

$ tail --lines=4 /var/log/nginx/mqtt_access.log
192.168.91.1 [23/Mar/2017:11:41:56 +0000] TCP 200 23 4 127.0.0.1:18831
192.168.91.1 [23/Mar/2017:11:42:26 +0000] TCP 200 23 4 127.0.0.1:18832
192.168.91.1 [23/Mar/2017:11:42:27 +0000] TCP 200 23 4 127.0.0.1:18833
192.168.91.1 [23/Mar/2017:11:42:28 +0000] TCP 200 23 4 127.0.0.1:18831

4. NGINX JavaScript 모듈을 사용하여 세션 지속성을 위한 로드 밸런싱 MQTT

[메모 – 다음 사용 사례는 NGINX JavaScript 모듈의 많은 사용 사례 중 하나에 불과합니다. 전체 목록은 NGINX JavaScript 모듈의 사용 사례를 참조하세요.]

이 섹션의 코드는 블로그가 처음 게시된 이후 NGINX JavaScript 구현에 대한 변경 사항을 반영하기 위해 다음과 같이 업데이트됩니다.

  • NGINX JavaScript 0.2.4에서 도입된 stream 모듈용 리팩터링된 세션 개체를 사용합니다.
  • NGINX Plus R23 이상에서 js_include 지시어를 대체하는 js_import 지시어를 사용합니다. 자세한 내용은 NGINX JavaScript 모듈에 대한 참조 문서를 참조하세요. 예제 구성 섹션은 NGINX 구성 및 JavaScript 파일에 대한 올바른 구문을 보여줍니다.

라운드 로빈 로드 밸런싱은 클라이언트 연결을 서버 그룹에 분산시키는 효과적인 메커니즘입니다. 그러나 MQTT 연결에 적합하지 않은 몇 가지 이유가 있습니다.

MQTT 서버는 종종 클라이언트와 서버 간의 오 연결을 기대하며 많은 세션 상태가 서버에 구축될 수 있습니다. 안타깝게도 IoT 디바이스와 이들이 사용하는 IP 네트워크의 특성상 연결이 끊어져 일부 클라이언트가 자주 다시 연결해야 합니다. NGINX Plus는 해시 로드 밸런싱 알고리즘을 사용하여 클라이언트 IP 주소를 기반으로 MQTT 서버를 선택할 수 있습니다. $remote_addr 해시를 추가하기만 하면 됩니다. upstream 블록에 대한 세션 지속성을 활성화하여 지정된 클라이언트 IP 주소에서 새 연결이 들어올 때마다 동일한 MQTT 서버가 선택되도록 합니다.

그러나 특히 셀룰러 네트워크(예: GSM 또는 LTE)를 사용하는 경우 동일한 IP 주소에서 다시 연결하기 위해 IoT 디바이스에 의존할 수 없습니다. 동일한 클라이언트가 동일한 MQTT 서버에 다시 연결되도록 하려면 MQTT 클라이언트 식별자를 해싱 알고리즘의 키로 사용해야 합니다.

5. MQTT ClientId 기반 세션 지속성

MQTT ClientId는 초기 CONNECT 패킷의 필수 요소입니다. 즉, 패킷이 upstream 서버에 프록시되기 전에 NGINX Plus에서 사용할 수 있습니다. NGINX JavaScript를 사용하여 CONNECT 패킷을 구문 분석하고 MQTT 관련 세션 지속성을 구현하기 위해 해시 지시문에서 사용할 수 있는 변수로 ClientId를 추출할 수 있습니다.

NGINX JavaScript는 “NGINX‑네이티브” 프로그램 구성 언어입니다. NGINX 및 NGINX Plus를 위한 고유한 JavaScript 구현으로 서버 측 사용 사례 및 요청별 처리를 위해 특별히 설계되었습니다. MQTT용 세션 지속성 구현에 적합한 세 가지 주요 특성이 있습니다.

  • NGINX JavaScript는 NGINX Plus 처리 단계와 긴밀하게 통합되어 클라이언트 패킷이 upstream 그룹으로 로드 밸런싱되기 전에 클라이언트 패킷을 검사할 수 있습니다.
  • NGINX JavaScript는 문자열 및 수치 처리에 내장된 JavaScript 메서드를 사용하여 레이어 4 프로토콜의 효율적인 구문 분석을 가능하게 합니다. MQTT CONNECT 패킷의 실제 구문 분석에는 20줄 미만의 코드가 필요합니다.
  • NGINX JavaScript는 NGINX Plus 구성에 사용할 수 있는 변수를 만들 수 있습니다.

6. 세션 지속성을 위한 NGINX Plus 로드 밸런싱 구성

이 사용 사례에 대한 NGINX Plus 구성은 비교적 간단합니다. 다음 구성은 간결성을 위해 상태 확인(Health Check)이 제거된 Active Health Check을 사용한 로드 밸런싱의 수정된 버전입니다.


js_import mqtt.js;
js_set     $mqtt_client_id mqtt.setClientId;

log_format mqtt '$remote_addr [$time_local] $protocol $status $bytes_received ' 
                '$bytes_sent $upstream_addr $mqtt_client_id'; # Include MQTT ClientId

upstream hive_mq {
    server 127.0.0.1:18831; #node1
    server 127.0.0.1:18832; #node2
    server 127.0.0.1:18833; #node3
    zone tcp_mem 64k;
    hash $mqtt_client_id consistent; # Session persistence keyed against ClientId
}

server {
    listen 1883;
    preread_buffer_size 1k; # Big enough to read CONNECT packet header
    js_preread mqtt.getClientId; # Parse CONNECT packet for ClientId

    proxy_pass hive_mq;
    proxy_connect_timeout 1s;

    access_log /var/log/nginx/mqtt_access.log mqtt;
    error_log  /var/log/nginx/mqtt_error.log info; # NGINX JavaScript debug logging
}

js_import 지시문을 사용하여 NGINX JavaScript 코드의 위치를 지정하는 것으로 시작합니다. js_set 지시문은 $mqtt_client_id변수를 평가해야 할 때 setClientId 함수를 호출하도록 NGINX Plus에 지시합니다. 이 변수를 5행의 mqtt 로그 형식에 추가하여 Access Log에 세부 정보를 추가합니다.

$mqtt_client_id를 키로 지정하는 hash 지시문을 사용하여 12행에서 세션 지속성을 활성화합니다. upstream 서버에 장애가 발생하는 경우 해당 서버에 이미 설정된 세션에 영향을 주지 않고 해당 서버의 트래픽 공유가 나머지 서버에 고르게 분산되도록 하기 위해 consistent 매개 변수를 사용합니다. 일관된 hashing은 NGINX Cache 클러스터 구축 에 대한 포스트에서 자세히 설명합니다. 원칙과 이점은 여기에서 동일하게 적용됩니다.

js_preread 지시문(18행)은 요청 처리의 미리 읽기 단계에서 실행되는 NGINX JavaScript 함수를 지정합니다. 사전 읽기 단계는 모든 패킷(양방향)에 대해 트리거되고 upstream 블록에서 필요할 때 $mqtt_client_id의 값을 사용할 수 있도록 프록시 전에 발생합니다.

7. 세션 지속성을 위한 NGINX JavaScript 코드

NGINX Plus 구성 파일(stream_mqtt_session_persistence.conf)의 js_import 지시문에 의해 로드되는 mqtt.js 파일에서 MQTT ClientId를 추출하기 위한 JavaScript를 정의합니다.


var client_messages = 1;
var client_id_str = "-";

function getClientId(s) {
    s.on('upload', function (data, flags) {
        if ( data.length == 0  ) {  // Initial calls may contain no data, so
            s.log("No buffer yet"); // ask that we get called again
            //s.done(1);            // (supposing that code=1 means that)
            return;

기본 함수인 getClientId()는 4행에서 선언됩니다. 현재 TCP 세션을 나타내는 s라는 개체가 전달됩니다. 세션 개체에는 수많은 속성이 있으며 그 중 일부는 이 함수에서 사용됩니다.

5-9행은 현재 패킷이 클라이언트로부터 가장 먼저 수신되도록 합니다. 후속 클라이언트 메시지와 서버 응답은 무시되므로 일단 연결이 설정되면 트래픽 흐름에 추가 오버헤드가 없습니다.

        } else if ( client_messages == 1 ) { // CONNECT is first packet from the client
            // CONNECT packet is 1, using upper 4 bits (00010000 to 00011111)
            var packet_type_flags_byte = data.charCodeAt(0);
            s.log("MQTT packet type+flags = " + packet_type_flags_byte.toString());
            if ( packet_type_flags_byte >= 16 && packet_type_flags_byte < 32 ) {
                // Calculate remaining length with variable encoding scheme
                var multiplier = 1;
                var remaining_len_val = 0;
                var remaining_len_byte;
                for (var remaining_len_pos = 1; remaining_len_pos < 5; remaining_len_pos++ ) {
                    remaining_len_byte = data.charCodeAt(remaining_len_pos);
                    if ( remaining_len_byte == 0 ) break; // Stop decoding on 0
                    remaining_len_val += (remaining_len_byte & 127) * multiplier;
                    multiplier *= 128;
                }

라인 10–24는 패킷이 CONNECT 유형인지 확인하고 MQTT 페이로드가 시작되는 위치를 결정하기 위해 MQTT 헤더를 검사합니다.


                // Extract ClientId based on length defined by 2-byte encoding
                var payload_offset = remaining_len_pos + 12; // Skip fixed header
                var client_id_len_msb = data.charCodeAt(payload_offset).toString(16);
                var client_id_len_lsb = data.charCodeAt(payload_offset + 1).toString(16);
                if ( client_id_len_lsb.length < 2 ) client_id_len_lsb = "0" + client_id_len_lsb;
                var client_id_len_int = parseInt(client_id_len_msb + client_id_len_lsb, 16);
                client_id_str = data.substr(payload_offset + 2, client_id_len_int);
                s.log("ClientId value  = " + client_id_str);
            } else {
                s.log("Received unexpected MQTT packet type+flags: " + packet_type_flags_byte.toString());
            }
        }
        client_messages++;
        s.allow();
    });
}

function setClientId(s) {
    return client_id_str;
}

export default { getClientId setClientId }

27~32행은 페이로드에서 ClientId를 추출하여 JavaScript 전역 변수 client_id_str에 값을 저장합니다. 그런 다음 이 변수를 setClientId 함수를 사용하여 NGINX 구성으로 내보냅니다(43–45행).

8. 세션 지속성 확인

이제 Mosquitto 클라이언트를 다시 사용하여 세 가지 다른 ClientId 값(-i 옵션)과 함께 일련의 MQTT 게시 요청을 전송하여 세션 지속성을 테스트할 수 있습니다.

$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "foo"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "bar"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "baz"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "foo"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "foo"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "foo"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "bar"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "bar"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "baz"
$ mosquitto_pub -h mqtt.example.com -t "topic/test" -m "test123" -i "baz"

Access Log를 검토하면 ClientId foo는 항상 node1(포트 18831)에 연결되고 ClientId bar는 항상 node2(포트 18832)에 연결되며 ClientId baz는 항상 node3(포트 18833)에 연결됩니다.

$ tail /var/log/nginx/mqtt_access.log
192.168.91.1 [23/Mar/2017:12:24:24 +0000] TCP 200 23 4 127.0.0.1:18831 foo
192.168.91.1 [23/Mar/2017:12:24:28 +0000] TCP 200 23 4 127.0.0.1:18832 bar
192.168.91.1 [23/Mar/2017:12:24:32 +0000] TCP 200 23 4 127.0.0.1:18833 baz
192.168.91.1 [23/Mar/2017:12:24:35 +0000] TCP 200 23 4 127.0.0.1:18831 foo
192.168.91.1 [23/Mar/2017:12:24:37 +0000] TCP 200 23 4 127.0.0.1:18831 foo
192.168.91.1 [23/Mar/2017:12:24:38 +0000] TCP 200 23 4 127.0.0.1:18831 foo
192.168.91.1 [23/Mar/2017:12:24:42 +0000] TCP 200 23 4 127.0.0.1:18832 bar
192.168.91.1 [23/Mar/2017:12:24:44 +0000] TCP 200 23 4 127.0.0.1:18832 bar
192.168.91.1 [23/Mar/2017:12:24:47 +0000] TCP 200 23 4 127.0.0.1:18833 baz
192.168.91.1 [23/Mar/2017:12:24:48 +0000] TCP 200 23 4 127.0.0.1:18833 baz

세션 지속성 또는 다른 로드 밸런싱 알고리즘을 사용하는지 여부에 관계없이 액세스 로그 라인에 나타나는 MQTT ClientId의 이점도 있습니다.

9. NGINX 로드 밸런싱 결론

두 부분으로 구성된 이 시리즈의 첫 번째 포스트에서는 NGINX Plus가 활성 상태 확인을 사용하여 IoT 애플리케이션의 가용성과 안정성을 개선하는 방법과 NGINX JavaScript가 다음과 같은 레이어 7 로드 밸런싱 기능을 제공하여 NGINX Plus를 확장하는 방법을 시연했습니다. TCP 트래픽에 대한 세션 지속성. 두 번째 부분에서는 NGINX Plus가 TLS 종료를 오프로드하고 클라이언트를 인증하여 IoT 애플리케이션을 더 안전하게 만드는 방법을 살펴봅니다.

NGINX JavaScript와 결합하거나 자체적으로 NGINX Plus 고유의 고성능 및 효율성을 통해 IoT 인프라를 위한 소프트웨어 로드 밸런서로 이상적입니다.

NGINX Plus와 함께 NGINX JavaScript를 사용해 보려면 무료 30일 평가판을 시작하거나 당사에 연락하여 사용 사례에 대해 논의하십시오.


부록

목차

1. 테스트 환경 만들기
1-1. NGINX Plus 설치
1-2. HiveMQ 설치
1-3. Mosquitto 설치
2. NGINX 및 NGINX Plus용 NGINX JavaScript 활성화
2-1. NGINX Plus용 NGINX JavaScript 모듈 로드
2-2. NGINX Open Source용 NGINX JavaScript 모듈 로드
2-3. NGINX Open Source용 동적 모듈로 NGINX JavaScript 컴파일

1. 테스트 환경 만들기

격리되고 반복 가능하도록 테스트 환경을 가상 머신에 설치했습니다. 그러나 물리적인 “베어 메탈” 서버에 설치할 수 없는 이유는 없습니다.

1-1. NGINX Plus 설치

NGINX Plus 관리자 가이드의 지침을 참조하세요.

1-2. HiveMQ 설치

모든 MQTT 서버를 사용할 수 있지만 이 테스트 환경은 HiveMQ(여기에서 다운로드)를 기반으로 합니다. 이 예에서는 각 노드에 대해 Docker 컨테이너를 사용하여 단일 호스트에 HiveMQ를 설치합니다. 다음 지침은 Docker를 사용하여 HiveMQ 배포에서 채택되었습니다.

1. hivemq.zip과 동일한 디렉터리에 HiveMQ용 Dockerfile을 만듭니다.

# Pull base image. The official docker openjdk-8 image is used here.
FROM java:8-jdk

# Copy HiveMQ to container
COPY hivemq.zip /tmp/
 
#Install wget and unzip, then download and install HiveMQ.
RUN \
    apt-get install -y wget unzip &&\
    unzip /tmp/hivemq.zip -d /opt/ &&\
    mv /opt/hivemq-* /opt/hivemq
  
# Define working directory.
WORKDIR /opt/hivemq
 
# Define HIVEMQ_HOME variable
ENV HIVEMQ_HOME /opt/hivemq
 
# Expose MQTT port
EXPOSE 1883
 
# Define default command. Here we use HiveMQ's run script.
CMD ["/opt/hivemq/bin/run.sh"]

2. hivemq.zip 및 Dockerfile이 포함된 디렉터리에서 작업하여 Docker 이미지를 만듭니다.

$ docker build -t hivemq:latest .

3. 각각 다른 포트에 노출되는 3개의 HiveMQ 노드를 만듭니다.

$ docker run -p 18831:1883 -d --name node1 hivemq:latest
ff2c012c595a
$ docker run -p 18832:1883 -d --name node2 hivemq:latest
47992b1f4910
$ docker run -p 18833:1883 -d --name node3 hivemq:latest
17303b900b64

4. 3개의 HiveMQ 노드가 모두 실행 중인지 확인합니다. (다음 샘플 출력에서는 쉽게 읽을 수 있도록 COMMAND, CREATED STATUS 열이 생략되었습니다.)

$ docker ps
CONTAINER ID  IMAGE          ...  PORTS                     NAMES
17303b900b64  hivemq:latest  ...  0.0.0.0:18833->1883/tcp   node3
47992b1f4910  hivemq:latest  ...  0.0.0.0:18832->1883/tcp   node2
ff2c012c595a  hivemq:latest  ...  0.0.0.0:18831->1883/tcp   node1

1-3. Mosquitto 설치

Mosquitto 명령줄 클라이언트는 프로젝트 웹 사이트에서 다운로드할 수 있습니다. Homebrew가 설치된 Mac 사용자는 다음 명령을 실행할 수 있습니다.

$ brew install mosquitto

Docker 이미지 중 하나에 간단한 게시 메시지를 전송하여 Mosquitto 클라이언트 및 HiveMQ 설치를 테스트합니다.

$ mosquitto_pub -d -h mqtt.example.com -t "topic/test" -m "test123" -i "thing001" -p 18831
Client thing001 sending CONNECT
Client thing001 received CONNACK
Client thing001 sending PUBLISH (d0, q0, r0, m1, 'topic/test', ... (7 bytes))
Client thing001 sending DISCONNECT

2. NGINX 및 NGINX Plus용 NGINX JavaScript 활성화

2-1. NGINX Plus용 NGINX JavaScript 모듈 로드

NGINX JavaScript는 NGINX Plus 가입자를 위한 무료 동적 모듈로 제공됩니다. 로드 지침은 NGINX Plus 관리자 가이드를 참조하세요.

2-2. NGINX Open Source용 NGINX JavaScript 모듈 로드

NGINX JavaScript 모듈은 기본적으로 공식 NGINX Docker 이미지에 포함되어 있습니다. 시스템이 NGINX Open Source 용 공식 사전 빌드 패키지를 사용하도록 구성되어 있고 설치된 버전이 1.9.11 이상인 경우 NGINX JavaScript를 플랫폼용 사전 빌드 패키지로 설치할 수 있습니다.

1. 미리 빌드된 패키지를 설치합니다.

Ubuntu 및 Debian 시스템의 경우:

$ sudo apt-get install nginx-module-njs

RedHat, CentOS 및 Oracle Linux 시스템의 경우:

$ sudo yum install nginx-module-njs

2. nginx.conf 구성 파일의 최상위(“main”) 컨텍스트(http 또는 stream 컨텍스트가 아님)에 모듈에 대한 load_module 지시문을 포함하여 모듈을 활성화합니다. 이 예제는 HTTP 및 TCP/UDP 트래픽 모두에 대해 NGINX JavaScript 모듈을 로드합니다.

load_module modules/ngx_http_js_module.so;
load_module modules/ngx_stream_js_module.so;

3. NGINX를 다시 로드하여 NGINX JavaScript 모듈을 실행 중인 인스턴스에 로드합니다.

$ sudo nginx -s reload

2-3. NGINX Open Source용 동적 모듈로 NGINX JavaScript 컴파일

source 에서 NGINX 모듈을 컴파일하려는 경우:

  1. 다음 지침에 따라 Open Source 리포지토리에서 HTTP 및 TCP/UDP NGINX JavaScript 모듈 중 하나 또는 모두를 빌드합니다.
  2. 모듈 바이너리(ngx_http_js_module.so, ngx_stream_js_module.so)를 NGINX root의 모듈 하위 디렉토리(일반적으로 /etc/nginx/modules)에 복사합니다.
  3. NGINX Open Source용 NGINX JavaScript 모듈 로드의 2단계와 3단계를 수행합니다.

사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required