External Component Configuration

In Tigase server version 4.4.x and later a new implementation for connecting external components has been introduced.

It is much simpler to setup and follows the same configuration standards as all other components. It is also much more powerful as a single instance can control many TCP/IP ports and many external components on each port and even allows for multiple connections for the same component. It supports both XEP-0114 and XEP-0225 with protocol auto-detection mechanisms. Protocols are pluggable so in future more protocols can be supported or custom extensions to existing protocols can be added.

The implementation also supports a scripting API and new domains with passwords can be added at run-time using ad-hoc commands. New scripts can be loaded to even further control all connected external components.

Even though it is much simpler to setup and to use it also offers a lot of new functionality and features. Pages in this guide describe in details all the administration aspects of setting up and managing external components.

Basic Configuration Options (External Component)

As for all Tigase components you can load it and configure it via init.properties file described in details in another guide. This document describes how to load the component and set the initial configuration to accept or initiate connections for an external component.

First thing to do is to specify the component class and the component name which must be unique within the Tigase installation. The most commonly name used is ext and the class is tigase.server.ext.ComponentProtocol.

Following 2 lines in the init.properties will load the component during the server startup time:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol

While this would load the component, there are no additional configurations provided to the component would be practically useless. It is possible to add necessary parameters (external domains, passwords) during run-time via ad-hoc commands. It is generally a good practice to provide some initial parameters in the configuration file too.

There are two additional properties used for setting initial configuration for external components connections: --external and --bind-ext-hostnames.

These two properties are very well described on the online documentation, therefore I will focus on practical and working examples here.

Simple Case

The most common scenario is to connect an external component which works for a specific given domain to the main server. The component authenticates with a defined password and the external component connects to a TCP/IP port the server listens on.

For example let’s say our server works for a virtual domain: devel.tigase.org. We want it to listen on port 5270 for incoming connections from an external component working for a domain: muc.devel.tigase.org. The authentication password for the domain is muc-secret.

For such a scenario we need 3 lines in the init.properties file:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:muc-secret:listen:5270

More External Components/Domains

Suppose you want to connect more than one external component. Let’s say you want to connect PubSub and MSN components to Tigase server as well.

In that case you don’t have to open another port on the server, all the components can connect to the same port. Of course each of the components connect for a different domain and probably should use a different password.

Let’s say then that we want Tigase server accept two more domains with corresponding passwords: (pubsub.devel.tigase.org:pubsub_pass) and (msn.devel.tigase.org:msn_pass). Your configuration properties should look like this:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:muc-secret:listen:5270, \
    pubsub.devel.tigase.org:pubsub_pass, \
    msn.devel.tigase.org:msn_pass

Please note, the --external property with value should be written in a single line. The above example has split the line for readability.

More TCP/IP Ports

You can make Tigase listen on more than one TCP/IP port for incoming external component connections. Please be aware that there is no way, currently to bind an external component to a particular port. If Tigase listens on two or more ports it accepts any external component on any of the ports. Therefore there is no practical reason for opening more than one port.

However, if for some reason you need Tigase to listen on more ports then this is an example configuration:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:muc-secret:listen:5270, \
   pubsub.devel.tigase.org:pubsub_pass:listen:5271, \
   msn.devel.tigase.org:msn_pass:listen:5272

Please note, the --external property with value should be written in a single line. The above example has split the line for readability.

These settings set three TCP/IP ports to listen on: 5270, 5271 and 5272. They also specify 3 different external domains with passwords which are accepted by Tigase. Even though each port is specified with conjunction with a domain they are not bound together in any way. Any of specified domains can connect through any of specified ports.

Outgoing Connections

Tigase server can not only accept connections from external components, it can also open connections to external components.

To make Tigase connect to an external component you have to change 'listen' parameter to 'connect' and of course you have to tell where to connect - the address of the external component:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = devel.tigase.org:muc-secret:connect:5270:muc.devel.tigase.org

Assuming the MUC component listens on the port '5270' at the DNS address: 'muc.devel.tigase.org' Tigase will connect to the component.

You can of course set as many as you need external components to which you want Tigase to connect to:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = devel.tigase.org:mucsecret:connect:5270:muc.devel.tigase.org, \
  devel.tigase.org:pubsub_pass:connect:5271:pubsub.devel.tigase.org, \
  devel.tigase.org:msn_pass:connect:5272:msn.devel.tigase.org

If external components run on a separate machines you can use the same port number for each of them.

Specifying Protocol

One of the last parameters you can set for the external component/domain is a protocol which should be used for the connection. At the moment the Tigase server supports two protocols defined in XEP-0114 and XEP-0225 and possibly further protocols.

You don’t have to specify a protocol if you setup a connection in 'listen' mode as the server automatically detects a protocol which is used in incoming connections.

You can specify the protocol which is used for outgoing connections but you have to add one more parameters to the connection string.

There are two possibilities:

  1. 'accept' which is an identifier for protocol defined in XEP-0114 (and is default if you do not specify anything)
  2. 'client' which is identifier for protocol defined in XEP-0225 and is based on the client-to-server protocol.

An example configuration with protocol specified:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = devel.tigase.org:mucsecret:connect:5270:muc.devel.tigase.org:accept, \
  devel.tigase.org:pubsub_pass:connect:5270:pubsub.devel.tigase.org:client

It defines two outgoing connections to external protocols, the first uses the XEP-0114 protocol and the second uses the XEP-0225 protocol.

Load Balancer Plugin

With the penultimate option you can set for external component connections is load balancer class.

The load balancer plugin is used if you have multiple connections for the same component (external domain name) and you want to spread the load over all connections. Perhaps you have an installation with huge number of MUC rooms and you want to spread the load over all MUC instances.

An example configuration with load balancer plugin specified:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:mucsecret:listen:5270:devel.tigase.org:accept:ReceiverBareJidLB, \
  pubsub.devel.tigase.org:pubsub_pass:listen:5270:devel.tigase.org:accept:SenderBareJidLB

It defines two listeners for external component with different load balancer plugins. The first load-balance traffic by a packet destination BareJID, which makes sense for MUC component. This way each MUC instance handles a different set of rooms which allows for a good load distribution.

For the PubSub component we use a different load balancer plugin which distributes load by the sender BareJID instead. This is because for the PubSub destination BareJID is always the same so we cannot use it to distribute the load.

Either the ReceiverBareJidLB or SenderBareJidLB are class names from package: tigase.server.ext.lb however, you can use any class name as a plugin, you just have to provide a full class name and the class name must implement LoadBalancerIfc interface.

Encrypting connection

With the last option you can set type of the socket connection.

Following options are available: . plain - will create a plain socket (accepting unencrypted or TLS connections) . tls - will create a plain type socket, which enforces performing StartTLS . ssl - will create an SSL socket (only accepting SSL connections)

An example configuration with socket type specified:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:mucsecret:listen:5270:devel.tigase.org:accept:ReceiverBareJidLB:plain, \
  pubsub.devel.tigase.org:pubsub_pass:listen:5270:devel.tigase.org:accept:SenderBareJidLB:ssl

for the MUC component it will be possible to establish plain socket connection (with possibility to perform StartTLS) and for the PubSub component an encrypted, SSL connection will be required.

Tigase as an External Component

There are cases when you want to deploy one or more Tigase components separately from the main server, or perhaps you want to run some Tigase components connecting to a different XMPP server, or perhaps you work on a component and you do not want to restart the main server every time you make a change.

There is a way to run the Tigase server in "external component mode". In fact you can run any of Tigase’s components as an external component and connect them to the main XMPP server either via XEP-0114 or XEP-0225 connection.

Let’s look at the examples…​

A Simple Case - MUC as an External Component

A few assumptions:

  1. We want to run a MUC component for a domain: 'muc.devel.tigase.org' and password 'muc-pass'
  2. The main server works at an address: devel.tigase.org and for the same virtual domain
  3. We want to connect to the server using XEP-0114 protocol and port '5270'.

There is a special configuration type for this case which simplifies setting needed to run Tigase as an external component:

config-type=--gen-config-comp.

This generates a configuration for Tigase with only one component loaded by default - the component used for external component connection. If you use this configuration type, your init.properties file may look like this:

config-type = --gen-config-comp
--debug = server
--user-db = derby
--admins = admin@devel.tigase.org
--user-db-uri = jdbc:derby:/tigasedb
--virt-hosts = devel.tigase.org
--comp-name-1 = muc
--comp-class-1 = tigase.muc.MUCComponent
--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:accept

Please note, you do not need lines:

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol

as the

--gen-config-comp

automatically includes them.

More Components

Suppose you want to run more than one component as an external components within one Tigase instance. Let’s add another - PubSub component to the configuration above and see how to set it up.

The most straightforward way is just to add another component and another connection to the main server for the component domain:

config-type = --gen-config-comp
--debug = server
--user-db = derby
--admins = admin@devel.tigase.org
--user-db-uri = jdbc:derby:/tigasedb
--virt-hosts = devel.tigase.org
--comp-name-1 = muc
--comp-class-1 = tigase.muc.MUCComponent
--comp-name-2 = pubsub
--comp-class-2 = tigase.pubsub.PubSubComponent
--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:accept, \
  pubsub.devel.tigase.org:pubsub-pass:connect:5270:devel.tigase.org:accept

Please note however that we are opening two connections to the same server. This can waste resources and overcomplicate the system. For example, what if we want to run even more components? Opening a separate connection for each component is a tad overkill.

In fact there is a way to reuse the same connection for all component domains running as an external component. The property '--bind-ext-hostnames' contains a comma separated list of all hostnames (external domains) which should reuse the existing connection.

There is one catch however. Since you are reusing connections (hostname binding is defined in XEP-0225 only), you must use this protocol for the functionality.

Here is an example configuration with a single connection over the XEP-0225 protocol used by both external domains:

config-type = --gen-config-comp
--debug = server
--user-db = derby
--admins = admin@devel.tigase.org
--user-db-uri = jdbc:derby:/tigasedb
--virt-hosts = devel.tigase.org
--comp-name-1 = muc
--comp-class-1 = tigase.muc.MUCComponent
--comp-name-2 = pubsub
--comp-class-2 = tigase.pubsub.PubSubComponent
--external = muc.devel.tigase.org:muc-pass:connect:5270:devel.tigase.org:client
--bind-ext-hostnames=pubsub.devel.tigase.org

Load Balancing External Components in Cluster Mode

This document describes how to load balance any external components using Tigase XMPP Server and how to make Tigase’s components work as external components in a cluster mode.

Please note, all configuration options described here apply to Tigase XMPP Server version 5.1.0 or later.

These are actually 2 separate topics:

  1. One is to distribute load over many instances of a single component to handle larger traffic, or perhaps for high availability.
  2. The second is to make Tigase’s components work as an external component and make it work in a cluster mode, even if the component itself does not support cluster mode.

Here are step by step instructions and configuration examples teaching how to achieve both goals.

Load Balancing External Component

The first, and most simple scenario is to connect multiple instances of an external component to a single Tigase XMPP Server to distribute load.

There are at least 2 reasons why this would be an optimal solution: one would be to spread load over more instances/machines and the second is to improve reliability in case one component fails the other one can take over the work.

So here is a simple picture showing the use case.

ExternalCompClustering002

We have a single machine running Tigase XMPP Server and 2 instances of the MUC component connecting to Tigase.

The server configuration

config-type = --gen-config-def
--user-db = mysql
--admins = admin@devel.tigase.org
--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase
--virt-hosts = devel.tigase.org

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.devel.tigase.org:muc-secret:listen:\
       5270:devel.tigase.org:accept:ReceiverBareJidLB

And configuration for both instances of the MUC component (identical for both of them):

config-type = --gen-config-comp
--user-db = mysql
--admins = admin@devel.tigase.org
--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase
--virt-hosts = devel.tigase.org

--comp-name-1 = muc
--comp-class-1 = tigase.muc.MUCComponent
--external = muc.devel.tigase.org:muc-secret:connect:\
       5270:devel.tigase.org:accept

For those familiar with Tigase’s configuration, this should be pretty basic. The difference is one small element in the server configuration. At the end of the component connection we have ReceiverBareJidLB.

This is the load balancing plugin class. Load balancing plugin decides how the traffic is distributed among different component connections that is different component instances. For the MUC component it makes sense to distribute the traffic based on the receiver bare JID because this is the MUC room address. This way we just distribute MUC rooms and traffic over different MUC component instances.

This distribution strategy does not always work for all possible components however. For transports for example this would not work at all. A better way to spread load for transports would be based on the source bare JID. And it is possible if you use plugin with class name: SenderBareJidLB.

This are two basic load distribution strategies available now. For some use cases none of them is good enough. If you have PubSub, then you probably want to distribute load based on the PubSub node. There is no plugin for that yet but it is easy enough to write one and put the class name in configuration.

External Component and Cluster

If you want to use Tigase’s component in a cluster mode which does not have clustering implemented yet there is a way to make it kind of cluster-able. In the previous section we connected many MUC components to a single Tigase server. Now we want to connect a single MUC component to many Tigase servers (or many Tigase cluster nodes).

Let’s say we have Tigase XMPP Server working for domain: xmpp-test.org and the server is installed on three cluster nodes: red.xmpp-test.org, green.xmpp-test.org and blue.xmpp-test.org.

ExternalCompClustering003 0

We want to make it possible to connect the MUC component to all nodes, so here is configuration for the server (for each node is the same):

config-type=--gen-config-def
--admins=admin@xmpp-test.org
--virt-hosts = xmpp-test.org

--cluster-mode = true
--cluster-nodes=red.xmpp-test.org,green.xmpp-test.org,blue.xmpp-test.org

--auth-db=tigase-auth
--user-db=mysql
--user-db-uri=jdbc:mysql://localhost/db?user=tigase&password=tigase

--comp-name-1 = ext
--comp-class-1 = tigase.server.ext.ComponentProtocol
--external = muc.xmpp-test.org:muc-secret:listen:5270:\
       xmpp-test.org:accept:ReceiverBareJidLB

As you can see there is nothing special here. The most interesting part comes on the MUC side.

config-type = --gen-config-comp
--user-db = mysql
--admins = admin@xmpp-test.orgg
--user-db-uri = jdbc:mysql://localhost/db?user=tigase&password=tigase

--virt-hosts = xmpp-test.org

--comp-name-1 = muc
--comp-class-1 = tigase.muc.MUCComponent
--external = muc.xmpp-test.org:muc-secret:connect:5270:xmpp-test.org;blue.xmpp-test.org;green.xmpp-test.org,red.xmpp-test.org:accept

As you can see remote host name is not a simple domain but a character string with a few comma separated parts. The first part is our remote domain and the rest are addresses of the host to connect to. This can be a list of domain names or IP addresses.

Of course it is possible to connect multiple external component to all cluster nodes, this way the whole installation would be really working in the cluster and also load balanced.