From 366a379ca2527612b60cc6a57d2572b7c07421d7 Mon Sep 17 00:00:00 2001 From: Chris Jean Date: Thu, 23 Feb 2023 01:01:21 -0600 Subject: [PATCH] Testing: Exporatory code. Do not merge. Testing out workers sending their details to the parent to allow the parent to more intelligently distribute work while minimizing the number of idle workers. Setting the foundation for a smarter way to recycle workers that is more reliable and doesn't lose pending URL checks on the recycled worker. Added a port 7802 listener that dumps stats about Jetmon and its workers. --- docker/.env-sample | 3 +++ docker/docker-compose.yml | 17 +++++++++++++---- docker/php-apache/html/.htaccess | 8 ++++++++ docker/php-apache/html/index.php | 5 +++++ lib/httpcheck.js | 27 ++++++++++++++++++++++++++- lib/jetmon.js | 31 +++++++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 docker/php-apache/html/.htaccess create mode 100644 docker/php-apache/html/index.php diff --git a/docker/.env-sample b/docker/.env-sample index ec90dce..831cf63 100644 --- a/docker/.env-sample +++ b/docker/.env-sample @@ -7,6 +7,9 @@ MYSQLDB_DOCKER_PORT=3306 JETMON_LOCAL_PORT=7800 JETMON_DOCKER_PORT=7800 +JETMON_STATUS_LOCAL_PORT=7802 +JETMON_STATUS_DOCKER_PORT=7802 + WPCOM_JETMON_AUTH_TOKEN=change_me VERIFLIER_LOCAL_PORT=7801 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 1ca5222..effd6f6 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,6 +1,6 @@ version: '3.8' -services: +services: mysqldb: image: mysql:5.7 restart: unless-stopped @@ -15,7 +15,7 @@ services: - db:/var/lib/mysql jetmon: hostname: docker.jetmon.dev.com - build: + build: context: ../ dockerfile: docker/Dockerfile_jetmon env_file: @@ -35,10 +35,11 @@ services: - WPCOM_JETMON_AUTH_TOKEN=$WPCOM_JETMON_AUTH_TOKEN ports: - $JETMON_LOCAL_PORT:$JETMON_DOCKER_PORT + - $JETMON_STATUS_LOCAL_PORT:$JETMON_STATUS_DOCKER_PORT depends_on: - mysqldb veriflier: - build: + build: context: ../ dockerfile: docker/Dockerfile_veriflier volumes: @@ -49,6 +50,14 @@ services: - VERIFLIER_AUTH_TOKEN=$VERIFLIER_AUTH_TOKEN - VERIFLIER_PORT=$VERIFLIER_DOCKER_PORT - JETMON_PORT=$JETMON_DOCKER_PORT + php-apache: + image: php:apache + hostname: test.local + volumes: + - ./php-apache/html:/var/www/html + command: > + bash -c "a2enmod rewrite + && apache2-foreground" -volumes: +volumes: db: diff --git a/docker/php-apache/html/.htaccess b/docker/php-apache/html/.htaccess new file mode 100644 index 0000000..7e25e32 --- /dev/null +++ b/docker/php-apache/html/.htaccess @@ -0,0 +1,8 @@ + +RewriteEngine On +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . /index.php [L] + diff --git a/docker/php-apache/html/index.php b/docker/php-apache/html/index.php new file mode 100644 index 0000000..b8ae064 --- /dev/null +++ b/docker/php-apache/html/index.php @@ -0,0 +1,5 @@ +OK diff --git a/lib/httpcheck.js b/lib/httpcheck.js index 7820801..260c015 100644 --- a/lib/httpcheck.js +++ b/lib/httpcheck.js @@ -29,10 +29,12 @@ var config = require( './config' ); config.load(); var arrCheck = []; -var running = false; +var running = false; var askedForWork = false; var suicideSignal = false; var pointer = 0; +var activeChecks = 0; +var createdTime = Date.now(); var workerTotals = {}; workerTotals[SITE_DOWN] = 0; @@ -73,6 +75,7 @@ var HttpChecker = { if ( pointerCurrentMax > arrCheck.length ) pointerCurrentMax = arrCheck.length; for ( ; pointer < pointerCurrentMax ; pointer++ ) { + activeChecks++; _watcher.http_check( arrCheck[ pointer ].monitor_url, DEFAULT_HTTP_PORT, pointer, HttpChecker.processResultsCallback ); } } @@ -82,6 +85,8 @@ var HttpChecker = { }, processResultsCallback: function( serverArrayIndex, rtt, http_code ) { + activeChecks--; + var server = arrCheck[ serverArrayIndex ]; server.processed = true; server.lastCheck = new Date().valueOf(); // we use set the value to the milliseconds value @@ -118,6 +123,7 @@ var HttpChecker = { workerTotals[server.site_status]++; if ( pointer < arrCheck.length ) { + activeChecks++; _watcher.http_check( arrCheck[ pointer ].monitor_url, DEFAULT_HTTP_PORT, pointer, HttpChecker.processResultsCallback ); pointer++; } else { @@ -160,6 +166,10 @@ var HttpChecker = { } }, + getAge: function() { + return Date.now() - createdTime; + } + }; process.on( 'message', function( msg ) { @@ -211,3 +221,18 @@ setTimeout( function() { } }, 2000 ); +setInterval( function() { + var message = { + msgtype: 'stats', + worker_pid: process.pid, + stats: { + queueLength: arrCheck.length, + pointer: pointer, + activeChecks: activeChecks, + memoryUsage: process.memoryUsage().rss + } + }; + + process.send( message ); +}, 1000 ); + diff --git a/lib/jetmon.js b/lib/jetmon.js index d01a05b..62091f8 100755 --- a/lib/jetmon.js +++ b/lib/jetmon.js @@ -16,6 +16,8 @@ const NUM_SSL_SERVERS = 4; const JETMON_CHECK = 1; const VERIFLIER_CHECK = 2; +const STATUS_PORT = 7802; + const SECONDS = 1000; const MINUTES = 60 * SECONDS; const HOURS = 60 * MINUTES; @@ -59,6 +61,7 @@ var db_mysql = require( './database' ); var wpcom = require( './wpcom' ); var comms = require( './comms' ); var cluster = require( 'cluster' ); +var http = require( 'http' ); var gCountSuccess = 0; var gCountError = 0; @@ -69,6 +72,7 @@ var arrObjects = []; var localRetries = []; var freeWorkers = []; var arrWorkers = []; +var workerStats = {}; var gettingSites = false; var endOfRound = false; @@ -135,6 +139,9 @@ function deleteWorker( pid ) { if ( ( undefined != arrWorkers[count] ) && ( arrWorkers[count].pid == pid ) ) { arrWorkers.splice( count, 1 ); + if ( workerStats[pid] ) { + delete( workerStats[pid] ); + } break; } } @@ -362,6 +369,11 @@ function workerMsgCallback( msg ) { // we have exhausted our local check limit, ask the verifliers to confirm host_check_request( msg.server ); } + case 'stats': + if ( msg.stats ) { + workerStats[msg.worker_pid] = msg.stats; + } + break; default: } } @@ -536,6 +548,25 @@ for ( var i = 0; i < NUM_SSL_SERVERS; i++ ) { ssl_server.on( 'message', sslWorkerCallBack ); } +http.createServer( function ( request, response ) { + response.writeHead( 200, {'Content-Type': 'application/json'} ); + + var status = { + 'sites per second': sitesCount, + 'sites in queue': arrObjects.length, + 'working': ( arrWorkers.length - freeWorkers.length ), + 'waiting': freeWorkers.length, + 'error': gCountError, + 'offline': gCountOffline, + 'total': gCountSuccess, + 'workers': workerStats + }; + + response.write( JSON.stringify( status ) ); + + response.end(); +} ).listen( STATUS_PORT ); + // set a repeating 'tick' to perform clean-up and retries allocation setInterval( processQueuedRetries, SECONDS * 5 );