Forum OpenACS Q&A: Multiple OpenACS instances in one configuration file

Hello! I have been trying to set up multiple OpenACS instances in a single instance of NaviServer for a while now and whilst researching it I came across several wiki posts that say that it's not possible to do within one configuration file if both of the setups are the same.

Why is it like that? What exactly is meant by that? And how should I proceed?

Annabel

Collapse
Posted by Ann T on
Also, the configurations are the same but I'm trying to use a different database and a different port for the configuration.
Collapse
Posted by Iuri Sampaio on
Ann,

It's possible to run multiple OACS "instances" on a single "installation" of Naviserver.

Nevertheless, you must have one file per instance, respectively.

Furthermore, you have broken your statement about the setup being the same, when you confirmed that they have the database to differeante themselves, not mentioning their IP addresses and ports, which must be different as well.

After you create one config file per each instance, you will need to start every instances accordingly.

Ex.
/usr/local/ns/bin/nsd -t /usr/local/ns/config-instance1.tcl -u projop -g nsadmin

/usr/local/ns/bin/nsd -t /usr/local/ns/config-instance2.tcl -u projop -g nsadmin

...

Now, if your goal is to make one single instance of OACS, having multiples sites, then you must look at side-node-map, within /acs-admin section. It will help you accomplish it.

Did I answered your questions?

Best wishes,
I

Collapse
Posted by Ann T on
I think it did answer my question for now.

Thank you :)

Where are the posts, suggesting that this is not possible? These were probably referring to AOLserver, which has much less flexibility in this regards than NaviServer.

NaviServer supports different means to run multiple servers from one configuration file in one nsd process:

  1. define multiple servers, and run all or some of these
  2. virtual hosting (direct requests to different servers based on the "host" header field)

I stick with the first option here, since this closer to your question. We start with a simple NaviServer configuration file, containing two servers, named "s1" and "s2".

ns_section "ns/servers"
ns_param    s1         "NaviServer Instance 1"
ns_param    s2         "NaviServer Instance 1"

# ----------------------- Server s1 ------------------------------
ns_section "ns/server/s1/adp"
ns_param    map              /*.adp

ns_section "ns/server/s1/modules"
ns_param    nssock        nssock

ns_section "ns/server/s1/module/nssock"
ns_param    address        0.0.0.0
ns_param    port           8000

# ----------------------- Server s2 ------------------------------
ns_section "ns/server/s2/adp"
ns_param    map              /*.adp

ns_section "ns/server/s2/modules"
ns_param    nssock        nssock

ns_section "ns/server/s2/module/nssock"
ns_param    address        0.0.0.0
ns_param    port           8001

When NaviServer is started with the config file e.g. via /usr/local/ns/bin/nsd -u nsadmin -t two-server-config.tcl -f, then the system log will contain the following lines.

...
[12/Apr/2019:12:35:20][39849.70000ee02000][-driver:nssock:0-] Notice: nssock:0: listening on [0.0.0.0]:8001
[12/Apr/2019:12:35:20][39849.70000ee85000][-driver:nssock:0-] Notice: nssock:0: listening on [0.0.0.0]:8000
[12/Apr/2019:12:35:20][39849.70000ed7f000][-conn:s2:0:0-] Notice: thread initialized (0.169447 secs)
[12/Apr/2019:12:35:20][39849.70000ecfc000][-conn:s1:0:0-] Notice: thread initialized (0.169740 secs)
...

This means that nsd is listening on two different ports, directing requests depending on the port to the two server instances (which are here configured identically). One might certainly wish to configure the server instances differently, e.g. to load the NaviServer blueprints from different sources and/or serve pages from different directories, etc. This can be achieved along the following lines:

#
# Load blueprint from the following directory
#
#ns_section "ns/server/s2/tcl"
#ns_param library /var/www/s2/tcl

#
# Serve pages from the following directory
#
#ns_section "ns/server/s2/fastpath"
#ns_param   serverdir /var/www/s2
#ns_param   page

In case, only one of these server should be started, one can use the flag "-server ..." to start e.g. only one of these servers.

/usr/local/ns/bin/nsd -u nsadmin -t two-server-config.tcl -f -server s1

A configuration based on virtual hosting means that the server is listing on one port for connections to many servers, but depending on the "host:" header field, requests are directed to one of the configured servers.

When using multiple NaviServer severs with OpenACS, the configuration files are usually more complex. The sample configuration files contain usually a Tcl variable "server", which is used for various purposes (name of server, name of directory, name of database, name of database user, ...). Certainly, this has to be demangled when someone wants to run multiple OpenACS instances at the same time, and one has to decide, what should be the same and what not.

In case, you want to run multiple OpenACS instances against the same database concurrently, expect problems, since one server instances might change the data in ways the other server instances might not expect (e.g. caching won't work).

Hope, this makes things clearer. So far it is not clear to me what you want to achieve.

-g

Collapse
Posted by Ann T on
Thank you for your reply!

We have set up two virtual servers in one naviserver instance (on different ports), each virtual server running OpenACS with a separate database, and on the second instance, we are getting an error which states that the ns_pg and ns_pg_bind are not available for that server.
-Ann

Collapse
Posted by Ann T on
Additionally, each server has its own set of pools and the logs confirm that they are available.

Also, the first server is operational.

You are sure, the config file loads nsdb for both servers?
Collapse
Posted by Ann T on
Yes.

Furthermore, the server that's first in the ns/servers section will be the one that gets loaded.

```ns_section ns/servers
ns_param s1 s1
ns_param s2 s2```
Then s1 will be loaded, if those lines are switched then s2 gets loaded.

Dear Ann,

I've put together a configuration file for loading two OpenACS instances concurrently (see below)..... and I was able to reproduce the problem you are reporting. The actual problem was located in the PostgreSQL driver "nsdbpg", which defined its specific Tcl commands only when it was loaded the first time.

Please get a fresh version of the nsdbpg modules from bitbucket, recompile and install it, and it will work.

all the best -g

######################################################################
#
# Demo config file for loading two OpenACS instances into one
# NaviServer process. These servers are named "s1" and "s2" below.
#
# This configuration is in no way tuned, so don't use this in your
# production environment.
#
# Since the two servers are distinguished via virtual hosting, Define
# in your etc/hosts file a localhost entry like (names used below):
#
# 127.0.0.1       localhost localhost1 localhost2
#
######################################################################
set address     127.0.0.1  ;# listen on loopback via IPv4
set httpport        8100

set s1_hostname     localhost1
set s2_hostname     localhost2

set s1_serverroot   /usr/local/oacs-5-10/openacs-4/
set s2_serverroot   /usr/local/oacs-5-9/openacs-4/

set homedir     [file dirname [ns_info config]]
set bindir      [file dirname [ns_info nsd]]

set s1_db_name          "oacs-head"
set s2_db_name          "oacs-5-9"

set db_host             localhost
set db_port             ""
set db_user             nsadmin

#---------------------------------------------------------------------
# Set environment variables HOME and LANG. HOME is needed since
# otherwise some programs called via exec might try to write into the
# root home directory.
#
set env(HOME) $homedir
set env(LANG) en_US.UTF-8

#---------------------------------------------------------------------
# Global server parameters
#---------------------------------------------------------------------
ns_section ns/parameters {
    ns_param    serverlog   $s1_serverroot/log/error.log
    ns_param    pidfile     $s1_serverroot/log/nsd.pid
    ns_param    home        $homedir
}

#---------------------------------------------------------------------
# Definition of NaviServer servers 
#---------------------------------------------------------------------
ns_section ns/servers {
    ns_param s1 "Server 1"
    ns_param s2 "Server 2"  
}

#---------------------------------------------------------------------
# Global driver modules
#---------------------------------------------------------------------
ns_section "ns/modules" {
    ns_param nssock ${bindir}/nssock
}

#---------------------------------------------------------------------
# Configuration for plain HTTP interface  -- module nssock
#---------------------------------------------------------------------
ns_section ns/module/nssock {
    ns_param    defaultserver   s1
    ns_param    address     $address
    ns_param    port        $httpport
}
#
# Define, which "host" (as supplied by the "host:" header
# field) accepted over this driver should be associated with
# which server.
#
ns_section ns/module/nssock/servers {
    ns_param s1 localhost
    ns_param s1 $s1_hostname
    ns_param s2 $s2_hostname
}

ns_section ns/threads {
    ns_param    stacksize   1MB
}

#---------------------------------------------------------------------
# Database drivers
#---------------------------------------------------------------------
ns_section "ns/db/drivers" {
    ns_param    postgres       ${bindir}/nsdbpg
}

#---------------------------------------------------------------------
# Server-level configuration
#
#---------------------------------------------------------------------
# Server s1
#---------------------------------------------------------------------
ns_section ns/server/s1 {
    ns_param    minthreads  2   ;# 1; minimal number of connection threads
    ns_param    connsperthread  1000    ;# 10000; number of connections (requests) handled per thread
}

ns_section ns/server/s1/redirects {
    ns_param   404 /shared/404
    ns_param   403 /shared/403
    ns_param   503 /shared/503
    ns_param   500 /shared/500
}

ns_section ns/server/s1/tcl {
    ns_param    library     $s1_serverroot/tcl
}

ns_section "ns/server/s1/fastpath" {
    ns_param    serverdir   $homedir
    ns_param    pagedir     $s1_serverroot/www
}

ns_section ns/server/s1/module/nslog {
    ns_param    file    $s1_serverroot/log/access.log
}

ns_section ns/server/s1/modules {
    ns_param    nslog       nslog
    ns_param    nsdb        nsdb
    ns_param    nsproxy     nsproxy
    set libthread [lindex [lsort [glob -nocomplain $homedir/lib/thread*/libthread*[info sharedlibextension]]] end]
    ns_param    libthread   $libthread
}

#
# DB setup
#
ns_section ns/db/pools {
    ns_param    s1_pool1        "S1 Pool 1"
    ns_param    s1_pool2        "S1 Pool 2"
    ns_param    s1_pool3        "S1 Pool 3"
}

ns_section ns/server/s1/db {
    ns_param    pools              s1_pool1,s1_pool2,s1_pool3
    ns_param    defaultpool        s1_pool1
}

ns_section ns/db/pool/s1_pool1 {
    ns_param    connections        15
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s1_db_name}
    ns_param    user               $db_user
}

ns_section ns/db/pool/s1_pool2 {
    ns_param    connections        5
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s1_db_name}
    ns_param    user               $db_user
}

ns_section ns/db/pool/s1_pool3 {
    ns_param    connections        2
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s1_db_name}
    ns_param    user               $db_user
}

#---------------------------------------------------------------------
# Server s2
#---------------------------------------------------------------------
ns_section ns/server/s2 {
    ns_param    minthreads  2   ;# 1; minimal number of connection threads
    ns_param    connsperthread  1000    ;# 10000; number of connections (requests) handled per thread
}

ns_section ns/server/s2/redirects {
    ns_param   404 /shared/404
    ns_param   403 /shared/403
    ns_param   503 /shared/503
    ns_param   500 /shared/500
}

ns_section ns/server/s2/tcl {
    ns_param    library     $s2_serverroot/tcl
}

ns_section "ns/server/s2/fastpath" {
    ns_param    serverdir   $homedir
    ns_param    pagedir     $s2_serverroot/www
}

ns_section ns/server/s2/module/nslog {
    ns_param    file        $s2_serverroot/log/access.log
}

ns_section ns/server/s2/modules {
    ns_param    nslog       nslog
    ns_param    nsdb        nsdb
    ns_param    nsproxy     nsproxy
    set libthread [lindex [lsort [glob -nocomplain $homedir/lib/thread*/libthread*[info sharedlibextension]]] end]
    ns_param    libthread   $libthread
}

#
# DB setup
#
ns_section ns/db/pools {
    ns_param    s2_pool1        "S2 Pool 1"
    ns_param    s2_pool2        "S2 Pool 2"
    ns_param    s2_pool3        "S2 Pool 3"
}

ns_section ns/server/s2/db {
    ns_param    pools           s2_pool1,s2_pool2,s2_pool3
    ns_param    defaultpool     s2_pool1
}

ns_section ns/db/pool/s2_pool1 {
    ns_param    connections        15
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s2_db_name}
    ns_param    user               $db_user
}

ns_section ns/db/pool/s2_pool2 {
    ns_param    connections        5
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s2_db_name}
    ns_param    user               $db_user
}

ns_section ns/db/pool/s2_pool3 {
    ns_param    connections        2
    ns_param    driver             postgres
    ns_param    datasource         ${db_host}:${db_port}:dbname=${s2_db_name}
    ns_param    user               $db_user
}
#---------------------------------------------------------------------
ns_log notice "nsd.tcl: finished reading config file."
Collapse
Posted by Ann T on
Thank you!

Everything works nicely now.