7. 配置

当用户第一次尝试设置客户端时,他遇到了 2 个配置文件:/etc 文件夹中的 tigase.confconfig.tdsl。以下是所有这些文件的简要说明,在其他部分中,您可以了解配置服务器所需的所有详细信息。

  1. config.tdsl 文件是一个简单的文本文件,其服务器参数格式为:key = value。当 XML 配置文件丢失时,Tigase 服务器读取 config.tdsl 文件并使用在那里找到的参数作为生成 XML 文件的默认值。因此,如果您更改 config.tdsl 文件,您通常必须停止服务器,删除 XML 文件并重新启动服务器。config.tdsl 中的所有设置都被读取并应用于 XML 配置。属性文件易于阅读且修改起来非常安全。目前这是推荐的更改服务器配置的方法。

  2. tigase.conf 是 Tigase 服务器启动配置。它实际上不被服务器本身使用。它包含操作系统设置和环境参数以正确运行 Java 虚拟机。它仅在带有 Bash shell 的类 unix 系统上有用。如果您在 MS Windows 系统上运行服务器,则需使用 tigase.batwrapper.conf 文件。 tigase.conf 文件由 scripts/tigase.sh shell 脚本读取和加载,该脚本还可以扫描操作系统环境以查找 Java VM 和其他所需工具。

7.1. DSL 文件格式

在以前的 Tigase XMPP 服务器版本中,配置存储在基于配置文件的属性中。从 Tigase XMPP Server 8.0.0 版本开始,将需要使用新的基于 DSL 的配置文件格式。这种文件格式的灵感来自 Groovy 语言语法和 Tigase XMPP 服务器的新核心功能 - Tigase 内核框架 。

7.1.1. 为什么是新格式?

在属性配置格式中,每一行都包含键和值以及存储值类型的可选定义:

c2s/ports[i]=5222,5223

其中 c2s/ports 是属性名称,[i] 定义了值的类型是整数数组,5222,5223 是逗号分隔的值列表。

这种格式有效,但实际上 c2s/ports 不是您配置的属性的名称,而是后来在 / char 上拆分为由名称路径定义的部分的键,该名称在最后一部分中。从这您可以看到它是基于域的属性设置。

除了这个多部分键之外,我们还使用了以 -- 开头的属性,这些属性是应用程序的每个部分都可以访问的全局属性,即:添加新组件并设置一些您需要编写的属性:

--comp-name-1=pubsub
--comp-class-1=tigase.pubsub.PubSubComponent
pubsub/test[B]=true
pubsub/pubsub-repo-url="jdbc:XXXX:XXXX/db_name"

这会导致错误,例如为相同数量的组件重复定义名称和类或在一个配置文件的其他位置重新定义属性值 - 特别是在配置很大的情况下。

在这种配置结构中,很难分辨特定组件的配置在哪里,或者这个安装使用什么数据库。这可以在整个文件中定义。

在这个版本中,我们引入了 Tigase 内核框架,它允许在配置文件中配置 bean,甚至定义从外部 jars 加载的新 bean 的使用,这些 jars 可以修改 Tigase 组件的行为。这将使配置文件更加复杂,困难且可读性更差。

7.1.2. 什么是 DSL?

DSL 代表特定领域的语言 - 在这种情况下,语言是为存储配置而创建的。

现在我们使用基于域的配置,这意味着我们的配置文件不是平面键=值存储,而是定义对象,其属性和分配值。

为了更好地说明它,让我们从一个简单的例子开始。在属性文件中,为了配置名为 pubsub 的 PubSub 组件,您将使用以下属性:

--comp-name-1=pubsub
--comp-class-1=tigase.pubsub.PubSubComponent
pubsub/test[B]=true

在基于 DSL 的配置中,这将被以下块替换

pubsub (class: tigase.pubsub.PubSubComponent) {
    # comment
    test = true
}

在其中我们定义名为 pubsub 的 bean 并将其在 () 块中的类设置为 tigase.pubsub.PubSubComponent。我们还使用 {} 字符之间的块来定义与 bean 相关的属性。这意味着此属性将仅传递给 Tigase PubSub 组件的此实例,与之前我们需要添加前缀的位置相同。 \# 之后的条目是注释,要传递 # 你需要将包含它的整个部分包裹在 '' 中,即 'test#242'

警告

如果分配给属性的字符串值包含来自以下列表 =:,[]#+-*/ 的任何字符,则需要将其包在 '' 中。

7.1.3. 为什么是 DSL?

与旧的配置系统相比,DSL 配置格式有许多优势。组件的所有配置都在一个块中相关,因此它们不会分布在多个不同的行中。不需要长属性名称,不再需要为多个值调用一长串设置。为环境变量提供支持。不再需要转义某些字符,使设置一目了然。可以使用基本计算来设置值,例如 100 * 200 * 2 而不是 40000。不再需要参数类型值,不再需要 [i]、[S]、[B] 等。逗号分隔的值现在可以简化为列表,单独的条目可以位于多行中。

尽管格式可能看起来更复杂,像一段 java 代码,但格式是一致的并且可读性更强。在对 DSL 格式进行了一些体验之后,您会发现它远比看起来更直观和易于使用。当然,如果有任何真正的混淆,Tigase 可以使用以下命令自动将旧样式属性文件转换为 DSL 格式:

./scripts/tigase.sh upgrade-config etc/tigase.conf

设置属性

要设置属性,您只需编写属性名称,后跟 = 和要设置的值。这些总是在您要设置的配置属性的 bean 上下文中完成。

test=true

也可以通过将属性放置在任何上下文之外的主上下文中设置属性。这设置了哪个值的属性可以被任何 bean 访问。

设置全局属性

就像在属性文件中一样,仍然可以在没有任何上下文或全局范围内的任何其他属性的情况下使用以 -- 开头的属性名称。格式与设置属性的情况相同,但它们是没有定义范围(在全局范围内)。此属性是全局的,任何 bean 都可以访问,但在 JVM 中也设置为系统属性。

定义 bean

您可以使用以下格式配置 bean:

beanName (class: className, active: activeValue, exportable: exportableValue) {
    # scope of bean properties
}

其中 beanName 是您要配置 bean 的名称。 beanName 必须包在 '' 中,如果 beanName 包含像 =:,[]#+-*/ 这样的字符并且被推荐,如果 beanName 只是数字。

(`and`) 之间的块内你可以定义:

  • class 将被用作 bean,在上面的示例中,我们将 class 设置为 className(默认值:如果您尝试在 Tigase 框架中配置默认类的名称下配置 bean,则将使用此分配的类。在其他情况下,您需要传递类的名称以用作 bean)

  • active (布尔值)是否希望 bean 处于活动状态(不加载 active 设置为 false 的 bean)。(默认:true)

  • exportable (boolean) 定义这个 bean 是否应该被导出并且可用于内部范围以内的 bean。这是大多数情况下的高级选项,建议在配置中忽略此字段。(默认:false)

不仅 beanName 之间和 () 之间的空格是可选的,而且 () 之间和 {} 之间的块也是可选的。建议将 bean 的属性放置在带有缩进的单独行中,并将第一个属性放置在新行中。

重要

() 块的使用非常重要。当在配置中使用这个块时,它会自动将 bean 定义的 active 属性设置为 true。这是因为“active”的默认值为“true”。

如果您在配置中忽略它,您将设置 bean 配置,但它可能保持 inactive。在这种状态下,bean 不会被加载,因此 Tigase XMPP 服务器不会使用它。

配置bean

如果您知道 bean 已定义并且您不想更改它的活动或类,那么您可以通过以下方式传递属性来配置 bean:

beanName {
    # scope of bean properties
    test = true
}

其中 beanName 是要配置的 bean 的名称,而 test 是要在这个 bean 中设置为 true 的属性的名称。

值的格式

在基于属性的配置文件中,每个属性都被定义为一个字符串,并且只有通过定义预期的格式,它才能正确转换为预期的值。在 DSL 中,可以通过两种方式设置值:

作为一个对象

使用这种格式,您将列表设置为列表,并且将整数设置为整数。

值的格式

类型

描述

字符串

把它包在 '' 中,也就是将 test 设置为使用 'test' 的字符串

整数

也就是,把值设置为 543 使用 543

长整型

输入数值并在其后面加上 L,即设置 23645434 为长整型使用 23645434L

浮点型

输入数值并在其后面加上 f,即将 231.342 设置为 231.342f

布尔值

要设置值,只需使用 truefalse

列表

列表可以有多种类型,为了简单起见,我们决定使用逗号分隔的值列表,以正确的格式放在 [] 中。

  • 字符串列表 - [ 'alfa', 'beta', 'gamma' ]

  • 整型列表 - [ 1, 2, 3, 4]

如果需要,您可以将其写成多行:

[
    'alfa'
    'beta'
    'gamma'
]

映射

映射可以写成属性块并放在 {} 中。这种映射格式与用于将配置传递给 bean 属性的格式相同。键和值可以写在单独的行中 (推荐)

{
    test = true
    ssl = false
    ssl-certificate = '/test/cert.pem'
    another-map = {
        key = 'value'
    }
}

或单行 (不需要用空格分开)

{ test = true, ssl = false, ssl-certificate = '/test/cert.pem' }
作为纯字符串

与基于属性的配置非常相似,实际上值以相同的格式传递,然后通过检查 bean 预期的类型将其转换为正确的类型。(不建议)

类型

类型

描述

字符串

只是放入值,即设置 testtest

整数

也就是,把值设置为 543 使用 543

长整型

把值放入,即设置 23645434 为长整型使用 23645434

浮点型

放入数值,即设置 231.342231.342

布尔值

要设置值,只需使用 truefalse

列表

列表需要写为用逗号分隔的值列表,即 test,abc,efg1,2,3

映射

不可能

使用系统属性和环境变量中的值

现在可以使用 system propertiesenvironment variables 并将它们分配给 bean 属性。为此,我们添加了可在 DSL 中使用的函数,这些函数将返回以下值:

系统属性

prop('property-name')prop('property-name','default value')

环境变量

env('variable-name')

将系统属性和环境变量的值设置为 bean ``user`` 的示例。

user {
  name = env('USER')
  home = prop('user.home')
  paths = [ prop('user.home'), prop('user.dir') ]
}

警告

对于列表接受的属性,不允许使用带有逗号分隔的变量/属性值,例如放在在 [] 中的 value1,value2,即 property = [ env('some-variable') ]。它需要按以下方式设置 property = env('some-variable')

计算值

通过 DSL 配置格式,我们引入了对属性的可计算值的支持。现在可以把值设置为作为计算结果的值,即字符串或非常简单的数学表达式的连接。我们目前仅支持以下数学运算:

  • 加法

  • 减法

  • 乘法

  • 除法

设置环境变量相关路径和计算超时的示例。

bean {
  # setting path to `some-subdirectory` of user home directory
  path = prop('user.home') + '/some-subdirectory/'

  # setting timeout to 5 minutes (setting value in milliseconds)
  timeout = 5L * 60 * 1000
  # previously it would need to be configured in following way:
  # timeout = 300000L
}

警告

对于列表所接受的属性,不允许使用带有逗号分隔值的计算值来设置值,例如放在 [] 中的``value1,value2``,即 property = [ env('some-variable') + ',other-value' ]。它需要按以下方式设置 property = env('some-variable') + ',other-value'

Period / Duration 值

一些配置选项允许控制特定时期或特定持续时间内的任务执行。 DSL 文件格式接受表示特定时间量的字符串,它遵循 Java 的本地结构(请参阅: PeriodDuration 详细解释).

  • Duration 接受的格式是基于 ISO-8601的 持续时间格式 PnDTnHnMn.nS,其中天数被认为是 24 小时,例如:

    • PT20.345S - 20.345 秒

    • PT15M - 15 分钟(一分钟为 60 秒)

    • PT10H - 10 小时(其中 1 小时为 3600 秒)

    • P2D - 2 天(一天是 24 小时或 86400 秒)

    • P2DT3H4M - 2天,3小时,4分钟

  • Period 格式是基于 ISO-8601 的周期格式 PnYnMnD 和 PnW,例如,以下是有效输入:

    • P2Y - 2 年

    • P3M - 3 月

    • P4W - 4周

    • P5D - 5天

    • P1Y2M3D - 1年,2个月,3天

    • P1Y2M3W4D - 1年,2个月,3周,4天

7.1.4. DSL 中的示例配置文件

# Enable cluster mode
--cluster-mode = true
# Enable debugging for server and xmpp.impl
--debug = 'server,xmpp.impl'
# Set list of virtual hosts (old way)
--virt-hosts = 'example.com,test-1.example.com,test-2.example.com'

# Configure list of administrator jids
admins = [ 'admin@zeus', '[email protected]' ]
# Set config type
config-type = '--gen-config-def'

# Configure dataSource bean with database configuration
dataSource {
    # Configure default data source (using default implementation so class is omitted)
    default () {
        uri = 'jdbc:postgresql://127.0.0.1/tigase?user=test&password=test&autoCreateUser=true'
    }

    # Configure data source with name exaple.com (will be used by domain example.com)
    'example.com' () {
        uri = 'jdbc:mysq://127.0.0.1/example?user=test&password=test&autoCreateUser=true'
    }
}

# Configure C2S component
c2s {
    # Enable Stream Management bean
    'urn:xmpp:sm:3' () {}

    # Register tigase.server.xmppclient.SeeOtherHostDualIP as seeOtherHost bean
    seeOtherHost (class: tigase.server.xmppclient.SeeOtherHostDualIP) {}

    # Add additional port 5224 which is SSL port and disable port 5223
    connections () {
        '5224' () {
             socket = ssl
          }
        '5223' (active: false) {}
    }
}

# Configure HTTP API component
http {
    # Set list of API keys
    api-keys = [ 'test1234', 'test2356' ]
    rest {
        # Set value of environment property as a path to look for REST scripts
        rest-scripts-dir = env('TIGASE_REST_SCRIPTS_DIR')
    }
}

# Register pubsub-2 (class is passed as pubsub-2 name do not have default class assigned)
pubsub-2 (class: tigase.pubsub.cluster.PubSubComponentClustered) {
    # Set configuration bean properties
    pubsubConfig {
        persistentPep = true
    }
    # Use tigase.pubsub.cluster.ClusteredNodeStrategy as advanced clustering strategy
    strategy (class: tigase.pubsub.cluster.ClusteredNodeStrategy) {}
}

# Configure Session Manager
sess-man {
    # Here we enable pep, urn:xmpp:mam:1 processors and disable message-archive-xep-0136 processor
    pep () {}
    'urn:xmpp:mam:1' () {}
    message-archive-xep-0136 (active: false) {}

    # Define class used as clustering strategy (it is different than default so class is required)
    strategy (class: tigase.server.cluster.strategy.OnlineUsersCachingStrategy) {}
}

7.1.5. 默认配置

Tigase XMPP 服务器包含一个基本的 config.tdsl 文件,该文件告诉服务器以设置模式启动。

'config-type' = 'setup'

http () {
    setup () {
        'admin-user' = 'admin'
    'admin-password' = 'tigase'
    }
}

这告诉 Tigase 在设置模式下运行,并告诉 http 组件允许使用用户名和密码 admin/tigase 登录。有了它,您可以进入 this section 中介绍的设置过程。

配置类型还有其他选项: default, session-manager, connection-managers, 和 component 。如需更多信息,请访问 Config Type 属性说明。

7.2. tigase.sh 的启动文件 - tigase.conf

tigase.sh 启动脚本的属性文件名是启动脚本的第二个参数。如果环境变量设置在不同的位置或以不同的方式设置,则可以跳过它。

启动脚本的配置文件简单地设置环境变量的数量以及所需组件的位置。在此文件中设置的可能变量是:

  • JAVA_HOME - Java 安装主目录的位置。 必须设置

  • TIGASE_HOME - Tigase 安装主目录的位置。 默认情况下,脚本尝试通过从脚本运行的位置搜索目录来找到此位置。

  • TIGASE_CONSOLE_LOG - 如果服务器在后台运行,所有控制台消息将被重定向到的文件。默认情况下,它将是:TIGASE_HOME/logs/tigase-console.log如果 Tigase 进程无法写入此文件/目录,所有控制台消息将被重定向到 /dev/null

  • TIGASE_PID 带有服务器 PID 号的文件的位置。默认情况下,它将是 TIGASE_HOME/logs/tigase.pid

  • JAVA_OPTIONS - JVM 的选项,例如为 JVM 分配的 RAM 大小,属性等。

  • TIGASE_OPTIONS - (可选)Tigase 服务器程序的附加选项。您可以在此处为您的环境调整初始参数。如果你想为配置文件指定自定义位置,你应该使用 --config-file <path/to/config.tdsl> 配置

使用 PostgreSQL 数据库运行 Tigase 的示例文件可能如下所示:

ENC="-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
DRV="-Djdbc.drivers=org.postgresql.Driver"
JAVA_OPTIONS="${ENC} ${DRV} -server -Xms100M -Xmx100M "
CLASSPATH=""
TIGASE_CONFIG="tigase-pgsql.xml"
TIGASE_OPTIONS=" "

请注意编码设置。JVM 默认使用操作系统环境中设置的编码。然而,XMPP 协议使用 UTF-8 进行所有数据处理。因此 ENC 设置对所有操作强制执行 UTF-8 编码。

另一个重要的设置是 \’CLASSPATH’。它被有意设置为空字符串。 tigase.sh 启动脚本根据 jars/libs/ 目录中的文件自行构建 CLASSPATH。建议将 CLASSPATH 设置为空字符串,因为 Tigase 服务器会扫描所有可用的类以查找所有组件和插件实现。如果 CLASSPATH 包含大量未使用的库,则可能会导致启动时间长和系统负载高。

7.3. 高负载系统的 Linux 设置

您必须针对高负载系统调整一些基本设置,以确保服务器有足够的资源来处理大量网络连接。

主要参数是允许进程同时保留的最大打开文件数。每个网络连接都使用一个文件处理程序,因此如果此限制数太低,您可能会很快用完处理程序,服务器将无法接受更多连接。

此限制设置在 2 个级别 - 内核级别(fs.file-max)和系统级别(nofile)。

另一个在某些配置中可能很重要的内核属性(例如传输安装或当您使用代理进行 Bosh 连接时)是:net.ipv4.ip_local_port_range。此参数的设置方式与 fs.file-max 属性相同。

7.3.1. fs.file-max

fs.file-max 内核属性是通过 sysctl 命令设置的。您可以通过执行以下命令查看当前设置:

# sysctl fs.file-max
fs.file-max = 358920

如果您计划运行具有大量服务器连接的高负载服务,则此参数应至少是您希望支持的网络连接数的两倍。您可以通过执行以下命令来更改此设置:

# sysctl -w fs.file-max=360000
fs.file-max = 360000

7.3.2. net.ipv4.ip_local_port_range

您可以通过执行以下命令查看当前设置:

# sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768    61000

您可以通过执行以下命令来更改此设置:

# sysctl -w net.ipv4.ip_local_port_range="1024 65000"
net.ipv4.ip_local_port_range = 1024 65000

7.3.3. TCP_keepalive

根据 Using TCP keepalive to Detect Network ErrorsTCP Keepalive HOWTO 应该更改一些 keepalive 设置以提高可靠性 - 它将启用 keep alive功能(检查连接是否已建立和有效),并且通过减少时间和间隔 - 将更快地检测断开的连接。

# sysctl -w net.ipv4.tcp_keepalive_time="60"
net.ipv4.tcp_keepalive_time = 60
# sysctl -w net.ipv4.tcp_keepalive_probes="3"
net.ipv4.tcp_keepalive_probes = 3
# sysctl -w net.ipv4.tcp_keepalive_intvl="90"
net.ipv4.tcp_keepalive_intvl = 90
# sysctl -w net.ipv4.tcp_retries2=4
net.ipv4.tcp_retries2 = 4

7.3.4. /etc/sysctl.conf

上述命令让系统记住新设置,直到下次系统重新启动。如果要使更改永久生效,则必须编辑文件:/etc/sysctl.conf 并在文件末尾添加属性:

fs.file-max=360000
net.ipv4.ip_local_port_range=1024 65000
net.ipv4.tcp_keepalive_time=60
net.ipv4.tcp_keepalive_probes=3
net.ipv4.tcp_keepalive_intvl=90
net.ipv4.tcp_retries2=4

下次启动服务器时会自动加载。

命令:

# sysctl -p

导致 /etc/systcl.conf 被重新加载,当您向文件添加更多参数并且不想重新启动服务器时,这很有用。

7.3.5. 无文件

这是被系统限制所使用的属性。例如,运行命令 ulimit -a 会显示为当前用户设置的所有限制:

# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 38912
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 40960
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 38912
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

为了让它更有趣和更复杂,有两种类型的系统限制:软限制,此时用户可以暂时超过,硬限制,此时用户不能超过。要查看您的 硬限制 执行如下命令:

# ulimit -a -H
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 38912
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 40960
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 38912
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

硬限制通常大于软限制或有时相同。

对我们来说最重要的参数是:打开文件。您可以更改文件中的属性:/etc/security/limits.conf。您必须将以下 2 行附加到文件末尾:

jabber               soft    nofile         350000
jabber               hard    nofile         350000

其中 jabber 是运行您的 IM 服务的帐户的用户名。您还可以通过以下方式为机器上的所有用户设置限制:

*               soft    nofile         350000
*               hard    nofile         350000

要使这些更改生效,您必须从修改后的帐户注销并再次登录。新的限制应该被运用。

7.3.6. su 和 init 脚本

如果打算使用 init 脚本来启动(或者只是希望能够使用 su 命令启动服务器),则有必要通过修改 /etc/pam.d/su 文件并取消以下行的注释来调整 PAM 配置:

session    required   pam_limits.so

之后, init 脚本将遵守配置的限制。

7.4. JVM 设置和建议

Tigase 配置文件 tigase.conf (在 Startup File for tigase.sh-tigase.conf 中有更详细的描述)提到了几个与 JVM 的操作相关的环境变量。在本指南中,我们将阐述这些配置选项并提供最佳设置提示。

etc/tigase.conf 中包含的设置如下:

#GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
#EX="-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA"

#GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc "

#PRODUCTION_HEAP_SETTINGS=" -Xms5G -Xmx5G " # heap memory settings must be adjusted on per deployment-base!
JAVA_OPTIONS="${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m "

虽然此文件使用 bash 变量,但 JVM 配置选项可以在所有操作系统上以相同的方式使用。

该指南将包括两个主要部分 - 内存设置和垃圾收集器来调整描述和提示。

我们建议在所有情况下都使用 -server JVM 参数。

7.4.1. 堆的大小

对于非生产部署(开发或说明环境),我们建议使用 JVM 的默认内存设置(取决于底层操作系统),这会导致自动内存分配,并且根据经验法则 - 在此类环境中是最安全的环境。

对于生产环境,我们建议使用固定大小的 堆 - 初始大小和最大大小,可以(分别)使用 -Xms-Xmx JVM 标志设置 - 理想情况下为相同的值(如果 Tigase 将是机器上的唯一服务,应该是大约 95% 的可用内存)以避免分配和释放。

为方便起见,可以取消注释行 PRODUCTION_HEAP_SETTINGS 并相应地调整参数。

内存考虑 - 总使用量

HEAP 大小并不是影响 JVM 内存使用的唯一因素。在尝试根据您的使用情况和机器规格调整大小时,您必须考虑计入总数的其他因素:加载的类、线程的堆栈、JIT 代码缓存、垃圾收集器等等。原则上考虑以下等式:

Maximum memory usage = [-Xmx] + [-XX:MaxMetaspaceSize] + number_of_threads * [-Xss] + [-XX:MaxDirectMemorySize]
                       (heap)   (classes)                (threads' stack)             (direct memory)

在 Tigase XMPP 服务器的情况下,除了堆之外,我们还限制了其余因素:

  • 直接内存到 128 MB

  • 加载类到 128 MB

  • 单线程的栈大小为 228 KB(线程数取决于 CPU 内核的数量,可能从 500 到几千不等)

原则上,除了由 -Xmx 定义的堆的最大大小之外,您还应该添加大约 512 MB

如果您对内存的详细跟踪感兴趣,请查看 [JVM 的内存占用](https://spring.io/blog/2019/03/11/memory-footprint-of-the-jvm/), [JVM中的Native Memory Tracking](https://www.baeldung.com/native-memory-tracking-in-jvm)或者[为什么我的Java进程消耗的内存比Xmx多?](https://plumbr.io/blog/memory-leaks/why-does-my-java-process-consume-more-memory-than-xmx)

To facilitate getting information about complete memory usage we include this information in Tigase statistics, but it requires explicitly enabling it:

  • uncomment JVM_MEMORY line in etc/tigase.conf:

JVM_MEMORY=" -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics "
  • enable detailed-memory-statistics in message-router bean in etc/config.tdsl file:

'message-router' () {
    'detailed-memory-statistics' = true
}

7.4.2. GC 设置

让我们首先声明没有 “一个人可以统治一切” - 每个部署和用例都是不同的,但是我们将尝试给出一些指示和建议,并继续简要介绍 GC 本身。

XMPP 在内存分配方面非常具体 - 短期对象(各种类型的节)通常超过长期对象(用户连接和相关数据)的数量。这是关于 JVM HEAP 的组织方式和垃圾收集器如何工作的重要信息。在最基本的层面上,堆被分成几个区域:

  • 年轻代,其又分为:

    • Eden - 创建对象时通常分配对象的区域;

    • 幸存者区 - (tofrom - 其中一个始终为空) - 负责存储收集 年轻代 (过程重复多次,直到最终考虑对象 足够老)后剩余的所有存活对象 ;

  • 老年代 - (养老区) - 负责在 幸存者区 上运行 GC 后剩余的活动对象 - 这些将是 长期 对象(通常是用户连接和相关数据);

Minor,Major 和 Full GC - 优化

一般认为:

  • Minor GC 清理年轻代;

  • Major GC 清理 Tenured 空间;

  • Full GC 清理所有堆。

然而,虽然我们可以肯定地说 Minor GC 会清理年轻代,但区分 Major GC 和 Full GC 有点困难,特别是考虑到 Major GC 经常由 Minor GC 触发,并且一些垃圾收集器可以同时执行清理。与其关注区分阶段,不如更关注垃圾收集器本身的实际操作 - 取消在 etc/tigase.conf 中的注释行 GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc: logs/jvm.log -verbose:gc " (或向 java 命令行添加相同的属性)并随后分析结果应该会更有帮助。此外,使用示例 VisualVM(带有 VisualGC 插件)监控 GC 操作也将有所帮助。

XMPP 的设置

理想情况下,我们应该限制 GC 暂停的次数及其持续时间。经过非同寻常的测试,得出以下结论:

  • 垃圾回收速度越快,死对象占用给定空间越多,因此在高流量安装中,最好使用较大的 YoungGen,从而降低对象向 OldGen 的提升;

  • 随着 JVM8 的年轻/老年代默认大小发生变化,即使 NewRatio 仍然默认为“2” - 将其显式设置为“2”会恢复以前的大小;

  • 启用并发标记和扫描 (CMS)(仅适用于 Tenured 空间),通常将 NewRatio 的显式配置设置为默认值 2(即 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2)表现最好;

  • 对于低流量的小型安装(核心 CPU 少,内存少)默认并行收集器可能是更好的解决方案;

  • 使用根据实际使用情况调整的堆大小会更好,因为堆越大,需要执行收集的空间就越大,从而导致更长的暂停;如果堆很大,G1 收集器可能是避免更长暂停的更好解决方案;

考虑到上述所有因素,使用以下选项应该是进一步优化垃圾收集的良好起点:

GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"

值得考虑的 GC 设置

除了使用 CMS 收集器的一般性建议外,以下选项(或对选项的更改)可能值得考虑:

  • -XX:NewRatio=2 - 定义年轻代和老生代的比例为 1:2。换句话说,eden和幸存者空间的组合大小将是总堆大小的三分之一。参数 NewSize 和 MaxNewSize 从下方和上方限制了年轻代的大小。将它们设置为相同的值会修复年轻代,就像将 -Xms 和 -Xmx 设置为相同的值会修复总堆大小一样。

  • -XX:CMSInitiatingOccupancyFraction=percent - 设置开始 CMS 收集周期的老年代占用率(0 到 100)。

  • -XX:+UseCMSInitiatingOccupancyOnly - 指示 JVM 不要根据运行时统计信息,而是使用每个 CMS 周期的 CMSInitiatingOccupancyFraction 的值来决定何时启动 CMS 周期。

  • -XX:ParallelGCThreads=x - 设置年轻代和老年代用于并行垃圾回收的线程数。默认值取决于 JVM 可用的 CPU 数量。如果 Tigase JMV 是安装中唯一的运行,建议使用默认值。

  • -XX:ConcGCThreads=x - 设置用于并发 GC 的线程数。默认值取决于 JVM 可用的 CPU 数量。如果 Tigase JMV 是安装中唯一的运行,建议使用默认值。

  • -XX:+UseBiasedLocking-XX:+DoEscapeAnalysis - 旨在消除锁定开销,但是它们对性能的影响是不可预测的,因此需要进行测试;减少锁定应该可提高并发性,并且在当前的多核硬件上,提高吞吐量。

  • -XX:+OptimizeStringConcat - 启用字符串连接操作的优化。此选项默认被启用。

  • -XX:+UseNUMA - 通过增加应用程序对低延迟内存的使用,在具有非统一内存架构(NUMA - 大多数现代计算机基于 NUMA 架构)的机器上启用应用程序的性能优化。默认情况下,此选项处于禁用状态,并且不会对NUMA进行优化。该选项仅在使用并行垃圾收集器时可用(-XX:+UseParallelGC)。

  • -XX:-UseCompressedOops -  禁用压缩指针的使用。此选项被默认启用,当 Java 堆大小小于 32 GB 时使用压缩指针。启用此选项后,对象引用将表示为 32 位偏移量而不是 64 位指针,这通常会在运行 Java 堆大小小于 32 GB 的应用程序时提高性能。此选项仅适用于 64 位 JVM。

7.4.3. 机器 x, y, z 使用什么?

服务器类机器(非 VM) , > 16GB, >= 8 核 CPU

对于此类设置,建议启用 CMS 垃圾收集器。根据流量使用情况和特定用例,可能需要调整 NewRatio。需要针对实际可用内存调整 Xms 和 Xms 大小(或者更好的是,针对实际流量!)。应使用以下内容:

GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
EX="-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA"

#GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc "

PRODUCTION_HEAP_SETTINGS=" -Xms15G -Xmx15G " # heap memory settings must be adjusted on per deployment-base!
JAVA_OPTIONS="${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m "

对于有大量可用内存并打算利用这些内存的安装,使用 G1GC 收集器可能是一个更好的主意:

GC="-XX:+UseG1GC -XX:ConcGCThreads=4 -XX:G1HeapRegionSize=2 -XX:InitiatingHeapOccupancyPercent=35 -XX:MaxGCPauseMillis=100"
EX="-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA"

#GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc "

PRODUCTION_HEAP_SETTINGS=" -Xms60G -Xmx60G " # heap memory settings must be adjusted on per deployment-base!
JAVA_OPTIONS="${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m "

VM 机器,8GB RAM,4 核 CPU 等效

对于此类设置,还建议启用 CMS 垃圾收集器。根据流量使用情况和特定用例,可能需要调整 NewRatio(并且必须配置 NewRatio!)。需要针对实际可用内存调整 Xms 和 Xms 大小(或者更好的是,针对实际流量!)。应使用以下内容:

GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
EX="-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA"

#GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc "

PRODUCTION_HEAP_SETTINGS=" -Xms7G -Xmx7G " # heap memory settings must be adjusted on per deployment-base!
JAVA_OPTIONS="${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m "

具有 4GB 或更少 RAM 且少于 4 核 CPU 的 VM 机器

资源有限的小型安装可以在默认情况下更好地运行(对于直到 8 的 JVM 版本,这是撰写本文时最新的版本)。同样 - 根据流量使用情况和特定用例,可能需要调整 NewRatio。建议针对实际可用内存调整 Xms 和 Xms 大小(或者更好的是,针对实际流量!)。应该使用以下内容(即应该注释 GC 行以便使用默认值):

#GC="-XX:+UseBiasedLocking -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:NewRatio=2 -XX:+CMSIncrementalMode -XX:-ReduceInitialCardMarks -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
EX="-XX:+OptimizeStringConcat -XX:+DoEscapeAnalysis -XX:+UseNUMA"

#GC_DEBUG=" -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Xloggc:logs/jvm.log -verbose:gc "

PRODUCTION_HEAP_SETTINGS=" -Xms3G -Xmx3G " # heap memory settings must be adjusted on per deployment-base!
JAVA_OPTIONS="${GC} ${GC_DEBUG} ${EX} ${ENC} ${DRV} ${JMX_REMOTE_IP} -server ${PRODUCTION_HEAP_SETTINGS} ${DNS_RESOLVER} ${INTERNAL_IP} ${EXTERNAL_IP}  -XX:MaxDirectMemorySize=128m "

7.4.4. 其他资源

7.5. 会话管理器

Tigase 会话管理器可以配置大多数 Tigase 基本选项,也可以控制许多操作。对会话管理器的更改会影响整个 XMPP 安装中的操作,因此在此处更改设置时必须小心。

7.5.1. 移动优化

默认情况下,Tigase 运用 XEP-0352 客户端状态指示,其通过允许 XMPP 服务器抑制或减少发送到客户端的更新数量,从而减少发送到非活动移动客户端的节数,从而实现更流畅的移动体验。此应用包含在处理器 ClientStateIndication 中,并且独立于 MobileV1、MobileV2、MobileV3 设置。

然而,这可以通过使用来自 Tigase 的移动插件进行微调,通过在 config.tdsl 文件中添加以下行并同时使用它:

}
'sess-man' {
    'urn:xmpp:csi:0' {
        logic = 'tigase.xmpp.impl.MobileV1'
    }
}

逻辑选项是:

MobileV1

将所有存在节保持在队列中直到客户端处于活动状态为止。

logic = 'tigase.xmpp.impl.MobileV1'

MobileV2

当客户端处于非活动状态时,此设置会延迟呈现状态的传递,但仅保留每个完整 jid 的最后呈现状态。 这是 CSI 逻辑的默认设置

logic = 'tigase.xmpp.impl.MobileV2'

MobileV3

保持与 MobileV2 相同的存在逻辑,但也把 Message Carbons 排队。目前不支持 CSI 处理器,会导致问题

logic = 'tigase.xmpp.impl.MobileV3'

禁用 CSI

如果您不想使用 ClientStateIndication 处理器,请在 config.tdsl 文件中设置以下内容:

'sess-man' () {
    'urn:xmpp:csi:0' (active: false) {}
}

关于移动插件的说明

之前,您可以通过启用 Mobile_V1 (){} bean 到会话管理器来启用移动优化逻辑:sess-man () {} bean。

如果您过去使用过这些,建议您更改系统以使用具有适当移动处理逻辑的 CSI 处理器。

如果您需要 v3 逻辑,或者不希望使用 CSI,请务必使用上述选项禁用它。

7.5.2. 线程池

threadsNo 属性允许你微调 SM 插件(处理器)的线程池。使用默认设置,每个插件都有自己的线程池。这保证了最佳性能和最佳资源使用。此设置的缺点是,如果在不同的线程池中处理数据包,它们可能会乱序到达。

我们甚至可以微调这个数据包处理。比方说您希望大多数插件在单个线程池中执行以保留它们的数据包顺序,但对于一些选定插件应该在单独的线程池中执行以提高性能。比如说,身份验证数据包和用户注册实际上可以在单独的线程池中执行,因为我们不担心它们的顺序。无论如何,用户在进行身份验证之前都无法发送或接收任何其他内容。解决方案是为所选插件指定线程数。例如,为所有插件设置一个公共线程池,但注册和身份验证可以通过以下配置完成:

'sess-man' () {
    'amp' () {
        threadsNo = 30
    }
    'presence-state' () {
        threadsNo = 27
    }
}

这取代了旧的 --sm-threads-pool 属性,并在 --sm-plugins 中指定线程池。

7.5.3. 线程池因子

会话管理器可以控制每个处理器的可用线程池数量。通过在 config.tdsl 文件中添加以下行,可以将全局线程池增加一个指定的因子:

'sess-man' () {
    'sm-threads-factor' = 3
}

在这种情况下,全局线程池增加了 3 倍。

7.5.4. Strategy

Strategy 属性允许用户指定用于处理集群环境的集群策略类;默认情况下使用 SMNonCachingAllNodes

任何实现 tigase.cluster.strategy.ClusteringStrategyIfc 接口的类都可以用于此设置。

例子:

'sess-man' () {
    strategy (class: tigase.cluster.strategy.SMCachingAllNodes)
}

这替换了 v7.1 中的旧的 --sm-cluster-strategy-class 设置。

7.6. Tigase 服务器中的虚拟主机

Tigase 服务器在单个服务器安装中支持多个虚拟主机。可以在运行时添加或删除,启用或禁用虚拟主机,而无需重新启动服务或中断正常操作。

本文档描述了虚拟主机在 Tigase 服务器中的工作方式以及如何在您的安装中充分利用此功能。

‘default-virtual-host’ 属性允许定义单个虚拟主机域的名称,该域将被视为此安装的默认虚拟主机域。它只允许您配置域名。任何额外的配置都需要使用 ad-hoc 命令进行配置。

虚拟主机应使用 ad-hoc 命令或管理 ui 进行管理,请访问 添加和管理域 以了解虚拟主机管理过程的说明或访问 用于管理虚拟域的临时命令规范 有关临时命令的更多信息。

如果您的组件可能无法处理多个虚拟主机或集群模式,我们也开发了一个虚拟组件解决方案,详细信息请参见 Tigase 集群的虚拟组件 部分。

您可能还想参考 Vhosts API 以获取更多信息: - Tigase 服务器中虚拟域管理的 API 描述

7.6.1. 默认虚拟主机配置

可以在 TDSL 配置文件(即 etc/config.tdsl)中为所选参数指定所有虚拟主机的初始默认配置。为此,您应该在属于 vhost-man bean 的 defaults bean 中指定每个配置选项:

'vhost-man' () {
    'defaults' () {
        'domain-filter-policy' = null
        's2s-secret' = null
        trusted = null
        'vhost-disable-dns-check' = false
        'vhost-max-users' = 0L
        'vhost-message-forward-jid' = null
        'vhost-presence-forward-jid' = null
        'vhost-register-enabled' = true
        'vhost-tls-required' = false
    }
}

初始定义默认配置或首次启动 Tigase XMPP 服务器后,可以使用 ad-hoc 命令配置虚拟主机默认值,方法是使用 ad-hoc 修改 default 的值,如 用于管理虚拟域的临时命令规范 中所述。

或者,您可以使用管理 UI 编辑默认虚拟主机配置(域 default 的配置),这些在默认情况下可通过 http://localhost:8080/admin/ 获得。

7.6.2. 用于管理虚拟域的临时命令规范

Tigase 服务器中有 3 个用于虚拟域管理的临时命令:

  1. VHOSTS_RELOAD 用于从存储库(数据库)重新加载虚拟域列表。

  2. VHOSTS_UPDATE 用于添加新的虚拟域或更新现有虚拟域的信息。

  3. VHOSTS_REMOVE 用于从正在运行的服务器中删除现有的虚拟主机。

命令的语法遵循 XEP-0050 中描述的规范。完成命令所需的额外信息以 XEP-0004 中描述的数据形式携带。

仅当安装管理员发送所有命令时,服务器才会接受所有命令。如果命令是从任何其他帐户发送的,则返回 <not-authorized /> 错误。若要授予帐户管理员权限,您必须在 admins 配置文件中设置 admins 属性。

命令被发送到 ‘vhost-man’ 服务器组件,并且该节的 ‘to’ 属性必须包含服务器上 VHostManager 的完整 JID。完整的 JID 包含组件名称:’vhost-man’ 和本地域,即已经在虚拟域列表中并且处于活动状态的域。假设已经为服务器安装激活的域之一 ‘existing.domain.com’ 的 JID 是:’vhost-man@existing.domain.com’。

从数据库重新加载域列表

为了从配置文件以外的永久存储库重新加载虚拟域,您必须向服务器上的 VHostManager 发送 VHOSTS_RELOAD 临时命令。

重新加载命令请求的形式为:

<iq type="set"
    to="[email protected]"
    id="aac8a">
  <command xmlns="http://jabber.org/protocol/commands"
           node="VHOSTS_RELOAD" />
</iq>

服务器在成功完成命令后使用当前虚拟域服务器数量通过安装发送响应:

<iq from="[email protected]"
    type="result"
    to="[email protected]"
    id="aac8a">
  <command xmlns="http://jabber.org/protocol/commands"
           status="completed"
           node="VHOSTS_RELOAD">
    <x xmlns="jabber:x:data" type="result">
      <field type="fixed" var="Note">
        <value>Current number of VHosts: 123</value>
      </field>
    </x>
  </command>
</iq>

如果命令是从 admin 以外的帐户发送的,则服务器会返回错误:

<iq from="[email protected]"
    type="error"
    to="[email protected]"
    id="aac8a">
  <command xmlns="http://jabber.org/protocol/commands"
           node="VHOSTS_RELOAD" />
  <error type="auth" code="401">
    <not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
    <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"
          xml:lang="en">
      You are not authorized for this action.
    </text>
  </error>
</iq>

除了最终用户信息之外,响应没有任何特殊含义。客户端可能会忽略响应,因为它是在命令执行后发送的。

添加新域或更新现有域

为了添加新域或更新现有域,您必须发送一个临时命令 VHOSTS_UPDATE ,其命令数据形式中至少包含一个域名。您还可以指定此域是启用还是禁用,但这些是可选的。未来的版本可能允许为域设置其他参数:此域的最大用户帐户数,对域启用/禁用匿名登录、对该域启用/禁用通过 XMPP 注册以及尚未指定的更多参数。

域添加/更新命令请求的形式为:

<iq type="set"
    to="[email protected]"
    id="aacba">
  <command xmlns="http://jabber.org/protocol/commands"
           node="VHOSTS_UPDATE">
    <x xmlns="jabber:x:data" type="submit">
      <field type="text-single"
             var="VHost">
        <value>new-virt.domain.com</value>
      </field>
      <field type="list-single"
             var="Enabled">
        <value>true</value>
      </field>
    </x>
  </command>
</iq>

请注意:命令字段变量名称中的字符大小写确实很重要。

成功完成命令后,服务器将响应返回给客户端,其中包含服务器上现有虚拟主机数量的信息:

<iq from="[email protected]"
    type="result"
    to="[email protected]"
    id="aacba">
  <command xmlns="http://jabber.org/protocol/commands"
           status="completed"
           node="VHOSTS_UPDATE">
    <x xmlns="jabber:x:data" type="result">
      <field type="fixed" var="Note">
        <value>Current number of VHosts: 124</value>
      </field>
    </x>
  </command>
</iq>

从服务器中删除虚拟域

为了删除一个虚拟域,你必须发送 VHOSTS_REMOVE 命令到带有域名的服务器。

域删除命令由客户端发送:

<iq type="set"
    to="[email protected]"
    id="aacba">
  <command xmlns="http://jabber.org/protocol/commands"
           node="VHOSTS_REMOVE">
    <x xmlns="jabber:x:data" type="submit">
      <field type="text-single"
             var="VHost">
        <value>virt-nn.domain.com</value>
      </field>
    </x>
  </command>
</iq>

成功完成命令后,服务器将响应返回给客户端,其中包含服务器上现有虚拟主机数量的信息:

<iq from="[email protected]"
    type="result"
    to="[email protected]"
    id="aacba">
  <command xmlns="http://jabber.org/protocol/commands"
           status="completed"
           node="VHOSTS_REMOVE">
    <x xmlns="jabber:x:data" type="result">
      <field type="fixed" var="Note">
        <value>Current number of VHosts: 124</value>
      </field>
    </x>
  </command>
</iq>

7.6.3. 集群模式的虚拟组件

假设您有一个集群安装,并且您希望在您的安装中还包含一个不支持集群模式的组件。如果您将它作为单独的实例放在所有节点上,它们将不同步,并且整体功能可能毫无用处。如果您只放置一个节点,它将正常工作,但其仅对连接到该节点的用户可见。

理想情况下,您希望有一种机制将其安装在一个节点上,并在其他节点上进行一些重定向,以将该组件的所有数据包转发到该组件正在工作的节点。它自己的重定向是不够的,因为该组件必须在服务发现列表中可见,并且必须以某种方式对连接到所有节点的用户可见。

这是虚拟组件很方便的地方。它们作为本地普通组件对用户可见,它们看起来似乎是真正的本地组件,但实际上它们只是将所有请求/数据包转发到真正组件上正在工作的集群节点。

虚拟组件是 Tigase 服务器中一个非常轻量级的 ServerComponent 实现。它可以伪装成任何类型的组件,并且可以将所有数据包重定向到给定地址。它们可以模仿原生 Tigase 组件也可以作为通过外部组件协议 (XEP-0114) 连接的第三方组件。

配置非常简单明了,实际上它与任何 Tigase 组件的配置非常相似。您将真实组件名称设置为组件名称和要加载的虚拟组件类名称。假设我们想以这种方式部署 MUC 组件。 MUC 组件在安装中显示为 muc.domain.oug。因此组件的名称是:muc

muc (class: tigase.cluster.VirtualComponent) {}

这几乎是加载虚拟组件所需的全部内容。需要一些其他选项来指向正确的数据包转发目标地址并设置正确的服务发现参数:

}
muc (class: tigase.cluster.VirtualComponent) {
    'disco-category' = 'conference'
    'disco-features' = 'http://jabber.org/protocol/muc'
    'disco-name' = 'Multi User Chat'
    'disco-node' = ''
    'disco-type' = 'text'
    'redirect-to' = '[email protected]'
}

就这些

7.7. Tigase 中的自定义日志设置

日志记录可以成为监控服务器运行状况和性能的重要工具。日志记录可以在每个组件的基础上进行控制和定制。

实现了一个 logging bean,以允许在 Tigase XMPP 服务器中更灵活地配置日志记录。

7.7.1. 配置日志记录

在配置文件中

您安装的默认日志配置保存在配置文件中,并且可以在那里进行调整。

logging () {
    rootLevel = CONFIG
    'packet-debug-full' = true
    loggers = {
        'tigase.server' = {
            level = ALL
        }
        'tigase.conf' = {
            level = FINEST
        }
    }
    handlers = {
        ' java.util.logging.FileHandler' = {
            level = ALL
            append = true
            count = 5
            formatter = 'tigase.util.LogFormatter'
            limit = 10000000
            pattern = 'logs/tigase.log'
        }
        'java.util.logging.ConsoleHandler' = {
            level = WARNING
            formatter = 'tigase.util.LogFormatter'
        }
    }
}

您只需要指定想要自定义的设置,否则它们将保留默认设置。

  • packet-debug-full - 控制日志条目是否应该被混淆(所有元素的所有 CData 将被替换为 CData size: <length in bytes of the replaced string>) ; 默认值: false

  • rootLevel - 为所有未另行定义的组件定义日志记录的根级别。默认是CONFIG

  • loggers - 定义在 tigase 服务器中运行的包的日志记录级别。这类似于 –debug 设置,但是您必须使用 tigase.{package} 格式。默认为NONE。

  • handlers - 定义文件输出和控制台输出的日志记录级别。

    1. FileHandler - 是日志文件的文件输出,有以下选项:

      1. level - 指定要写入的日志级别,默认为 ALL。

      2. append - 是追加到日志还是在重启期间替换它。默认是true。

      3. count - 保持在设定限制的单个日志文件的数量。默认为 5。(默认设置将继续附加日志,直到达到 5 个 10MB 的文件,然后最旧的文件将被覆盖。)

      4. formatter - 指定要格式化日志输出的包。默认为 tigase.util.LogFormatter。

      5. limit - 每个日志文件的字节限制。默认值为 10000000 或 10MB。

      6. pattern - 关于 Tigase 安装目录的日志文件的目录和文件名。默认为日志/tigase.log。

    2. ConsoleHandler - 决定 Tigase 输出到控制台的格式。

      1. level - 指定要写入的日志级别,默认为 WARNING。

      2. formatter - 指定要格式化日志输出的包。默认为 tigase.util.LogFormatter。

7.7.2. 禁用彩色输出

如果由于某种原因您不想在日志中显示彩色输出,您可以通过将 disable_logger_color 设置为 true 来禁用它。为方便起见,您可以在 etc/tigase.conf 以下行中取消注释:

#DISABLE_LOGGER_COLOR=" -Ddisable_logger_color=true "

对日志记录配置的临时更改

也可以使用名为 Set package logging 的 ad-hoc 命令,在 message-router@domain (其中 domain 是您的服务器名称)用id logging-set 来重新配置日志记录级别运行时的数据包,且无需重新启动 Tigase XMPP 服务器。

注意

这些更改将应用于此单个集群节点。

使用Admin UI

如果您的 Tigase XMPP 服务器正在运行 HTTP 服务器并启用了 Admin UI,那么更改日志记录配置的最简单方法是使用 Admin UI。登录到 Web 界面后,打开 Configuration 部分并选择 Set package logging 命令。这将为您带来一个表格,您需要填写以下字段:

  • Package name - 应包含您希望更改日志记录级别的 Java 包或类名

  • Level - 选择您希望的输入包名称的日志记录级别 (* OFF 表示将禁用日志记录*)

按下 Submit 后,您的表单将被传递到服务器进行验证,并将应用选定的更改。

使用ad-hoc命令

如果您有权访问 Tigase XMPP 服务器和支持执行 ad-hoc 命令的 XMPP 客户端的 XMPP 管理员帐户,您可以将 XMPP 客户端连接到 Tigase XMPP 服务器并在 message-router@domain (其中 domain 是您的服务器名称)中查找可用的adh-hoc命令 。在找到的adh-hoc命令中,您应该找到名为 Set package logginglogging-set 的命令(这取决于您的 XMPP 客户端显示的内容,命令的 ID 或名称)并且您应该执行它。 Tigase XMPP 服务器将返回一个表单,您需要填写以下字段:

  • Package name - 应包含您希望更改日志记录级别的 Java 包或类名

  • Level - 选择您希望的输入包名称的日志记录级别 (* OFF 表示将禁用日志记录*)

提交表单后,Tigase XMPP 服务器将验证您的请求并更新日志配置。

使用 REST API

如果您启用了 REST API 的 Tigase XMPP 服务器,您也可以使用它来配置 Tigase XMPP 服务器的日志记录。

注意

与所有 HTTP REST API 请求一样,您将需要一个有效的 API 密钥,在这种情况下,需要一个有效的管理员凭据来使用基本 HTTP 身份验证对 HTTP 请求进行身份验证。

您需要做的就是发送一个 HTTP POST 请求到 /rest/adhoc/message-router@domain.com (其中域是您的服务器名称),并将 Contect-Type 设置为 application/xml 和以下 XML 作为有效负载将 tigase.server 包的日志记录级别设置为 ALL

<command>
  <node>logging-set</node>
  <fields>
    <item>
      <var>package-name</var>
      <value>tigase.server</value>
    </item>
    <item>
      <var>level</var>
      <value>ALL</value>
    </item>
  </fields>
</command>

7.7.3. Tigase 中的备用记录器 - Logback

可以将 Logback 用于日志记录目的,它提供了某些有趣的功能(异步日志记录,更好地控制日志轮换,动态更改日志记录配置)

要求: * slf4j-api.jar (在 -dist-max 包中提供) * jul-to-slf4j.jar (在 -dist-max 包中提供) * 所需的记录器库 (对于 logback 它是 logback-classic.jarlogback-core.jar (在 -dist-max中提供)。

配置归结为将 slf4j 桥处理程序添加到内置 Java Logger 处理程序配置列表中,在 Tigase 中,这转换为在 etc/config.tdsl 中添加以下行:

logging () {
    rootHandlers = [ 'java.util.logging.ConsoleHandler', 'java.util.logging.FileHandler', 'org.slf4j.bridge.SLF4JBridgeHandler' ]
}

之后将使用 etc/logback.xml 配置文件。

如 [jul-to-slf4j 桥接文档](http://www.slf4j.org/legacy.html#jul-to-slf4j) 中所述,必须包含 LevelChangePropagator 以消除禁用日志的翻译开销声明:

<configuration debug="true">
  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
  ...
</configuration>

注意,通过将以下内容附加到 etc/logback.xml 配置来删除所有旧 JUL 记录器的配置可能是谨慎的:

<configuration debug="true">
  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
    <resetJUL>true</resetJUL>
</configuration>

7.8. Tigase 高级选项

本部分旨在包括 Tigase 中可用的许多高级配置选项,但可能还没有相关部分来安置他们。

7.8.1. 使用 CAPTCHA 进行带内注册

为了减少对 Tigase XMPP 服务器的虚假或垃圾邮件注册,现在可以将 CAPTCHA 表单添加为带内注册的一部分。 CAPTCHA 将生成一个随机数学方程式,并要求注册新帐户的用户回答它。这可以作为在 config.tdsl 中启用注册的子选项被启用:

'sess-man' {
    'jabber:iq:register' {
        captchaRequired = 'true'
    }
}

3 次不成功的尝试将导致验证码无效,并且客户端将收到错误消息。

7.8.2. 启用空昵称

Tigase 现在可以支持昵称为空的用户。这可以通过在 config.tdsl 中添加以下代码来启用。

'sess-man' {
    'jabber:iq:roster' {
        empty_name_enabled = 'true'
    }
}

7.8.3. 对传送到不可用资源的数据包启用静默忽略

您现在可以让 Tigase 忽略传送到不可用资源的数据包,以避免数据包反弹并产生不必要的流量。您可以在全局范围内,仅在标准消息处理内或在 AMP 组件内使用以下设置进行设置:

在全局范围内:

'sess-man' {
    'silently-ignore-message' = 'true'
}

仅消息处理:

'sess-man' {
    message {
        'silently-ignore-message' = 'true'
    }
}

AMP 组件:

'sess-man' {
    amp () {
        'silently-ignore-message' = 'true'
}

7.8.4. Tigase 中的错误计数机制

在统计信息中添加了一个新处理器来计算 Tigase 返回的错误数。这个名为 error-counter 的处理器将对 Tigase 返回的所有错误进行计数,但默认情况下,如果未被启用,该数字始终为零。其可以在 JMX 中的 ErrorStatistics 下作为 MBean 对象找到,并包含带有 ERROR 且按类型分组的数据包的值。要启用这些对错误数的计数,您必须确保处理器包含在您的 sess-man 配置中:

'sess-man' {
    'error-counter' () {}
}

包括流错误

默认情况下,流 ERROR 数据包不包含在上述计数器中,因为它们是单独处理的。要将其添加到计数器中,以下行必须在您的 config.tdsl 文件中。

c2s {
    'stream-error-counter' () {
        active = true
    }
}

流恢复默认值和最大超时

SteamManagementIOProcessor 现在有一个设置,如果客户端未发送等待时间,其可用于更改等待重新连接的最大超时时间。现在有两种设置可用:

c2s {
    'urn:xmpp:sm:3' {
        'resumption-timeout' = 90
    }
}

config.tdsl 文件中的上述设置会将默认超时时间更改为 90 秒。

c2s {
    'urn:xmpp:sm:3' {
        'max-resumption-timeout' = 900
    }
}

此设置会将流恢复允许的最长时间设置为 900 秒。如果您希望有许多手机连接到您的服务器并希望避免来回发送重复的消息,这可能会很方便。

自动订阅批准

您可以设置一个服务器来自动批准所有用户的状态订阅或名册授权。比如您正在托管机器人并希望自动化该过程。这可以通过以下设置来完成:

'sess-man' () {
    'jabber:iq:roster' {
        'auto-authorize' = 'true'
    }
    'presence-subscription' () {
        'auto-authorize' = 'true'
    }
}

这两个设置默认为 false,您可以一起使用,也可以单独使用。

当它们都被激活时,将遵循以下行为:

  • 发送订阅请求后 - 双方联系人将彼此订阅并添加到彼此的名册中。存在信息将立即在双方之间交换。

  • 在发送带有 unsubscribe 或 unsubscribed 类型的出席信息时,其遵循 RFC 中定义的关于处理这些节的规则(即调整用户/联系人的订阅类型),但不将这些节转发给接收实体以避免向客户端发送任何通知。但是,这会生成名册推送以无缝方式反映用户名册中存在的变化。

  • 简单地将一个项目添加到名册(即使用具有正确语义的 <iq/> 节)也将导致用户和联系人之间的自动订阅,正如上所述。

滥用联系人

Tigase 支持 XEP-0128: Service Discovery Extensions 为服务器和组件发现信息提供附加信息。此功能的重要用途之一是 XEP-0157: Contact Addresses for XMPP Services ,其描述了使用此功能向服务器提供联系信息管理员或滥用响应小组。

要设置滥用联系人详细信息,您应该在 etc/config.tdsl 文件的属性中设置 disco-extensions,并将子属性 abuse-addresses 设置为您的滥用地址 URI(对于电子邮件,您需要添加前缀使用 mailto: 并且对于 XMPP 地址,您需要使用 xmpp 作为前缀):

'disco-extensions' = {
    'abuse-addresses' = [ 'mailto:abuse@localhost', 'xmpp:abuse@localhost' ]
}

推送通知

Tigase XMPP 服务器支持 XEP-0357: Push Notifications 并默认允许用户在其 XMPP 客户端未连接时接收消息通知。

禁用通知

您可以使用以下设置禁用此功能:

'sess-man' {
    'urn:xmpp:push:0' (active: false) {}
}

从通知中删除正文和发件人

如果您希望 Tigase XMPP 服务器不在推送通知中转发消息正文或发件人详细信息,您可以使用以下设置禁用它:

'sess-man' {
    'urn:xmpp:push:0' () {
        'with-body' = false
        'with-sender' = false
    }
}

覆盖通知的正文

如果您希望 Tigase XMPP 服务器在推送通知中覆盖加密消息的转发正文(例如,为了避免指示存在”error”),您可以使用以下设置来实现:

'sess-man' {
    'urn:xmpp:push:0' () {
        'encryptedMessageBody' = "You have a new secure message. Open to see the message"
    }
}

当所有资源都是 AWAY/XA/DND 时为收到的消息启用推送通知

当收到新消息并且接收者的所有资源都处于 AWAY/XA/DND 状态时,Tigase XMPP Server 也可以发送推送通知。要启用这种类型的通知,您需要在默认推送处理器中启用名为 away 的附加推送扩展:

'sess-man' () {
    'urn:xmpp:push:0' () {
        'away' () {}
    }
}

由于用户可能不期望这种行为,并且用户需要兼容的 XMPP 客户端来正确处理此通知(XMPP 客户端需要从服务器检索消息历史记录以获取实际消息),除了在服务器上启用此插件外,XMPP 客户端还需要显式激活此功能。他们可以通过在推送 enable 元素中包含值为 trueaway 属性发送到服务器,如下例所示:

为 away/xa/dnd 帐户启用推送通知。

<iq type='set' id='x43'>
  <enable xmlns='urn:xmpp:push:0' away='true' jid='push-5.client.example' node='yxs32uqsflafdk3iuqo'>
    <x xmlns='jabber:x:data' type='submit'>
        ....
    </x>
  </enable>
</iq>

如果稍后,用户决定为 away/xa/dnd 状态的帐户禁用通知,它可能会禁用推送通知或再次发送节以启用推送通知,但没有设置 away 属性:

<iq type='set' id='x43'>
  <enable xmlns='urn:xmpp:push:0' away='true' jid='push-5.client.example' node='yxs32uqsflafdk3iuqo'>
    <x xmlns='jabber:x:data' type='submit'>
        ....
    </x>
  </enable>
</iq>