0

I am using Apache CGI-Script with Nodejs to develop dynamic web page content

Here I am using Node addon C++ (sample.node) as CGI-script. That uses node environment with the help of Addhandler and Action option provided by apache.

In my configuration of the Apache server

    ScriptAlias /cgi-bin/ /var/webapp/server/
    ScriptAlias /cgi-node-bin/ /usr/lib/node_modules/cgi-node

The below-mentioned script name CGI-node.js developed for Node Addon C++ works in Apache Server environment.

    Action cgi-node /cgi-node-bin/cgi-node.js
    AddHandler cgi-node .cgi .node

Script file path and Directory permission like

    <Directory "/usr/lib/node_modules/cgi-node/">
            AllowOverride All
            Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
            Require all granted
    </Directory>

    <Directory "/var/webapp/server/">
            AllowOverride None
            Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
            Require all granted

            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule (.*).cgi$ /cgi-bin/$1.node [P,QSA,L]

            Action cgi-node /cgi-node-bin/cgi-node.js
            AddHandler cgi-node .cgi .node

    </Directory>

Enabled module in apache

apache modules => mpm_event and cgi

apache2ctl -M

Output

 core_module (static)
 so_module (static)
 watchdog_module (static)
 http_module (static)
 log_config_module (static)
 logio_module (static)
 version_module (static)
 unixd_module (static)
 access_compat_module (shared)
 actions_module (shared)
 alias_module (shared)
 auth_basic_module (shared)
 authn_core_module (shared)
 authn_file_module (shared)
 authz_core_module (shared)
 authz_host_module (shared)
 authz_user_module (shared)
 autoindex_module (shared)
 cgi_module (shared)  <---- CGI Module
 deflate_module (shared)
 dir_module (shared)
 env_module (shared)
 filter_module (shared)
 headers_module (shared)
 http2_module (shared)
 lbmethod_byrequests_module (shared)
 mime_module (shared)
 mpm_event_module (shared)  <---- MPM Event Module
 negotiation_module (shared)
 proxy_module (shared)
 proxy_balancer_module (shared)
 proxy_express_module (shared)
 proxy_http_module (shared)
 reqtimeout_module (shared)
 rewrite_module (shared)
 setenvif_module (shared)
 slotmem_shm_module (shared)
 status_module (shared)

Current Apache version

apache2ctl -V

Output

Server version: Apache/2.4.52 (Ubuntu)
Server built:   2021-12-28T20:18:12
Server's Module Magic Number: 20120211:121
Server loaded:  APR 1.7.0, APR-UTIL 1.6.1
Compiled using: APR 1.7.0, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_PROC_PTHREAD_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

Here comes the Buffer memory issue. Every Http request will be handled in the CGI-node.js. Some of the napi module used lots of memory (1GB occupied in buff/cache) and some of the napi modules less memory (relatively 50MB occupied in buff/cache).

Less memory used process freed up automatically after process ends. But near 1GB used process never clearup. Apache kept that buffer memory when checking the status of apache server. These issues are checked and verified by the below command.

I am checking the used memory Linux command cross verifying with apache2 status

free -h

Output

               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.4Gi       7.6Gi       1.4Gi       3.5Gi       9.4Gi
Swap:           16Gi          0B        16Gi

Apache status

systemctl status apache2

Output

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2022-03-05 12:16:18 IST; 2 days ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 782 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
    Process: 32437 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS)
   Main PID: 1003 (apache2)
      Tasks: 143 (limit: 18948)
     Memory: 1.1G
        CPU: 40.631s
     CGroup: /system.slice/apache2.service
             ├─ 1003 /usr/sbin/apache2 -k start
             ├─32441 /usr/sbin/apache2 -k start
             ├─32442 /usr/sbin/apache2 -k start
             ├─40659 node --expose-gc --max-old-space-size=8192 --napi-modules /usr/lib/node_modules/cgi-node/cgi-node.js
             ├─40670 /bin/sh -c "node --expose-gc --max-old-space-size=8192 --napi-modules -e \"process.stdout.write(require('/var/webapp/server/sample.node').getResponse());process.on('exit', () => {   (g>
             ├─40671 node --expose-gc --max-old-space-size=8192 --napi-modules -e "process.stdout.write(require('/var/webapp/server/sample.node').getResponse());process.on('exit', () => {   (global.gc) ? g>
             ├─40680 node --expose-gc --max-old-space-size=8192 --napi-modules /usr/lib/node_modules/cgi-node/cgi-node.js
             ├─40691 /bin/sh -c "node --expose-gc --max-old-space-size=8192 --napi-modules -e \"process.stdout.write(require('/var/webapp/server/samplerun.node').getResponse());process.on('exit', () => {  >
             └─40692 node --expose-gc --max-old-space-size=8192 --napi-modules -e "process.stdout.write(require('/var/webapp/server/samplerun.node').getResponse());process.on('exit', () => {   (global.gc) >

Below command used to remove unused memory (in Linux Ubuntu 20.0.4 LTS server platform)

sudo -i
sync; echo 1 > /proc/sys/vm/drop_caches
sync; echo 2 > /proc/sys/vm/drop_caches
sync; echo 3 > /proc/sys/vm/drop_caches

Checking free memory and status of Apache server

free -h

Output

               total        used        free      shared  buff/cache   available
Mem:            15Gi       4.5Gi       9.0Gi       1.1Gi       1.9Gi       9.6Gi
Swap:           16Gi          0B        16Gi
systemctl status apache2 

Output

Note: using Bash commnd forcefully clear 24.7 MB memory only occupied.

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2022-03-05 12:16:18 IST; 2 days ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 782 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
    Process: 32437 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS)
   Main PID: 1003 (apache2)
      Tasks: 105 (limit: 18948)
     Memory: 24.7M
        CPU: 50.125s
     CGroup: /system.slice/apache2.service
             ├─ 1003 /usr/sbin/apache2 -k start
             ├─32441 /usr/sbin/apache2 -k start
             └─32442 /usr/sbin/apache2 -k start

Mar 05 12:15:47 client11 systemd[1]: Starting The Apache HTTP Server...
Mar 05 12:16:18 client11 apachectl[810]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Mar 05 12:16:18 client11 systemd[1]: Started The Apache HTTP Server.
Mar 06 00:00:07 client11 systemd[1]: Reloading The Apache HTTP Server...
Mar 06 00:00:08 client11 apachectl[22970]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this mess>
Mar 06 00:00:08 client11 systemd[1]: Reloaded The Apache HTTP Server.
Mar 07 00:00:08 client11 systemd[1]: Reloading The Apache HTTP Server...
Mar 07 00:00:09 client11 apachectl[32440]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this mess>
Mar 07 00:00:09 client11 systemd[1]: Reloaded The Apache HTTP Server.

I want to clear buffer/cache storage after exit that program programatically in NodeJs. I know these buffer memory generated from nodejs. After enabling maxBuffer when using the child process.

Restart Apache

Note: Forcefully restart the apache2 8.4 MB memory only occupied.

What steps i need to follow to clear in my Nodejs programming as well in apache server?

● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2022-03-07 17:42:20 IST; 2s ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 46077 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
   Main PID: 46081 (apache2)
      Tasks: 105 (limit: 18948)
     Memory: 8.4M
        CPU: 131ms
     CGroup: /system.slice/apache2.service
             ├─46081 /usr/sbin/apache2 -k start
             ├─46082 /usr/sbin/apache2 -k start
             └─46083 /usr/sbin/apache2 -k start

Mar 07 17:42:20 client11 systemd[1]: Starting The Apache HTTP Server...
Mar 07 17:42:20 client11 apachectl[46080]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this mess>
Mar 07 17:42:20 client11 systemd[1]: Started The Apache HTTP Server.

I try to the following steps via programmatically:

In nodejs --expose-gc offered to clear from gc() function call. It does not work. In my case Main process handle child process.

In my nodejs script handler (cgi-node.js)

#!/usr/bin/env -S node --expose-gc --napi-module

// lots of stuff here
{...}

// In Child process maxBuffer set 
process.stdout._handle.setBlocking(true);
let MAX_BUF_LEN = require('buffer').constants.MAX_LENGTH;
let {stdio, stdout, stderr} = exec(`node --max-old-space-size=8192 --expose-gc --napi-module \
-pe require(...some_module).getResponse(); \
process.on('exit', function (code) { \
  if(global.gc) { \
    global.gc(); \
    console.error('memory cleared...'); \
  } \
}); \
process.stdout.clearLine(); \
process.stdout.cursorTo(0);
`, {
    maxBuffer: MAX_BUF_LEN         // <<--- MAX_BUF_LEN set here
});

process.on('exit', function (code) {
  if(global.gc) {
    global.gc();
    console.error('memory cleared...');
  }
});

// In NodeJs flush the buffer when piping the child process stdout to the main process
stdout.pipe(process.stdout);

// After CGI script pipe the response to the client, and then reset stdout

process.stdout.clearLine();
process.stdout.cursorTo(0);

What will I do to clear buffer storage? Is there a way to clear buffer / Cache memory from apache status and as well Ubuntu operating system via programmatically? Please help me to resolve this issue.

Jeyaprakash
  • 151
  • 3
  • 11

1 Answers1

1

You don't really have a problem here. systemd has a weird way of reporting the memory usage. The buffer cache is not tied to the process that created it - it is shared across all processes and it is automatically freed if a process tries to allocate memory.

Don't worry about it too much. Plus, if your Node.js process exits after each request, this guarantees that it is not tying down any memory.

mmomtchev
  • 2,497
  • 1
  • 8
  • 23