Configuration

Introduction

The N-Squared JSLEE is a multi-component micro-services system. Each component of this system is configured and executed separately, and communicate over a shared message bus. This communication may be within a node or to other nodes, as required.

Due to the underlying Vert.X architecture, a JSLEE instance can be clustered with other JSLEE instances running on separate server instances - either within virtual machines, on bare metal, or within containers This clustering is transparent to application instances.

Basic Execution

The JSLEE is, fundamentally, a Java application. It runs as a standard system process, and can be run using:

java -jar n2jslee.jar config.json

or with the provided script to execute:

cd /opt/nsquared/jslee
export JAVA_OPTS=-Dlogback.configurationFile=/opt/nsquared/jslee/etc/server/logback.xml
bin/n2jslee etc/server/server.json

The above configuration assumes that both logback.xml and server.json exist.

Server Configuration File

The JSLEE server is configured using a JSON file. When running the JSLEE instance it must be run with the path to the configuration file as its main argument, e.g. from the upstart configuration file /etc/init/n2jslee.conf or from the systemd configuration file /etc/systemd/system/n2jslee.service:

/opt/nsquared/jslee/bin/n2jslee /opt/nsquared/jslee/etc/server/server.json

The basic structure of the configuration file is:

{
  "clustered": true,
  "server-name": "prod-auck-n2jslee-01",
  "event-bus.host": "0.0.0.0",
  "event-bus.port": 6049,
  "cluster.config": "/opt/nsquared/jslee/etc/hazelcast/hazelcast.xml",
  "applications": {
    "<application name>": {
      "handler": "<application handler class>",
      "instance-count": "<number of threads>",
      "configuration": {
      }
    }
  }
}

In this configuration structure, there are both node configuration parameters (e.g. server-name) that apply to the entire JSLEE node and common per-application parameters (e.g. instance-count) that may be specified individually per-application and that can be applied to any application.

Each application is listed in the applications section of the configuration file, and each application is given a name as the key to its configuration in this section. The service to execute for this application is specified by the handler configuration option. More than one application can use the same handler (this is useful when different configuration setup is required - e.g. authentication for SMPP endpoints vs authentication for the web interface).

A practical example of an application might be:

{
  "server-name": "jslee-server",
  "cluster.config": "/opt/nsquared/jslee/etc/hazelcast/hazelcast.xml",
  "applications": {
    ...
    "complexAuth": {
      "handler": "nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle",
      "configuration": {
        "rules": [
          {
            "username": "smsc",
            "password": "password"
          }
        ]
      }
    }
    ...

This configuration initialises a local authentication service handler with the name complexAuth using the Java class nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle. Only one thread is given to the service (the default), and its custom configuration provides the recognised authentication rules.

To reference this application, other applications could use any of the following:

See Referencing Applications for further details on application naming.

Dependency Checking

Some services or endpoints may require other services in the JSLEE to be available before they will start or become available to process traffic. Application-level configuration parameters can be used to control how much leeway such services have to perform dependency checks. Each applicaton’s configuration documentation will highlight any dependencies that may prevent startup or traffic-processing ability.

Node Configuration Parameters

The following node-wide configuration parameters are available for the JSLEE:

Field Type Required? Default Description
server-name String No (hostname) The server name for all applications in this JSLEE instance, used for addressing purposes.
clustered Boolean No true Whether the JSLEE should be run clustered (using Hazelcast) or not.
event-bus-host String No 0.0.0.0 The hostname or interface to use for event bus communication with other nodes.
Note: the local loopback device (127.0.0.1) is not permitted to be used as a value here to prevent cross-cluster messaging from silently failing.
event-bus-port Integer No 6049 The port to use for event bus communication with other nodes.
Note: take care to ensure that this value is consistent across all nodes in the JSLEE cluster to prevent the formation of isolated sub-clusters.
vertx-options Object No (Vert.X defaults) A passthrough JSON object which is provided to Vert.X on creation. Options listed in the Vertx Options page may be specified in this section.
cluster.config String No (Hazelcast defaults) The configuration file for the Hazelcast Cluster Manager, such as member nodes and communication mechanisms. This is specified in a separate configuration file, defined as per the Hazelcast configuration requirements.

Common Application Configuration Parameters

For each application on a JSLEE node, the following application-level common configuration options are available:

Field Type Required? Default Description
shutdown-monitor-frequency-ms Integer No 250 The period, in milliseconds, to check if traffic across the service has finished when a shutdown command is issued. The service will internally poll using this period.
shutdown-completion-timeout-ms Integer No 20000 The period, in milliseconds, to wait in total for traffic across the service to finish when a shutdown command is issued. Once this period is reached, or when no responses are outstanding, the service will halt immediately.
dependency-check-startup-retry-ms Integer No 1000 The period, in milliseconds, to wait between each attempt at checking for service and/or endpoint dependency availability at startup. Note that ongoing dependency checking happens in real-time.
dependency-check-startup-attempts Integer No 30 The number of attempts, in total, that will be made to check for a service’s dependencies at startup. Note that this parameter is not used for ongoing dependency checking.

OS and JVM Statistics

The JSLEE captures OS and JVM statistics, publishing these alongside other statistics which are gathered from the operational platform. The purpose of gathering JVM and OS statistics in this manner is to provide a comprehensive single point of access for all system and platform statistics.

However, OS and JVM statistics may be captured in an operational environment by other means. To control whether the JSLEE platform captures these statistics, the following top-level configuration options exist:

Field Description Default
stats.jvm.enable If set to false, all JVM statistics are disabled, even if individual JVM statistics are enabled. true
stats.os.enable If set to false, all OS statistics are disabled, even if individual OS statistics are enabled. true
stats.jvm.memory.enable If set to false, JVM memory statistics are not enabled. May be overriden by stats.jvm.enable. true
stats.os.memory.enable If set to false, OS memory statistics are not enabled. May be overriden by stats.os.enable. true
stats.os.processor.enable If set to false, OS process statistics are not enabled. May be overriden by stats.os.enable. true
stats.os.network.enable If set to false, OS network traffic statistics are not enabled. May be overriden by stats.os.enable. true

Vert.X Options

Vert.X has many internal defaults, some of which are required by the JSLEE to be specified, and which are defined in JSLEE-specific configuration parameters. Other internal options can be specified on a case-by-case basis through the vertx-options configuration section. For example:

{
    "vertx-options": {
        "workerPoolSize": 100,
        "internalBlockingPoolSize":100
    }
}

This example section configures the thread-pool sizing used by Vert.X internally. For a full list of options, see Vert.X documentation on VertxOptions. The most relevant configuration options for the JSLEE are:

Field Description Default
eventLoopPoolSize The maximum number of threads used by the Vert.X event loop pool. This is the standard thread-pool for all verticle processing and these threads are where all JSLEE business rule processing occurs. 2 * number of vCPUs
workerPoolSize The maximum number of threads used by the Vert.X worker pool. Worker threads are used by Vert.X when running blocking code. Standard JSLEE features use no worker threads, so this may be left as default. 20
internalBlockingPoolSize The maximum of threads used by Vert.X internally. Vert.X requires an internal set of workers for blocking actions such as cluster communication and semaphore locking. A sufficient thread count for the anticipated call load is required for this. It is suggested that an internal thread count is set to at least 100 when using EDR processing or the N-Squared OCS. 20

Referencing Applications

Sometimes configuration of one application will need to refer to another application. E.g. a module that requires authentication will need to refer to an application running nz.co.nsquared.slee.Authenticator. To allow for inter-application addressing, the JSLEE incorporates the following addressing scheme:

  1. Every application has a base name, which is their application name as configured as the key in the applications list in the configuration file. To address the application, use their base name. In the example above, the base name is edr.
  2. To access a local application instance only, and never transfer a request over the network to another instance of the JSLEE, even if it were possible to do so, prefix the base name with local:. Most applications support both local and non-local addressing - e.g. an authentication endpoint with the base name auth can be accessed with auth or local:auth.
  3. Where an application supports referencing specific endpoints or objects within an instance, these are accessed using a / separated path to the endpoint. For example, a SMPP application may include a load balance configuration called route-a, with a specific endpoint within that configuration with the IP/port 10.10.30.21:5700. To reference this endpoint, the path /route-a/10.10.30.21:5700 would be used. To reference the load balance configuration only, /route-a (or /route-a/) would be used.

Including Other Files

As some application configuration can become very large and make it difficult to manage the JSLEE configuration file, it is possible to include configuration from another file in the main server configuration using the __include directive.

The __include directive is valid in any level in the configuration file, however as each key must be unique, the __include directive is only valid once per JSON hash.

{
    "auth-app": {
      "handler": "nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle",
      "configuration": {
        "__include": "/etc/n2jslee/auth.json"
      }
    }
}

The format of the file (auth.json) (in this example) must be an object whose keys will be injected into the configuration object (note that the content of this file will overwrite those existing keys in the source file section configuration, so while rules' or grants could be specified in the main file, any definition in the included file would overwrite the main file version):

{
  "rules": [
  ],
  "grants": {
  }
}

You can mix some configuration in the main file, and some in the included file. For example, the grants section may be defined in the main server configuration file, while the rules section may be defined in a separate file.

Files may be included at any level of the configuration, e.g.:

{
    "auth-app": {
      "handler": "nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle",
      "configuration": {
        "__include": "/etc/n2jslee/auth.json",
        "grants": {
          "__include": "/etc/n2jslee/auth_grants.json"
        }
      }
    }
}

In addition, only a certain key of a file may be included by specifying the key after the | character. This is useful if you keep all shared configuration in a single file, e.g.:

{
    "auth-app1": {
      "handler": "nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle",
      "configuration": {
        "rules": {
          "__include": "/etc/n2jslee/auth.json|auth_rules_1"
        }
        "grants": {
          "__include": "/etc/n2jslee/auth_.json|auth_grants"
        }
      }
    }
},
{
    "auth-app2": {
      "handler": "nz.co.nsquared.slee.authentication.LocalConfigurationAuthenticatorVerticle",
      "configuration": {
        "rules": {
          "__include": "/etc/n2jslee/auth.json|auth_rules_2"
        }
        "grants": {
          "__include": "/etc/n2jslee/auth_.json|auth_grants"
        }
      }
    }
}

Verifying Config Files

To verify that configuration files will be read correctly, the checkconfig script can be used. This script is provided as part of the JSLEE distributions, and can be run from the JSLEE bin directory:

cd /opt/nsquared/jslee/bin
./checkconfig < /opt/nsquared/jslee/etc/server/server.json

The checkconfig script will parse the given configuration file and ensure it is syntatically valid for a JSON file (with comments being allowed). It will also process any __include directive, ensuring the file referenced by the directive can be found and processed.

Manual visual verification of the output file is still required. Semantic validation of all the options is not automatically done.