클 라 이언 트 병행 테스트 Mqtt Broker

6731 단어
백업 전재 금 총 노트
개술
본 고 는 example broker 에 대해 성능 테스트 를 할 때 클 라 이언 트 가 설정 해 야 하 는 관련 절 차 를 묘사 했다.
테스트 소프트웨어
example broker 는 Mqtt 서버 로 서 테스트 를 진행 할 때 해당 하 는 Mqtt 클 라 이언 트 가 필요 합 니 다.편리 성 을 고려 하여 우 리 는 nodejs 기반 의 오픈 소스 Mqtt 클 라 이언 트: MQTT. js 를 사용 했다.테스트 프로그램 을 실행 하기 전에 다음 과 같은 소프트웨어 를 설치 해 야 한다.
  • Git
  • Node.js
  • npm

  • 자신 이 미리 설정 한 작업 디 렉 터 리 실행 git clone https://github.com/mqttjs/MQTT.js 에서 최신 MQTT. js 를 다운로드 합 니 다.MQTT. js 실행 npm install 에 들 어가 필요 한 의존 팩 을 다운로드 합 니 다.
    테스트 프로그램 은 사용자 정의 ip 을 지원 해 야 하기 때문에 MQTT. js 프로그램 을 수정 하여 추가 인 자 를 추가 할 수 있 도록 해 야 합 니 다.문서 에서 지불 한 tcp. js 를 사용 하여 디 렉 터 리 MQTT. js 디 렉 터 리 의 동명 파일 을 교체 합 니 다.문서 에서 지불 한 perface 복사test. js 에서 MQTT. js 디 렉 터 리 로 이동 합 니 다.
    테스트 프로그램 을 실행 할 때 추가 적 인 인자 가 필요 합 니 다. 다음은 매개 변수 예제 설명 입 니 다. node performance_test.js joshua 192.168.1.100 10.65.81.60:12306 50000 그 중에서 joshua mqtt client id 의 접두사 입 니 다. 테스트 프로그램 은 뒤에 번호 에 따라 숫자 를 추가 하여 모든 유일한 연결 mqtt client id 를 확보 합 니 다.192.168.1.100 이 컴퓨터 의 ip 이 므 로 이 ip 이 이 컴퓨터 에서 사용 할 수 있 는 ip 중 하나 이 고 example broker ip 을 정상적으로 연결 할 수 있 도록 해 야 합 니 다.10.65.81.60:12306 테스트 가 필요 한 mqtt 서버 주소 와 포트, 50000 이번 테스트 연결 의 클 라 이언 트 수 입 니 다.이상 의 매개 변 수 는 테스트 필요 에 따라 스스로 수정 할 수 있 습 니 다.
    운영 체제
    테스트 서버 를 사용 하여 테스트 할 때 필요 한 병발 량 이 100, 000 이하 이면 Mac OS X 를 테스트 클 라 이언 트 가 사용 하 는 운영 체제 로 사용 할 수 있다.100, 000 이상 이면 리 눅 스 운영 체 제 를 사용 하고 여러 개의 ip 주 소 를 추가 하여 테스트 하 는 것 을 권장 합 니 다.다음은 이 두 운영 체제 에 대한 설정 을 소개 합 니 다. 일부 명령 은 루트 권한 이 필요 할 수 있 습 니 다.
    Mac OS X
    운영 체제 의 매개 변 수 는 tcp / ip 와 관련 된 네트워크 매개 변수 와 파일 설명자 의 관련 매개 변수 두 가지 가 있 습 니 다.
    실행 sysctl -a | grep port, 보기 net.inet.ip.portrange.first, net.inet.ip.portrange.hifirst 의 값.이 두 가지 값 은 운영 체제 의 사용자 가 사용 할 수 있 는 포트 의 시작 범 위 를 정의 하고 연결 이 필요 한 병발 량 에 따라 수정 합 니 다. 우 리 는 10, 000 으로 수정 하 는 것 을 권장 합 니 다.수 정 된 명령 은 다음 과 같다. sysctl -w net.inet.ip.portrange.first=10000, sysctl -w net.inet.ip.portrange.hifirst=10000.
    실행 sysctl -a | grep files, 보기 kern.maxfiles, kern.maxfilesperproc 두 항목 의 값.이 두 값 은 사용자 가 열 수 있 는 최대 파일 수 와 프로 세 스 마다 열 수 있 는 최대 파일 수 를 결정 합 니 다.우 리 는 1, 000, 000, 100, 000 으로 수정 할 것 을 건의 합 니 다.수 정 된 명령 은 다음 과 같다. sysctl -w kern.maxfiles=1000000, sysctl -w kern.maxfilesperproc=100000.
    4 core, 16G 메모리 의 rMBP 에 서 는 하나의 ip 이 최대 50, 000 개의 긴 연결 을 안정 적 으로 유지 할 수 있 습 니 다.연결 개 수 를 계속 늘 려 야 한다 면 ip 을 늘 리 는 방식 을 취 할 수 있 지만 실제 테스트 결과 에 따 르 면 한 대의 rMBP 가 유지 할 수 있 는 안정 적 인 긴 연결 개 수 는 70, 000 개 정도 이기 때문에 대량의 긴 연결 테스트 가 필요 하 다 면 리 눅 스 서버 를 사용 하 는 것 을 추천 합 니 다.
    Linux
    Mac OS X 와 유사 합 니 다. 먼저 sysctl -a | grep port 보기 net.ipv4.ip_local_port_range 의 값 을 실행 합 니 다. 이 매개 변 수 는 사용자 가 시스템 내 에서 포트 를 사용 할 수 있 는 범 위 를 결정 합 니 다. 저 희 는 수 정 된 하한 선 을 10, 000 으로 권장 합 니 다.
    실행 sysctl -a | grep file 보기 fs.file-max 의 값 입 니 다. 이 매개 변 수 는 사용자 가 시스템 에서 열 수 있 는 최대 파일 개 수 를 결정 합 니 다. 저 희 는 1, 500, 000 으로 수정 하 는 것 을 권장 합 니 다.
    리 눅 스에 서 가상 IP 를 추가 하 는 형식 으로 테스트 의 연결 수 를 늘 릴 수 있다. 우리 의 테스트 사례 에서 우 리 는 한 대의 리 눅 스 서버 에 5 개의 가상 IP 를 추 가 했 는데 모두 6 개의 IP 가 있 고 한 개의 IP 는 50, 000 개의 긴 연결 을 안정 적 으로 유지 할 수 있 기 때문에 한 대의 서버 는 300, 000 개의 안정 적 인 긴 연결 을 생산 할 수 있다.가상 ip 추가 명령 예 는 다음 과 같다. ifconfig eth0:1 192.168.190.151 이 명령 은 네트워크 카드 eth 0 에 가상 ip 192.168.190.151 을 추가 했다.
    테스트 프로그램 실행
    작업 디 렉 터 리 를 MQTT. js 의 루트 디 렉 터 리 로 전환 하고 테스트 를 시작 하 는 클 라 이언 트 명령 을 실행 합 니 다.
    var mqtt = require('./');
    var EventEmitter = require('events').EventEmitter;
    var connectingCount = 0;
    var connectedCount = 0;
    var connectClosedCount = 0;
    var connectErrorCount = 0;
    var tcpConnectedCount = 0;
    
    var cid = 0;
    
    
    var cmdOpts = process.argv.splice(2);
    var clid = cmdOpts[0];
    var localhostIp = cmdOpts[1];
    var serverIp = cmdOpts[2];
    var limit = cmdOpts[3];
    
    console.log(clid);
    console.log(localhostIp);
    console.log(limit);
    
    var doconnectInterval = null;
    
    function addTimer(){
      doconnectInterval = setInterval(doConnect, 10);
    }
    
    function delTimer(){
      clearInterval(doconnectInterval);
    }
    
    addTimer();
    
    setInterval(
      function(){
        if(connectedCount + connectingCount < limit){
          addTimer();
        }
        console.log("src[" + localhostIp
            + "] tcpConnectedCount[" + tcpConnectedCount
                    + "] mqttConnectedCount[" + connectedCount
            + "] mqttConnectingCount[" + connectingCount
            + "] tcpConnectClosedCount[" + connectClosedCount
            + "] tcpConnectErrorCount[" + connectErrorCount + "]");
      },1000
    );
    
    function doConnect() {
    
      for(var i = 0; i < 8192; i++) {
        if( connectedCount + connectingCount >= limit || connectingCount >= 4096){
          delTimer();
          return true;
        }
        mqttTest();
      }
    }
    
    function mqttTest(){
      var client = mqtt.connect('tcp://' + serverIp, {
        clientId: 'mqtt-' + clid + '-' + (cid++),
        clean: false,
        keepalive: 300,
        reconnectPeriod: -1,
        localAddress: localhostIp
      });
    
      client.stream.on('connect', function(){
        tcpConnectedCount++;
      });
      connectingCount++;
      client.isConnected = false;
    
      client.on('connect', function(){
        connectedCount++;
        connectingCount--;
        client.isConnected = true;
        client.subscribe('hello');
      });
    
      client.on('close', function(data) {
        console.log('connection[' + (client.isConnected ? 'connected':'connecting') + '] close: ' + data);
        connectClosedCount++;
        if(client.isConnected){
          connectedCount--;
          tcpConnectedCount--;
        }else{
          connectingCount--
        }
      });
    
      client.on('message', function(topic, payload){
        console.log(topic + '
    ' + payload); }); client.on('error', function(error) { connectErrorCount++; console.log('mqtt error: ' + error); }); };
    'use strict';
    var net = require('net');
    
    /*
      variables port and host can be removed since
      you have all required information in opts object
    */
    function buildBuilder (client, opts) {
      var port, host, localAddress;
      opts.port = opts.port || 1883;
      opts.hostname = opts.hostname || opts.host || 'localhost';
    
      port = opts.port;
      host = opts.hostname;
      localAddress = opts.localAddress;
    
      if (!opts.localAddress) {
        return net.createConnection(port, host);
      }
      return net.createConnection({'port': port, 'host': host, 'localAddress': localAddress});
    }
    
    module.exports = buildBuilder;
    

    좋은 웹페이지 즐겨찾기