11. 使用 Tigase
本节保留了适用于所有 Tigase 服务器版本的文档集,并包含有关一般用途和功能的更多通用或介绍性信息。
配置向导
11.1. 离线消息
Tigase 像任何 XMPP 服务器一样支持为离线用户存储消息,以便他们可以在未登录时接收发送给他们的消息。
默认情况下,Tigase MessageAmp 处理器负责存储离线消息,并且会自动存储离线消息。本指南包含多个部分,用于在全局,每个用户等其他方面设置限制。
此处列出的许多功能都需要使用默认打开的高级消息处理器插件。为确保 AMP 已打开您的系统,请查看您的 config.tdsl 文件并确保您的 plugins 行中有以下内容:
'sess-man' {
    amp () {}
}
当他们在名册交换后首次登录时,消息将被传递给预期的收件人。
11.1.1. 离线消息限制
自 v7.1.0 起,Tigase 现已添加对基于每个用户限制存储的离线消息数量的支持。默认情况下,Tigase 带有为每个用户设置的存储离线消息的限制。默认情况下,barejid-barejid 对的此限制为 100 条脱机消息。这个值可以通过 store-limit 属性改变。要在 barejid-barejid 上付费更改为 200 条消息,请将以下条目添加到 config.tdsl 文件中:
amp {
    'store-limit' = 200L
}
'sess-man' {
    amp () {
        'store-limit' = 200L
    }
}
此设置适用于每个用户。
用户限制
每个用户都可以配置应该为他存储的离线消息的数量。要启用此功能,需要在 config.tdsl 文件中输入以下行:
amp {
    'user-store-limit-enable' = true
}
'sess-man' {
    amp () {
        'user-store-limit-enable' = true
    }
}
用户特定限制的值将存储在 offline-msgs 子节点和 store-limit 键下的 UserRepository 中。数据存储将存储在 tig_pairs 键中,其值和来自 tig_nodes 的适当记录指向该记录。
离线消息超限处理
有两种可能的方式来处理超出限制的离线消息: . error 将带有错误类型的消息发送回发件人。 . drop 在没有通知发件人的情况下丢弃消息。
默认情况下,Tigase 向原始发件人发送一条错误类型为 service-unavailable 的消息,并根据 XEP-0160 正确描述错误。但是,可以更改此行为以更好地满足您的需求。这是通过将以下行添加到您的 config.tdsl 文件来完成的。
'sess-man' {
    amp () {
        'quota-exceeded' = 'drop'
    }
}
这将强制 Tigase 丢弃超过离线消息限制的数据包。
按用户设置限制
希望为 barejid-barejid 对设置存储离线消息的自定义限制的用户需要将以下 XMPP 节发送到服务器:
<iq type="set" id="${random-id}">
  <msgoffline xmlns="msgoffline" limit="${limit}"/>
</iq>
其中:. ${random-id} 是节的随机 ID(可以是任何字符串)。. ${limit} 是离线消息限制的整数值。 其可以设置为 false 以禁用离线消息限制。
作为响应,服务器将返回一个带有结果类型的 iq 节:
<iq type="result" id="${random-id}">
  <msgoffline xmlns="msgoffline" limit="${limit}"/>
</iq>
将存储的离线消息限制设置为 10 的示例
XMPP 客户端向服务器发送以下内容:
<iq type="set" id="aabba">
  <msgoffline xmlns="msgoffline" limit="10"/>
</iq>
服务器响应:
<iq type="result" id="aabba">
  <msgoffline xmlns="msgoffline" limit="10"/>
</iq>
禁用离线消息限制示例
XMPP 客户端向服务器发送以下内容:
<iq type="set" id="aabbb">
  <msgoffline xmlns="msgoffline" limit="false"/>
</iq>
服务器响应:
<iq type="result" id="aabbb">
  <msgoffline xmlns="msgoffline" limit="false"/>
</iq>
11.1.2. 存储没有正文内容的离线消息
Tigase 现在可以存储没有 <body/> 内容的离线消息。
有关协议详细信息,请参阅 XEP-0334。
这可以包括消息回执和带有特定 do-not-store 标签的消息。
添加了支持以设置路径列表和 xmlns 以使用 config.tdsl 中的以下设置触发和放置离线消息的存储:
'sess-man' {
    amp () {
        'msg-store-offline-paths' = [ '/message/received[urn:xmpp:receipts]', '/message/store-offline' ]
    }
}
此示例产生两个设置:
/message/received[urn:xmpp:receipts]结果存储带有
recieved子元素和xlmns设置为urn:xmpp:receipts的消息/message/store-offline导致在不检查 xmlns 的情况下使用
store-offline子元素存储消息。
过滤离线存储
可以设置其他类型的存储来保存:
'sess-man' {
    amp () {
        'msg-store-offline-paths' = [ '/message/store-offline', '-/message/do-not-store' ]
    }
}
config.tdsl 文件中的上述设置将导致:
带有
<store-offline>子元素的消息将被存储而不检查关联的 xmlns。带有
<do-not-store>元素的消息 不会 被保存。
这些中的任何一个都可以根据您的安装进行调整,请记住,’-’ 将停止存储具有指定属性的消息。这些匹配器将检查消息,如果其中任何一个结果为肯定,它们将覆盖默认设置。
例如,如果您想存储带有 <received> 元素的消息,而不是带有 <plain> 元素的消息,您的过滤器将如下所示:
'sess-man' {
    amp () {
        'msg-store-offline-paths' = [ '/message/received', '-/message/plain' ]
    }
}
然而….
备注
上述声明将不起作用 因为它只会存储所有带有 <received> 子元素的消息。
以下语句将正确过滤您的结果。
'sess-man' {
    amp () {
        'msg-store-offline-paths' = [ '-/message/plain', '-/message/received' ]
    }
}
过滤逻辑按从左到右的顺序完成。第一条语句上的匹配项将忽略或覆盖后面列出的匹配项。
11.1.3. 禁用离线消息
如果您希望禁用离线消息的存储,请在 config.tdsl 文件中使用以下行。这不会禁用 AMP 插件的其他功能。
'sess-man' {
    amp () {
        msgoffline (active: false) {}
    }
}
11.2. 最后的活动
Tigase XMPP 服务器支持 XEP-0012: Last Activity 扩展,允许在特定联系人最后处于活动状态时检索信息。默认情况下未启用。
功能本身分为两个插件:
jabber:iq:last-marker- 负责更新有关用户最后活动的信息jabber:iq:last- 负责处理请求以检索最后活动信息 (这取决于jabber:iq:last-marker插件)。
为了启用功能,您应该将两个插件都添加到配置文件中
'sess-man' {
    'jabber:iq:last-marker' (active: true) {
        'jabber:iq:last' (active: true) {}
    }
}
11.2.1. 更新最后活动的内容
默认情况下,标记插件只会更新存在节上的最后一个活动信息。可以控制 <presence/> 和/或 <message/> 是否应该使用各自的选项进行更新:
'sess-man' {
    'jabber:iq:last-marker' (active: true) {
        message = true
        presence = true
    }
}
这些设置将导致更新 <message/> 和 <presence/> 节的最后活动信息
11.2.2. 将所有内容持久化到存储库
为了降低对性能的影响,默认情况下最后一个活动信息不那么频繁地保存到存储库。在具有多个集群节点且用户连接了多个资源的安装中,这可能会产生稍微不太准确的结果。为了获得更准确的结果,您应该将 persistAllToRepository 设置为 true,这将导致所有更新时间都被持久化(请记住,这可能会对存储库造成更大的影响)。
'sess-man' {
    'jabber:iq:last-marker' (active: true) {
        persistAllToRepository = true
    }
}
11.3. Tigase 日志指南
Tigase 具有多个级别的日志记录,可帮助提供有关进程,组件或流量的有针对性的详细信息。在这些文档中,我们将了解 tigase 生成日志的位置,它们包含的内容,以及我们如何根据需要自定义它们。
11.3.1. install.log
此日志文件是安装 Tigase 服务器时生成的文件的基本列表。尽管您可能不需要使用它,但它可以提供一个方便的列表,以查看安装时是否有任何文件未写入您的硬盘驱动器。
11.3.2. derby.log
如果您使用的是与 Tigase 一起安装的 derby 数据库,这则是数据库本身的启动日志。可以在此文件中找到可能与数据库相关的问题。通常,如果一切正常,它就是一个只有 10 行的非常小的文件。它在数据库启动时被覆盖。
11.3.3. etc/config-dump.properties
config-dump.properties 是为 Tigase 和组件中的每个选项列出的所有属性的转储文件。日志行的结构与 Tigase XMPP Server 配置文件 - TDSL 的结构相同。让我们取 admins 的值,列出谁是服务器的管理员。
admins = [ '[email protected]', '[email protected]', '[email protected]' ]
admin 参数是一个字符串数组,列出了 3 个用户。
每次启动 tigase 时都会重写此文件。
11.3.4. logs/tigase.log.#
tigase.log 文件是进行大部分日志记录的地方。可以通过编辑 int.properties 文件中的文件来操作写入这些 long 的规则。要了解如何操作,请参阅本手册的 调试Tigase 部分,了解有关如何打开调试日志记录以及如何操作日志设置的更多详细信息。这些日志的条目采用以下格式:
2015-08-10 13:09:41.504 [main]      Sctipr.init()         INFO: Initilized script command, id: comp-manager, lang:Groovy, ext: groovy
这些日志的格式如下:<timestamp> <thread_name> <class>.<method>    <log_level>: <message> <thread_name>。这可能会有所不同 - 对于组件,它将是 <direction>_<int>_<component name>,对于插件,它将只是插件名称。
让我们看一下日志文件中的另一个示例。
2015-08-10 12:31:40.893 [in_14_muc] InMemoryMucRepository.createNewRoom()   FINE: Creating new room '[email protected]'
进程 ID 有时可能以不同的格式出现,例如 [in_14-muc] ,它指定组件 (muc) 以及进程线程标识符 (14)。如您所见,其他方面的格式几乎相同。
tigase.log.# 文件是 rotated - 这意味着服务器在第一次运行时开始写入 tigase.log.0,并继续转储信息,直到达到日志大小限制。此时,Tigase 将 tigase.log.0 重命名为 tigase.log.1。将创建一个新的 tigase.log.0,并且 Tigase 将开始记录到该文件。当此文件已满时,tigase.log.1 将重命名为 tigase.log.2,tigase.log.0 将重命名为 tigase.log.1。使用此方案,tigase.log.0 将 始终 是您最近的日志。
默认情况下,Tigase 的限制为 10000000 字节或 10MB,文件轮换为 10 个文件。您可以通过编辑 config.tdsl 文件并添加以下行来编辑这些值。
logging {
    java.util.logging.FileHandler {
        count = '15'
        limit = '20000000'
    }
}
这段代码,如果输入 config.tdsl 文件,将文件大小增加到 15,最大文件大小增加到 20MB。请注意,集体日志空间越大,硬盘上活动的扇区数就越多。大的日志块可能会影响系统性能。
当服务器运行时,您可能会在目录中看到一个 tigase.log.0.lck 文件。这只是一个临时文件,一旦完全关闭 Tigase 就会被删除。
11.3.5. logs/statistics.log.#
如果您使用的是未经许可的 Tigase XMPP 服务器副本,统计日志将复制与向 Tigase 发送统计信息相关的任何信息。主要包括LicenceChecker 的输出。编号逻辑将与 tigase.log.# 文件相同。
11.3.6. logs/tigase.pid
tigase.pid 是一个仅包含当前运行 Tigase 的进程 ID 或 PID 的文件。它仅对当前或最近的运行周期有效,并在每次 Tigase 启动时被覆盖。
11.3.7. logs/tigase-console.log
重要
这是最重要的日志文件,其中包含与 Tigase XMPP 服务器操作相关的最基本信息。此文件中的任何错误或异常都极有可能表明服务器操作存在严重问题。
该文件包含与 Tigase 的运行环境相关的信息,并且是服务器本身关于正在加载的内容,何时以及是否遇到任何问题的转储。它将首先加载 Java 类(随后确保 Java 环境存在且正常运行)。然后它将开始加载配置文件,并将默认值添加到尚未自定义的设置中。然后,您可以看到正在加载的所有组件,以及在需要默认值的地方添加的设置。最后,您将看到已加载的所有插件以及其中的任何参数的日志。您可能会在日志中看到诸如 INFO 或 WARNING 之类的标签。尽管它们可能包含重要信息,但程序将继续正常运行其并不太值得关注。
错误标志是您需要注意的问题,因为它们可能会列出阻止 Tigase 或组件正常运行的问题。
备注
Windows 不会创建此文件,而是在命令行中显示输出并且不会转储到文件中。
如果 Tigase 正常关闭,tigase-console.log 将按以下格式添加服务器运行寿命的统计信息。
component/statistic = value
任何可能具有统计信息的组件,无论是否使用,都会在此处放置一个值
如果您要跟踪服务器中的问题,此文件会很方便。
tigase-console.log 在服务器的每个运行会话期间附加。
11.3.8. 日志文件位置
如果您有想要使用的特定目录,也可以更改日志文件的位置。可以通过 config.tdsl 文件中的以下行进行配置:
logging {
    java.util.logging.FileHandler {
        pattern = '/var/log/tigase/tigase.log'
    }
}
此设置将日志文件位置更改为 /var/log/tigase/,所有日志文件都将在其中生成。原始位置的文件将被保留。
11.4. 调试 Tigase
如果出现问题并且您无法找出它没有按预期工作的原因,您可能需要打开更详细的调试选项。
Tigase 是一个 Java 应用程序,它使用 Java 日志库,这使您可以灵活地为选定的 Java 包甚至单个 Java 类切换日志记录。
日志文件存储在 logs/ 目录中。 tigase-console.log 存储基本的日志数据,但是是主要的日志文件。 tigase.log.N 文件保存所有详细的日志条目。因此,这是您在出现问题时应该查看的地方。
11.4.1. 配置
默认情况下,Tigase 已打开旧的 debug = ['server'] 设置,不需要再添加。
然而,人们想看看网络层面发生了什么。那就是服务器发送和接收的内容 - 实际的字符数据。打印所有接收和发送的字符数据的类是:tigase.xmpp.XMPPIOService。要启用此类的所有调试信息,您必须修改调试行:
debug = [ 'xmpp.XMPPIOService' ]
您还可以同时为许多包/类打开调试:
debug = [ 'cluster' , 'xmpp.XMPPIOService' ]
您可能感兴趣的其他软件包是:
io可以打印出在非常低级别的网络级别上发生的事情,包括 TLS/SSL 的东西。xml将打印 XML 解析器调试数据。cluster将打印所有与聚类相关的东西。xmpp.impl将打印加载到 Tigase 服务器的所有插件的日志。
非 Tigase 包
要为您自己的包从不同于 Tigase 的包中启用日志记录,您必须使用另一个可用的选项:
debug-packages = [ your.com.package ]
11.5. 基本系统检查
以前,有一篇关于 高负载系统的 Linux 设置 的配置文章。其描述了为成百上千的在线用户成功运行 XMPP 服务所必需的基本设置。
当然,高负载和高流量系统需要更多的调整和调整。如果您使用 selinux,则必须小心,因为它可能会在高负载下干扰服务。此外,某些防火墙设置可能会导致问题,因为系统可能会确定它受到 DDOS 攻击,并且可以开始阻止传入连接或限制流量。
无论如何,每次部署 XMPP 服务时都需要进行一些基本检查,以确保它能够正常运行。我正在尝试让上面提到的文章保持最新,并添加在使用不同安装时发现的所有设置和参数。 如果您对添加不同的值或不同的参数有一些建议,请告诉我。
如果您想在几个集群节点(5 个甚至 10 个)上运行服务,那么手动检查每台机器并调整这些设置非常耗时,而且很容易忘记。
为了克服这个问题,我开始编写一个 shell 脚本,该脚本将运行所有基本检查并报告发现的问题。理想情况下,它还应该能够为您调整一些参数。
在 Tigase 服务器 scripts/ 存储库中找到一个名为 machine-check.sh 的脚本。它执行文章中的所有基本检查,并在必要时尝试调整它们。 查看代码 并自己运行。
像往常一样,任何意见或建议都非常感谢。
11.6. 添加和管理域 (VHosts)
Tigase XMPP Server 提供了一种易于使用且非常灵活的方式来添加和管理安装时托管的域(vhosts)。
有两种方法可以管理您在服务器上托管的域:
备注
要使用其中任何一种方式,您需要成为服务器的管理员,这意味着您在此 XMPP 服务器上创建了一个 XMPP 帐户,并且您的帐户JID已添加到 Tigase XMPP服务器配置文件中的 管理员列表 中。
11.6.1. 使用Admin UI
首先,您需要打开 Admin UI 网页。默认情况下,管理 UI 已启用并且可在 XMPP 服务器上的路径 /admin/ 的端口 8080 上使用。假设您登录到托管 Tigase XMPP 服务器的同一台机器上,它将在 http://localhost:8080/admin/ 上可用。
当系统提示您输入用户名和密码以登录管理 UI 时,请使用您的 XMPP 管理员帐户的完整 JID 填写用户名,并使用该帐户的密码填写密码字段。提交正确的凭据后,您将可以访问 Admin UI 和 Tigase XMPP Server 配置和管理基于 Web 的界面。
添加新域
要添加新域,您需要打开管理 UI 的 Configuration 部分(通过单击 Configuration 标签,然后选择提及 vhost-man 的 Add new item 位置)。

完成此操作后,您将看到一个需要填写的表格。此表格允许您传递 Domain name 以添加和其他选项(其中一些是高级选项)。

小技巧
以后可以通过修改虚拟主机设置来更改除 Domain name 之外的所有选项。
当您准备好时,请使用表格下方的按钮提交表格。因此,您将看到此操作的结果。如果成功,它会显示 Operation successful 消息,如果出现问题,它会显示错误以帮助您解决遇到的问题。
修改域设置
修改域设置与添加新域非常相似。您需要打开管理 UI 的 Configuration 部分,然后选择提及 vhost-man 的 Update item configuration 位置。

您将看到托管在此 Tigase XMPP 服务器安装上的域列表。从它们中,您应该选择要修改设置的那个。

提交此选择后,您将看到与添加新域时使用的相同的表单。它提供了该域的配置选项和当前使用的值。

现在您应该根据需要调整它们并使用表单下方的按钮提交此表单。
因此,您将看到此操作的结果。如果成功,它会显示 Operation successful 消息,如果出现问题,它会显示错误以帮助您解决遇到的问题。
删除域
从 Tigase XMPP 服务器安装中删除托管域也非常简单。您需要打开管理 UI 的 Configuration 部分,然后选择提及 vhost-man 的 Remove an item 位置。

您将看到托管在此 Tigase XMPP 服务器安装上的域列表。从它们中,选择应该删除的那个。

提交您的选择后,Tigase XMPP 服务器将尝试从托管域列表中删除该域,并将结果显示给您。如果成功,它会显示 Operation successful 消息,如果出现问题,它会显示错误以帮助您解决遇到的问题。
11.6.2. 使用ad-hoc命令
对于有兴趣使用我们的服务来托管自己的 XMPP 域的每个人,我们都有好消息!您不必再要求管理员添加您的域或为您的域添加用户。你可以自己做。
请注意,这是非常新的东西。某些事情可能会出错或可能无法完善。请报告任何问题,通知或建议。
这是指导您完成新功能的指南,并描述了如何在您的域中添加新域和新用户。
您可以从 XMPP 客户端执行所有操作,也可以使用我们的 Web 应用程序连接到服务并执行管理命令。我推荐 Psi 因为它对用于域和用户管理的 XMPP 协议部分提供了出色的支持。您也可以使用其他客户端,但我们只能在您使用 Psi 客户端时提供支持和帮助。
其次,您需要在服务器上拥有一个帐户。这是因为此处描述的所有命令和功能仅对本地用户可用。因此,如果您还没有在我们这里注册域名,请去网站 Tigase.IM 或 Jabber.Today 上注册一个帐户 。
添加新域
在其中一个网站上注册帐户后,使用 Psi 客户端上的帐户连接到 XMPP 服务器。我们将使用以下帐户:green@tigase.im,这用于本指南。
准备好后,右键单击 Psi 名册窗口中的帐户名称以显示上下文菜单。选择 服务发现 元素。

如右侧示例所示,会弹出一个新窗口。服务发现窗口是 XMPP 服务上安装的所有内容应该显示的地方。列表中的大多数元素都是众所周知的传输,MUC 和 PubSub 组件。我们感兴趣的列表中的新内容是 2 个元素:VHost Manager 和 Session Manager。

Tigase 中的 VHost Manager 组件负责管理和控制安装中的虚拟主机。它为系统的所有其他部分提供虚拟主机信息,还允许您添加新主机和删除/更新现有虚拟主机。
Tigase 中的 Session Manager 组件负责管理用户。在大多数情况下是管理在线用户,但它也可以对存储所有用户数据的用户存储库执行一些操作。
选择 VHost Manager 并双击它。出现一个新窗口(可能隐藏在服务发现窗口后面)。该窗口包含另一个菜单,其中包含一些项目:Add…, Remove… and Update…。这些用于添加,删除和更新 VHost 信息。现在,只需选择第一个元素 Add….

单击 Execute,您会看到一个新窗口,您可以在其中输入所有 VHost 配置详细信息。所有字段都应该是不言自明的。暂时为 Other parameters 留一个空白字段。 Owner 是您,即控制域并可以更改域配置设置或可以从服务中删除域的 Jabber ID。 Administrators 字段可以留空,也可以包含逗号分隔的 Jabber ID 列表,供可以管理域内用户的人员使用。您无需将用户名添加到列表中,因为所有者始终可以管理域的用户。

准备就绪后,单击 Finish 按钮。希望一切都完成了。如果出现问题,您可以获得确认一切正常的窗口或打印错误消息的窗口。有什么问题?我决定对服务施加一些限制以防止滥用。限制之一是用户现在可以为自己注册的最大域数为 25。另一个限制是您添加的域必须具有指向我们服务的有效DNS条目。 XMPP 指南描述了有关DNS设置的所有详细信息。如果您需要更多详细信息,请参阅这些说明。
添加新用户
添加新用户进程非常相似,几乎与添加新域相同。但是这一次,我们必须在服务发现窗口中选择 Session Manager。

双击 Session Manager 会出现一个带有 SM 命令列表的窗口。目前,只有一个命令可供域管理员使用 - Add user。我将在未来提供更多命令,我正在等待您的建议。

如果您单击 Execute,则会显示左侧的窗口。相应地填写所有字段,然后按 Finish。

如果一切顺利,您刚刚添加了一个新用户,您应该会看到一个确认操作成功的窗口。如果出现问题,应该会显示一个带有错误消息的窗口。可能的错误也许是您尝试添加已存在的用户,或者您可能尝试为您没有权限的域或不存在的域添加用户。
SSL 证书管理
SSL 证书管理已实施,并且可以在 .pem 格式中操作证书。有关更多详细信息,请参阅文档的 在pem文件中创建和加载服务器证书 部分以获取更多信息。
11.7. Presence转发
你有没有想过在网站上显示你的用户存在状态?或者,也许,您想将 XMPP 服务与您自己的系统集成,并且不仅共享用户的帐户,还共享在线状态?
不仅有可能而且非常简单。您在域控制表单中有一个新选项。
实际上有两个新选项:
Presence转发地址
消息转发地址 - 尚未完全实现
Presence 转发地址可以是任何 XMPP 地址。通常你希望它是一个可以收集用户存在信息的机器人地址。一旦将此选项设置为有效的 XMPP 地址,Tigase 就会在每次用户更改其状态时转发用户的状态。当然,状态会被正常处理,并从联系人列表(名册)中分发给所有人,以及这个特殊地址。它可以是组件或机器人。如果这是连接到常规 XMPP 帐户的机器人,确保 presence 转发地址包含资源部分,并且机器人正在与此资源连接。 否则 presence 将不会传递给机器人。

如屏幕截图所示,有新的输入行,其中包含 presence 转发地址和消息转发地址选项。如您所见,可以为每个域单独指定此选项,因此您可以为每个域设置不同的转发地址。
如果您有自己的 Tigase 安装,也可以全局设置转发地址,并且所有域都可以相同。但是,对于本网站,我们向所有拥有自己域的用户提供此功能,并且可以在每个域的基础上进行设置。
现在,最大的问题。这个怎么用?我在下面附上一个示例代码。只需几行代码,您就可以将命令行机器人作为客户端连接到服务器,该客户端将收集用户的所有存在。下面的代码是一个简单的 Groovy 脚本,它接收状态数据包并将它们显示在控制台上。但是,将用户的存在信息存储在数据库中然后从 Web 应用程序加载它应该很容易。
bot/client 用户使用我们的 JaXMPP2 库,该库包含在 Tigase XMPP 服务器的当前版本中。
您应该能够在 wiki 页面上找到更多代码示例。
package jaxmppexample
import tigase.jaxmpp.core.client.BareJID
import tigase.jaxmpp.core.client.SessionObject
import tigase.jaxmpp.core.client.exceptions.JaxmppException
import tigase.jaxmpp.core.client.observer.Listener
import tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule
import tigase.jaxmpp.core.client.xmpp.modules.presence.PresenceModule.PresenceEvent
import tigase.jaxmpp.j2se.Jaxmpp
final Jaxmpp jaxmpp = new Jaxmpp()
jaxmpp.getProperties().setUserProperty( SessionObject.USER_BARE_JID,
  BareJID.bareJIDInstance( "[email protected]" ) )
jaxmpp.getProperties().setUserProperty(SessionObject.RESOURCE, "presence-collector")
jaxmpp.getProperties().setUserProperty( SessionObject.PASSWORD, "pass" )
jaxmpp.getModulesManager().getModule( PresenceModule.class ).addListener(
  PresenceModule.ContactChangedPresence,  new Listener() {
    public void handleEvent( PresenceEvent be ) {
      def msg = (be.getStatus() != null) ? be.getStatus() : "none"
      println( "Presence received:\t" + be.getJid() + " is now " + be.getShow() +
        " (" + msg + ")" )
    }
  }
)
println( "Loging in..." )
jaxmpp.login()
println( "Waiting for the presence for 10 minutes" )
Thread.sleep( 10 * 60 * 1000 )
disconnect()
11.8. 监视器
实施 Tigase 的监视器是为了帮助 Tigase 关闭已经过时或不活动的连接。有时连接会延迟,可能会丢失数据包或服务中断。一段时间后,如果重新建立该连接,服务器和客户端(或服务器和服务器)将继续运行,就好像什么都没发生一样。但是,这些连接间隙可能会持续更长时间,并且某些安装将依赖操作系统来检测和关闭过时的连接。某些操作系统或环境可能需要长达 2 小时或更长时间才能确定连接是否不良并等待来自外部实体的响应,并且可能未被配置。这不仅会降低性能,还会导致安全问题。为了解决这个问题,我们引入了监视器来监控独立于操作系统和环境的连接,以防止那些断开的连接成为问题。
11.8.1. 设置
无需额外设置,您的 Tigase 版本中已经包含 监视器(只要它是 7.1.0 或更高版本)。按照配置部分中的步骤操作。
11.8.2. 监视器配置
要配置监视器,需要在 config.tdsl 文件中出现或编辑以下行:
'watchdog-timeout' = 70000
'watchdog-delay' = 60000
'watchdog-ping-type' = 'xmpp'
三个设置如下:
'watchdog-timeout'= 70000此设置设置监视器在确定连接可能过时之前将考虑的时间量。此设置将超时设置为 70000 毫秒或 70 秒。'watchdog-delay' = 60000此设置设置监视器执行检查的频率,默认延迟为 60000 毫秒或 60 秒。'watchdog-ping-type'此设置决定当监视器测试活动时发送到组件的 ping 类型。
如果您选择,您可以通过将特定组件添加到组件设置来为特定组件指定单独的监视器设置,例如,如果我们想要更改 Client2Server 设置以包含监视器,请在 config.tdsl 中使用以下行:
c2s {
    watchdog-delay = '1500'
    watchdog-timeout = '3000'
}
如果未设置任何设置,则将使用全局或设置。 watchdog-delay 默认设置为 10 分钟 watchdog-ping-type 默认设置为 XMPP
11.8.3. 逻辑
监视器比较它自己的 ping,并记录往返不同组件,集群连接所需的时间,如果一个变量大于另一个变量,监视器将开始关闭该陈旧连接。这是一个细分:
在每个
watchdog-delay间隔上执行一次连接检查。在此检查期间,会发生两件事
如果最后一次传输时间超过了
max-inactivity-time,则会给出停止服务命令来终止并广播不可用的存在。如果最后一次传输时间低于
max-inactivity-time但超过watchdog-timeout,监视器将尝试发送ping (ofwatchdog-ping-type)。此 ping 可能是两种类型之一(在 config.tdsl 中设置)WHITESPACEping 将产生在任何方向上的最后一次数据传输的时间。XMPPping 将产生最后收到的 xmpp 节的时间。
如果第二个选项为真,则连接将保持打开状态,并且在
watchdog-delay时间到期后将开始另一次检查。
例如,让我们把它画出来并得到一个视觉表示
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--
     |     |     |     |     |     |     |     |     |     |     |
---+----------------------------------------------------------------
   1 2     3     4     5     6
---*-*-----*-----*-----*-----------
此行表示执行检查的频率。每个
-(破折号)为 10 秒,因此每 60 秒检查一次('watchdog-delay' = 60000)这一行是客户端活动,这里客户端在 40 秒时发送了一条消息(由
+标记)并且已经空闲。以下行表示监视器逻辑,超时时间为 120 秒,最大不活动超时时间为 180 秒:
'watchdog-timeout' = 120000 c2s { 'max-inactivity-time' = '180000' } (timeout at 120 seconds and max inactivity timeout at 180 seconds)
如何执行检查:
30 秒 - 此时 上次传输 或 上次接收 时间已更新。
60 秒 - 监视器运行 - 它检查连接并说:_ok,上次客户端传输是 20 秒前 - 但其低于不活动(所以不要断开连接)和超时(所以不要发送 ping)值。
120 秒 - 第二次检查 - 上次传输是 100 秒前 - 仍然低于两个值 - 什么都不做。
180 秒 - 第三次检查 - 上次传输是 160 秒前 - 低于不活动但大于延迟 - ping 它已发送。
240 秒 - 第 4 次检查 - 上次传输是 220 秒前 - 客户端仍然没有响应,监视器将空闲时间与
max-inactivity-timeout进行比较,发现它更大,连接终止。300 秒 - 再次运行监视器,但由于连接已终止,因此没有 XMPP 会话来检查该特定客户端。
小技巧
连接可能已断开,这可以在发送 ping 期间检测到,并且连接将在第 4 步被切断,而不是等待第 5 步。注意 这可能会导致 JVM 抛出异常。
备注
全局设置可能并不适合每种设置。由于每个组件都有自己的 max-inactivity-time 设置,您可能会发现有必要设计自定义监视器设置,或编辑不活动时间以更好地满足您的需求。以下是具有默认设置的组件的简短列表:
bosh {
    'max-inactivity-time' = 600L
}
c2s {
    'max-inactivity-time' = 86400L
}
'cl-comp' {
    'max-inactivity-time' = 180L
}
s2s {
    'max-inactivity-time' = 900L
}
ws2s {
    'max-inactivity-time' = 86400L
}
重要
再次记住,为了让监视器正常工作,max-inactivity-time 必须比 watchdog-timeout 设置长
测试
tigase.log.0 文件可以透露一些关于监视器的信息以及它是如何工作的(或者它可能如何与您的设置发生冲突)。为此,请在 config.tdsl 文件中输入以下行:
debug = [ 'server', 'xmpp.init' ]
这将为您的日志设置调试模式,并启用有关 Tigase 正在做什么的更多信息。为简单起见,这些日志被截断。让我们根据日志看一下上述场景:
第二阶段。
2015-10-16 08:00:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: [email protected]/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: [email protected]/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: [email protected]/mobile, sinceLastTransfer: 20,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP
第三阶段。
2015-10-16 08:01:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: [email protected]/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: [email protected]/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: [email protected]/mobile, sinceLastTransfer: 100,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP
第四阶段。
2015-10-16 08:02:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: [email protected]/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: [email protected]/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: [email protected]/mobile, sinceLastTransfer: 160,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP
2015-10-16 08:02:00.697 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: [email protected]/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: [email protected]/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: [email protected]/mobile, sending XMPP ping from=null, to=null, DATA=<iq from="xmpp.domain.com" id="tigase-ping" to="[email protected]/mobile" type="get"><ping xmlns="urn:xmpp:ping"/></iq>, SIZE=134, XMLNS=null, PRIORITY=NORMAL, PERMISSION=NONE, TYPE=get
第五阶段。
2015-10-16 08:03:00.000 [Watchdog - c2s]   ConnectionManager$Watchdog$1.check()  FINEST: Testing service: [email protected]/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: [email protected]/192.168.0.150_5222_192.168.0.201_50368 Socket[addr=/192.168.0.201,port=50368,localport=5222], jid: [email protected]/mobile, sinceLastTransfer: 100,000, maxInactivityTime: 180,000, watchdogTimeout: 120,000, watchdogDelay: 60,000, watchdogPingType: XMPP
2015-10-16 08:03:00.248 [pool-20-thread-6]  ConnectionManager.serviceStopped()  FINER:  [[c2s]] Connection stopped: c2s@xmpp./domain.com/192.168.0.150_5222_192.168.0.201_50368, type: accept, Socket: TLS: c2s@lenovo-z585/192.168.0.150_5222_192.168.0.201_50368 Socket[unconnected], jid: [email protected]
2015-10-16 08:03:00.248 [pool-20-thread-6]  ClientConnectionManager.xmppStreamClosed()  FINER: Stream closed: [email protected]/192.168.0.150_5222_192.168.0.201_50368
11.9. 技巧和窍门
该部分包含一些简短的技巧和技巧,可帮助解决与服务器管理和维护相关的不同类型的问题。
11.9.1. Tigase 提示:检查运行时环境
最近发生的事情是,我们非常努力地解决了其中一个 Tigase 安装上的一些烦人的问题。但是不管我们怎么做,上传新版本并重新启动服务器后问题仍然存在。它在我们的开发环境中运行良好,但在目标系统上却没有。
事实证明,由于目标系统上的特定环境设置,无论上传什么更新,总是启动旧版本的 Tigase 服务器。我们最终通过注意到日志没有在正确的位置生成定位了问题。这导致我们发现了问题:环境设置不当。
检查用于启动 Tigase 服务器的所有环境设置的最佳方法是使用… check 命令行参数:
$ ./scripts/tigase.sh check etc/tigase.conf
Checking arguments to Tigase
TIGASE_HOME = .
TIGASE_JAR = jars/tigase-server.jar
TIGASE_PARAMS = etc/tigase.conf
TIGASE_CONFIG = etc/tigase.xml
TIGASE_RUN = tigase.server.XMPPServer -c etc/tigase.xml --property-file etc/init.properties
TIGASE_PID = ./logs/tigase.pid
TIGASE_OPTIONS = --property-file etc/init.properties
JAVA_OPTIONS = -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 \
    -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver \
    -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m
JAVA = /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java
JAVA_CMD =
CLASSPATH = ./jars/tigase-server.jar:./libs/jdbc-mysql.jar:./libs/jdbc-postgresql.jar:\
    ./libs/tigase-extras.jar:./libs/tigase-muc.jar:./libs/tigase-pubsub.jar:\
    ./libs/tigase-utils.jar:./libs/tigase-xmltools.jar
TIGASE_CMD = /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java \
    -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 \
    -Djdbc.drivers=com.mysql.jdbc.Driver:org.postgresql.Driver \
    -server -Xms100M -Xmx200M -XX:PermSize=32m -XX:MaxPermSize=256m \
    -cp ./jars/tigase-server.jar:./libs/jdbc-mysql.jar:./libs/jdbc-postgresql.jar:\
    ./libs/tigase-extras.jar:./libs/tigase-muc.jar:./libs/tigase-pubsub.jar:\
    ./libs/tigase-utils.jar:./libs/tigase-xmltools.jar tigase.server.XMPPServer \
    -c etc/tigase.xml --property-file etc/init.properties
TIGASE_CONSOLE_LOG = ./logs/tigase-console.log
在我们的例子中,TIGASE_HOME 被设置为一个指向旧版本服务器文件的固定位置。快速的 check 命令可能是一个实时的节省程序。
从 Web 浏览器连接到 Tigase XMPP 服务器的最佳实践
目前我们有两种方法可以从 Web 浏览器连接到 Tigase XMPP 服务器:
BOSH(同步 HTTP 上的双向流)
WebSocket(基于 WebSocket 的 XMPP)
您将找到有关这些连接到 Tigase XMPP 服务器的方法的更多信息,其中包含一些有用的提示。
11.9.2. BOSH
XEP-0124 中指定的 BOSH 协议是第一个被定义允许从 Web 浏览器与 XMPP 服务器建立 XMPP 连接的协议,因为该协议广泛被支持和使用。在单服务器模式下也很容易使用。它在 Tigase XMPP 服务器中默认启用,可在端口 5280 使用。
在集群模式下,我们可以使用负载均衡器部署它,保证来自 Web 浏览器的每个 BOSH 连接都将转发到同一个 Tigase XMPP 服务器实例。所以在集群模式下,如果我们有两个 XMPP 服务器 t1 和 t2,其托管域是 example.com,我们需要有一个负载均衡器,它将响应对域 example.com 的 HTTP 请求,并将来自同一 IP 地址的所有请求转发到集群的同一节点(即来自 192.168.122.32 的所有请求应始终转发到节点 t1) 。
提示 #1 - 没有负载均衡器的集群模式下的 BOSH
还有一种方法可以在不启用负载平衡器的情况下使用 BOSH。在这种情况下,XMPP 客户端需要有更多关于所有可用集群节点的逻辑和知识(节点名称将识别来自 Internet 的特定集群节点)。利用这些知识,XMPP 客户端应该从可用节点列表中随机选择一个节点,并始终与该特定节点建立 BOSH 连接。如果由于网络连接问题导致 BOSH 连接失败,XMPP 客户端应从剩余可用节点列表中随机选择其他节点。
解决方案:
Tigase XMPP 服务器默认通过在 BOSH 响应的 body 元素中发送额外的 host 属性来为此问题提供服务器端解决方案。作为该属性的值 Tigase XMPP Server 将服务器集群节点的域名发送到客户端连接到的以及应该打开该会话的下一个连接。可以通过在 etc/config.tdsl 配置文件中添加以下行来禁用此自定义功能:
bosh {
    'send-node-hostname' = false
}
例子:
我们有服务器 t1.example.com and t2.example.com,它们是集群托管域 example.com 的节点。 Web 客户端从 Web 服务器检索集群节点列表,然后当它需要连接到 XMPP 服务器时,它从检索到的集群节点列表(即 t2.example.com)中随机选择主机并尝试使用 BOSH 协议进行连接托管 t2.example.com,但它应该发送 example.com 作为它尝试连接的服务器的名称(example.com 应该是 XMPP 流的 to 属性的值)。
11.9.3. WebSocket
WebSocket 协议是一种新的标准化协议,当前许多版本的浏览器都支持它。目前有一个协议草案 draft-ietf-xmpp-websocket-00 其描述了使用 WebSocket 连接到 XMPP服务器。 WebSocket 协议连接到 XMPP 服务器的 Tigase XMPP Server 实现非常接近本规范草案。默认情况下,Tigase XMPP 服务器启用了 XMPP-over-WebSocket 协议,但未在端口 5290 上加密。要使用此协议,您需要使用支持 XMPP-over-WebSocket 协议的库。
提示 #1 - 加密的 WebSocket 连接
可以在 Tigase XMPP 服务器中启用加密的 WebSocket 连接。为此,您需要将以下行添加到 etc/config.tdsl 配置文件:
ws2s {
    connections {
        ports = [ 5290, 5291 ]
        5290 {
            socket = 'ssl'
            type = 'accept'
        }
        5291 {
            socket = 'plain'
            type = 'accept'
        }
    }
}
在此示例中,我们在端口 5290 上启用了 WebSocket 端点,其允许未加密的连接,并在端口 5291 上启用了加密的 WebSocket 端点。由于这是 TLS/SSL 连接(无 STARTTLS),它使用安装在 Tigase XMPP 服务器实例中的默认证书。该证书位于 certs/default.pem 中。
备注
非默认端口没有默认配置。必须配置 443 以外的所有端口。
提示 #2 - 加密的 WebSocket 连接 - 处理多个虚拟主机
如提示 #1 中所述,WebSocket 端点是普通的 TLS/SSL 端口,因此它始终为 Tigase XMPP 服务器实例提供默认证书。如果我们托管单个域并且默认证书匹配我们的域,那也没关系。但是如果我们托管多个域,如果我们的默认证书是域 example2.com ,我们不能使用 wss://example1.com:5291/ 连接 URL。在这种情况下,建议对可以从 Internet 访问服务器的域使用默认证书。此域应标识此服务器,这样此域不会指向群集的两个节点。在我们为每个集群节点部署单独的证书之后,我们应该遵循与 BOSH 的提示 #1 相同的提示。我们基于 Web 的 XMPP 客户端应该了解集群的每个节点,当它需要连接时,它应该从可用集群节点列表中随机选择一个节点,并尝试使用包含服务器名称的连接 URL 进行连接从互联网上识别。
例子:
我们有服务器 t1.example1.com 和 t2.example1.com,它们是托管域 example2.com 中集群的节点。我们的每个节点都包含默认 SSL 证书,其域名与集群节点匹配。 Web 客户端从 Web 服务器检索集群节点列表,然后当它需要连接到 XMPP 服务器时,它从检索到的集群节点列表(即 t2.example1.com )中随机选择主机并尝试使用 WebSocket 加密协议进行连接使用以下 URL : wss://t2.example1.com:5291/ 托管 t2.example1.com 。连接后,客户端仍应发送 example2.com 作为它尝试连接的服务器的名称(example2.com 应该是 XMPP 流的属性值)。这将允许浏览器验证证书,因为它将与浏览器连接到同一个域,并且它将允许 XMPP 客户端连接到域 example2.com,这是托管的虚拟主机之一。
11.10. 许可
随着 v7.1.0 的发布,用户和商业客户现在可以自己注册并从我们的服务器请求许可证文件。此过程使每个人都可以在需要时更轻松地获得有效的许可证文件。不想注册的用户无需注册。但是,如果您使用 Tigase ACS 或其他商业软件,则需要注册。
警告
如果在给定的时间段内没有收到安装 ID 或许可证,Tigase XMPP 服务器将在许可证检查期间关闭。
再次重申,Tigase XMPP Server 在 AGPLv3 下仍可免费使用,免费用户无需注册。
备注
商业组件需要使用许可证。
11.10.1. 注册许可证
目前有两种方法可以注册 Tigase 商业产品的许可证。 最简单和推荐的方法是使用内置的自动注册功能。但是,如果您的安装对网络连接有限制,您也可以通过门户网站注册。
自动注册(推荐)
一旦在 Tigase XMPP 服务器上激活了商业组件,程序就会从我们的服务器中检索 Installation ID,并在您的 etc/ 目录中创建一个名为 installation-id 的文件,其中包含您实例的 安装 ID 的目录。安装 ID 是使用完整的集群映射生成的,并且同一集群中的所有机器都应具有相同的 安装 ID。然后,此 安装 ID 将与服务器详细信息一起发送到许可证服务器,并且将在您的 tigasedir/etc 目录中制作适当的许可证文件。当许可证到期时,此机制将自动更新您的许可证文件。
手动
小心
此方法应仅在无法使用 自动注册(推荐) 的极端情况下使用。
如果您不想使用自动方法,您可能决定使用我们的门户网站生成许可文件。离线安装可以通过三个步骤从我们的门户网站获取 安装ID:注册、生成哈希和获取许可证文件。
生成安装 ID
对于离线安装,您可以从以下地址获取 安装 ID:https://license.tigase.software/register。
数据字段:
Customer name: 用于识别机器的公司或用户名。多个集群或服务器可以具有相同的客户名称。VHosts: 您将在此节点上使用的VHosts的逗号分隔列表。注意:这些字段区分大小写!Legacy license hashes: 复制为所有旧版许可证生成的摘要哈希 - 它在启动后在etc/tigase-console.log中可用(如果存在此类许可证)。Captcha question: 输入此表格的基本数学答案以证明您不是机器人。
下一页将为您提供安装 ID,如下所示:
1TCICGG7K8AS2JSSEVMDA9QOLR4NVLJSR
编辑您的 config.tdsl 文件并添加您的安装 ID
'installation-id' = '1TCICGG7K8AS2JSSEVMDA9QOLR4NVLJSR'
请注意,一旦安装许可证文件被安装并由服务器验证,installation-id 文件将自动生成。
获取服务器代码
获得 安装ID 后,您将需要生成服务器代码。这可以通过访问管理UI页面并导航到许可证部分来完成。到达那里后,单击检索代码以获取许可证。选择您要为其生成代码的组件,然后单击提交。您将看到根据您的服务器配置填写的安装ID,模块,VHosts字段。复制代码字段的内容并继续下一部分。
获取许可证文件
打开一个新的浏览器并导航到这个地址:https://license.tigase.software/retrieve,在那里,将最后一步生成的代码粘贴到该字段中,然后单击提交。之后,系统会提示您下载许可证文件,将此文件放在您的 etc/ 文件夹中并重新启动服务器,您的许可证现在已激活并安装在您的服务器上。
如果您被提供手动生成的许可证,您需要将其放在同一个 etc/ 目录中,命名为 <component_name>.license (例如:etc/acs.license)
11.10.2. 如果我不使用许可证文件或它已过期会怎样?
Tigase允许在没有许可证的情况下使用商业产品,但必须完成验证过程,否则服务器将关闭。在运行的第一个小时内,Tigase将检查许可证文件的存在和有效性。如果没有找到,或者它无效或过期,服务器将联系Tigase主服务器以获得一个有效的文件。
将通过 https(端口 443)与 license.tigase.software 进行通信,以验证许可证或下载新许可证。
11.10.3. 演示模式
如果找不到有效的许可证,Tigase 将恢复为演示模式。大多数功能将可以被使用,但有一个事先声明。该服务器的统计信息有关您的服务器及其使用情况将发送到 https://stats.tigase.software。详细信息在下一节中。如果无法发送此信息,服务器将假定未经授权使用并关闭。
已发送统计信息
如果发生以下所有情况,您的服务器的统计信息可能会发送到 Tigase 服务器:
您正在使用商业 Tigase 组件。
您已经注册了一个
installation-id。您当前没有运行 Tigase 商业组件的许可证。
如果存在这些情况,统计数据将发送到我们的服务器,并在您的日志中发布警告。以下是一个示例告诉你哪些信息将被发送。
备注
下面的文本已被更好地格式化以提高可读性,但并不反映发送到 Tigase 的实际文本。
<statistics version="1">
    <domain>xmppserver</domain>
    <timestamp>2016-06-23T17:16:24.777-0700</timestamp>
    <vhosts>
        <item>vhost1.xmppserver.com</item>
    </vhosts>
    <uptime>308833</uptime>
    <heap>
        <used>30924376</used>
        <max>1426063360</max>
    </heap>
    <cluster>
        <nodes_count>1</nodes_count>
    </cluster>
    <users>
        <online>0</online>
        <active>0</active>
        <max_today>1</max_today>
        <max_yesterday>0</max_yesterday>
    </users>
    <additional_data>
        <components>
            <cmpInfo>
                <name>amp</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.AmpComponentClustered</class>
            </cmpInfo>
            <cmpInfo>
                <name>bosh</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.BoshConnectionClustered</class>
            </cmpInfo>
            <cmpInfo>
                <name>c2s</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.ClientConnectionClustered</class>
            </cmpInfo>
            <cmpInfo>
                <name>cl-comp</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.ClusterConnectionManager</class>
            </cmpInfo>
            <cmpInfo>
                <name>eventbus</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.disteventbus.component.EventBusComponent</class>
            </cmpInfo>
            <cmpInfo>
                <name>http</name>
                <title>Tigase HTTP API component: Tigase HTTP API component</title>
                <version>1.2.0-SNAPSHOT-b135/27310f9b-7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.http.HttpMessageReceiver</class>
            </cmpInfo>
            <cmpInfo>
                <name>monitor</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.monitor.MonitorComponent</class>
            </cmpInfo>
            <cmpInfo>
                <name>muc</name>
                <title>Tigase ACS - MUC Component</title>
                <version>1.2.0-SNAPSHOT-b62/74afbb91-2.4.0-SNAPSHOT-b425/d2e26014</version>
                <class>tigase.muc.cluster.MUCComponentClustered</class>
                <cmpData>
                    <MUCClusteringStrategy>class tigase.muc.cluster.ShardingStrategy</MUCClusteringStrategy>
                </cmpData>
            </cmpInfo>
            <cmpInfo>
                <name>pubsub</name>
                <title>Tigase ACS - PubSub Component</title>
                <version>1.2.0-SNAPSHOT-b65/1c802a4c-3.2.0-SNAPSHOT-b524/892f867f</version>
                <class>tigase.pubsub.cluster.PubSubComponentClustered</class>
                <cmpData>
                    <PubSubClusteringStrategy>class tigase.pubsub.cluster.PartitionedStrategy</PubSubClusteringStrategy>
                </cmpData>
            </cmpInfo>
            <cmpInfo>
                <name>s2s</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.server.xmppserver.S2SConnectionManager</class>
            </cmpInfo>
            <cmpInfo>
                <name>sess-man</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.SessionManagerClustered</class>
                <cmpData>
                    <ClusteringStrategy>class tigase.server.cluster.strategy.OnlineUsersCachingStrategy
                    </ClusteringStrategy>
                </cmpData>
            </cmpInfo>
            <cmpInfo>
                <name>ws2s</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.WebSocketClientConnectionClustered</class>
            </cmpInfo>
            <cmpInfo>
                <name>vhost-man</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.vhosts.VHostManager</class>
            </cmpInfo>
            <cmpInfo>
                <name>stats</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.stats.StatisticsCollector</class>
            </cmpInfo>
            <cmpInfo>
                <name>cluster-contr</name>
                <title>Tigase XMPP Server</title>
                <version>7.1.0-SNAPSHOT-b4226/5e7210f6 (2016-06-01/23:15:52)</version>
                <class>tigase.cluster.ClusterController</class>
            </cmpInfo>
        </components>
        <unlicencedComponenents>
            <ComponentAdditionalInfo name="acs"/>
        </unlicencedComponenents>
    </additional_data>
</statistics>
11.10.5. 手动模式
如果您无法通过所需端口(端口 443 上的https)打开与 stats.tigase.software 或 license.tigase.software 的通信,您可以请求使用手动模式。手动模式需要Tigase创建要在本地机器上使用的许可证文件。这个必须和上面的信息放在同一个文件夹里,除非License失效或过期,否则License检查系统不会寻求通信。
11.11. Tigase聚类
Tigase聚类允许使用多个服务器来统一交付,从客户或用户的角度来看,是一个统一的平台。为何应该使用集群有两个典型的原因:
高可用性
By using clustering, services can be provided with a high reliability and redundancy. By using a network of multiple servers, content or services can be served on any of the clustered servers maintaining a consistent uptime without relying on one machine.
负载均衡
This type of cluster helps to distribute a workload over a number of servers to reduce bottlenecking from heavy resource loads on a particular server.
使用Tigase,您不必在两者之间做出选择!
Tigase 聚类 提供 完全冗余 和 自动负载平衡 其允许在运行时通过简单的配置添加新节点。所有这些都没有对资源消耗造成严重负担。
所有基础组件都支持集群配置,并且部分组件可以开启或关闭。
11.11.1. 配置
要在Tigase服务器上启用集群,请在 config.tdsl 文件中使用以下行:
'cluster-mode' = true
就这些!
自定义端口
您可以为集群组件自定义端口,只需确保每个集群服务器也具有相同的设置,以便它们可以通信。
cl-comp {
    connections {
        4250 {}
        3540 {}
    }
}
您可以微调每个端口配置,但这通常不是必需的。
自定义端口配置
每个端口都有自己的详细信息,可以通过以下端口进行操作。再次强调 这是可选的
'cl-comp' {
    connections {
        4250 {
            ifc = [ '*' ]
            'remote-host' = 'localhost'
            socket = 'plain'
            type = 'accept'
            connections {
                tls {
                    required = false
                }
            }
        }
    }
}
多节点配置
每个节点都应该有 'cluster-mode' = true 以启用您希望连接到的集群。他们将自动发现其他节点以连接到VIA Server到Server的流量。添加或删除的节点将定期更新。
流量管制
您可以使用几个选项自定义集群服务器之间的流量。
cm-ht-traffic-throttling
此设置将控制通过非用户连接发送的字节数。即服务器到服务器或S2S连接。
'cm-ht-traffic-throttling' = 'xmpp:25k:0:disc,bin:200m:0:disc'
格式如下:{traffic-type}:{maximum-traffic}:{max-lifespan-traffic}:{action}
- 流量类型
 指定控制的流量类型。这可以是 XMPP 或 bin。XMPP限制传输的数据包数量,而bin限制传输的字节数。
- 最大流量
 指定一分钟内可以发送多少字节或数据包。
- 流量最大寿命
 指定在连接的生命周期内可以发送多少字节或数据包。0表示无限制。
- 操作
 指定要采取的操作,可以是 disc 断开连接,或 drop 其将丢弃任何超过阈值的数据。
cm-see-other-host
这允许通过选择 SeeOtherHostIfc 实现来特定使用负载平衡机制。有关更多详细信息,请参阅 Tigase负载平衡 文档。
11.11.2. 旧配置方法
虽然这些选项仍然可用,但这些设置可能不太可靠。仅当您需要自动集群模式无法满足的特定设置时使用。
指定特定节点
您仍然可以使用在每台服务器上指定每个节点的旧方法。服务器3需要以下设置
'cluster-nodes' = [ 'serv1.xmpp-test.org' , 'serv2.xmpp-test.org' ]
服务器2需要
'cluster-nodes' = [ 'serv1.xmpp-test.org' , 'serv3.xmpp-test.org' ]
等等…
但是,我们不建议这样做。
密码和端口配置
如果需要,您可以指定特定集群服务器的密码和端口。为此,您需要将{password}:{port}添加到域中,如下例所示:
'cluster-nodes' = [ 'serv1.xmpp-test.org:domainpass:5600' ]
11.11.3. 检查集群连接
设置集群后,您可能需要验证集群是否正常运行。现在可以通过两种方式完成 - 首先检查集群节点之间是否建立了实际的网络连接。另一种是检查服务器的内部状态。
已建立的连接
有多种方法可以检查打开的连接,最简单的一种是使用命令行。(Tigase使用端口 5277 进行集群连接)
Linux
$ lsof -iTCP:5277 -sTCP:ESTABLISHED -P -n
Windows
C:\WINNT>netstat -anp tcp | find ":5277 "
连接的集群节点(使用XMPP)
通过XMPP协议验证集群连接性需要任何 XMPP客户端能够使用 XEP-0030: Service Discovery。请务必记住,只有管理员(其JID配置为管理的用户)才有访问权限。
Psi XMPP客户端
出于本指南的目的,将使用 Psi 客户端。成功配置并连接到具有管理权限的帐户后,我们需要从应用程序菜单或特定帐户的上下文菜单访问 Service Discovery:

在 Service Discovery 窗口中,我们需要找到 Cluster Connection Manager 组件。展开组件的树节点后,所有集群节点的列表将显示当前状态(已连接 或 已断开)。节点列将包含集群节点的实际主机名:

11.12. 匿名用户和身份验证
要支持匿名用户,您必须首先在您的服务器上启用匿名身份验证。
11.12.1. 匿名认证
Tigase Server在某些场景下可以通过SASL-ANONYMOUS支持匿名登录。这可以通过调整 Anonymous enabled 选项在每个VHost基础上启用,正如 添加和管理域(VHosts) 中所述,默认情况下此设置为false,因为 SASL-ANONYMOUS可能并不完全安全,因为用户无需事先许可(用户名和密码)即可连接。
11.12.2. 匿名用户功能
要匿名连接到您的服务器,您必须使用支持匿名身份验证和用户的客户端。使用服务器名称作为用户名连接到服务器,没有密码。例如,要匿名连接到 xmpp.example.com,请使用以下凭据,
用户名:xmpp.example.com 密码:
在这种模式下,所有登录信息都存储在内存中,以后无法检索。
匿名身份验证的其他功能
临时Jid在登录/注销时被分配和销毁。
匿名用户无法访问数据库
匿名用户无法在服务器外部进行通信(使用s2s连接)
匿名用户对每个用户生成的流量有默认限制。
匿名重新连接
在我们的JaXMPP服务器等产品上,使用SASL-ANONYMOUS连接的用户可以使用cookie管理重新连接到现有会话。但是,可以使用 Bosh Session Cache 改进和扩展重新连接,它允许将会话存储在内存中而不是使用客户端数据来重新连接。
11.13. Tigase中的脚本支持
Tigase服务器支持4.3.1及更高版本的脚本语言。这些页面详细描述了此功能如何创建新脚本,将它们上传到服务器并执行它们。该指南还包含带有代码示例的API描述。
备注
Tigase服务器以其非常低的内存消耗而闻名,并且可以在不到10MB的RAM内存下成功运行。但是,向Tigase服务器添加对任何非标准(默认)语言的脚本支持会显著增加安装的内存需求。如果您启用Python,Scala或任何其他非标准语言,您不能期望Tigase服务器在10MB RAM系统上运行。
11.13.1. 脚本介绍 - Hello World!
本文档是描述Tigase服务器中的脚本支持系列的第一篇,展示了如何加载,安装,更新和调用脚本。它还包含对脚本API的介绍以及第一个 Hello world! 示例。
自Tigase版本 4.3.1 起,服务器支持管理员命令和标准命令的脚本。
理论上可以使用许多不同的语言编写脚本,唯一的要求是安装该语言的支持 JSR-223 。更多详细信息可在 Java scripting project site 上找到。
在实践中,某些语言比其他语言得到更好的支持,目前我们推荐 Groovy。然而,以下语言也被证实可以工作: Scala, Python 和 Ruby。 tigase-server GitHub 包含这些语言的一些示例。
备注
默认的Tigase安装只包含Groovy的库。添加对不同语言的支持就像将几个JAR 文件复制到Tigase libs/ 目录一样简单。
本指南中提供的所有示例也可以在Tigase SVN存储库中的目录中作为即用型脚本使用:src/main/groovy/tigase/admin。
该脚本仅使用标准XMPP扩展,绝不具体到任何特定解决方案。我们使用并更喜欢Psi客户端。整个指南和所有屏幕截图都是使用Psi客户端创建的。但是,您也可以使用任何其他支持这些扩展的客户端。由于整个事情都是基于服务发现和临时命令,因此您需要一个对这两个功能都有良好支持 XMPP客户端。
要遵循该指南并运行您需要的所有示例,您需要安装Tigase服务器版本4.3.1或更高版本,并且您必须以管理员身份连接到服务器。
在运行时加载脚本
所有脚本内容通常基于Tigase服务器中的服务发现和临时命令。

因此,首先要做的是浏览正在运行的服务器上的服务发现。您收到的结果将取决于您的安装和已安装的组件。
现在最有趣的是所有在其节点部分带有”http://jabber.org/protocol/admin”的项目。您可能已经加载了一些脚本,但是有两个用于脚本管理的命令。它们的名称足以描述自己:New command script 和 Remove command script。
第一个用于添加新脚本或更新现有脚本,第二个用于从服务器中删除脚本。
要添加新脚本,您只需执行 New command script。在Psi中,这是通过双击服务发现列表中的元素来完成的。

上面的屏幕截图显示了为加载脚本设置的几个选项:
- 描述
 是在服务发现窗口中显示为脚本名称的内容。其中放什么东西没有特别的限制。
- 命令id
 是脚本的唯一 ID(管理命令)。这是节点部分中”http://jabber.org/protocol/admin”之后显示的内容。这需要是独一无二的,否则现有的脚本会被覆盖。
- 语言
 您的安装支持的所有脚本语言的下拉列表。 Tigase自动检测所有脚本语言库并在此处列出。因此,您只需为您的脚本选择正确的语言。
- 脚本文本
 只是您的脚本内容。
当您的脚本准备好并且所有字段都设置正确时,只需按”Finish”按钮,您应该会收到一条消息,确认脚本已成功加载。

在本指南中,我们将创建一个用Groovy编写的简单”Hello world”脚本。它的作用是显示一个带有消息的窗口(临时命令结果):”Hello admin, how are you?”。
它使用下面逐行描述的基本脚本API:
它导入基本的Tigase类。
设置一个局部变量
p,它指向一个带有从客户端接收到的数据的packet变量。创建一个
res变量,它是发送回客户端(管理员)的响应。对客户端的响应是result类型。其他可能的类型将在后面介绍。我们在这里对临时命令进行操作,因此脚本使用Tigase实用程序类来设置/检索命令参数。它设置窗口标题和显示给用户(管理员)的简单消息。
最后一行返回新数据包作为脚本执行结果。
第一个非常简单的版本如下所示:
import tigase.server.*
def p = (Packet)packet
def res = p.commandResult(Command.DataType.result)
Command.addTitle(res, "Hello World Script")
Command.addInstructions(res, "Hello admin, how are you?")
return res
执行脚本
成功加载脚本后,您将不得不重新加载/刷新服务发现窗口,该窗口现在应该在列表中再显示一个元素。

如您所见,脚本名称设置为您在脚本加载窗口中输入的 “Description” - “Hello world script”。如果脚本ID设置为”hello”,则命令节点设置为:”http://jabber.org/protocol/admin#hello”。
要执行脚本,您只需双击脚本名称(如果您使用任何其他客户端,请单击执行命令)。
结果,您应该会看到一个类似于下面显示我们消息的屏幕截图的简单窗口。

脚本中的交互
只显示一条消息非常好,但在大多数情况下并不是很有用。通常,您需要向用户询问更多数据或参数,然后才能执行任何实际程序。
因此,在大多数情况下,管理员脚本必须显示一个带有输入字段的新窗口,要求用户提供更多数据。在本文档中,我们提供了非常简单的示例,这只是一个介绍,所以让我们在显示问候语之前询问管理员名称。

要向用户询问更多信息,我们必须使用更多代码扩展上面的示例:
import tigase.server.*
def p = (Packet)packet
def name = Command.getFieldValue(packet, "name")
if (name == null) {
  def res = p.commandResult(Command.DataType.form);
  Command.addTitle(res, "Hello World Script")
  Command.addInstructions(res, "Please provide some details")
  Command.addFieldValue(res, "name", name ?: "", "text-single",
    "Your name")
  return res
}
def res = p.commandResult(Command.DataType.result)
Command.addTitle(res, "Hello World Script")
Command.addInstructions(res, "Hello ${name}, how are you?")
return res
如果您比较这两个脚本,您会发现它们非常相似。然而,在显示问候语之前,脚本会尝试从 name 输入字段中检索数据。如果提供了名称,则会显示问候语,否则脚本会询问用户名。

请注意,在这种情况下,发回给用户的数据包的类型是表单而不是 result。实际的区别是 result 类型只显示 OK 按钮,按下该按钮时不会向服务器发送任何数据。表单数据包显示更多按钮 - Finish 和 Cancel。无论您按哪个,都会将一些数据发送回服务器。
该脚本演示了如何使用实用程序类”Command”中的两个新方法:getFieldValue 和 addFieldValue。
所有Command方法的第一个参数是带有 ad-hoc 命令的数据包。
第二个参数通常是输入字段名称
这两个方法参数实际上足以读取ad-hoc命令数据。在ad-hoc命令中创建输入字段的方法还需要一些参数:
下一个参数设置显示给用户的默认值。上面示例中设置的方法是特定于Groovy语言的,并且非常有用,这将在后面的示例中显而易见。
之后,我们必须指定字段类型。所有字段类型都在 XEP-0004 文章中定义。
最后一个参数指定显示给用户的字段标签。

Command类中还有其他一些不同的实用方法来设置不同类型的输入字段,稍后将详细介绍。
要重新加载脚本,只需再次调用”New command script”,输入脚本文本并确保输入的命令ID完全相同,以用新脚本替换旧脚本。
或者,当然,您可以输入新的命令ID来创建新命令并使其在您的服务器上可用。
当脚本加载到服务器上时,尝试执行它。您应该得到一个新的对话框窗口,询问您的姓名,如本节开头的屏幕截图所示。当您输入您的姓名并单击”Finish”按钮后,您将看到另一个窗口,其中包含您的姓名和问候消息。
启动时自动加载脚本
本指南中描述的最后一件事是如何在Tigase服务器启动时自动加载脚本。在运行时加载脚本,更新和删除脚本的能力非常有用,特别是在紧急情况下,如果出现问题并且您想在不影响服务的情况下采取此行动。
但是,如果您有几十个脚本,您不想在每次服务器重新启动时手动加载它们。
Tigase服务器在启动时自动加载位于管理脚本目录中的所有脚本。除非您在配置中设置不同,否则它在此:YourTigaseInstallationDir/scripts/admin/。您所要做的就是将所有脚本复制到此目录,它们将在下次服务器启动时加载。
但是等一等。脚本参数呢?语言,描述,命令ID?你应该如何设置它们?
语言很简单。它由脚本文件扩展名自动检测。因此,只需确保文件扩展名正确且语言已排序。
脚本描述和命令ID需要更多的工作。您必须在脚本中包含以下几行:
AS:Description: The command description
AS:CommandId: command-id
AS:Component: comp_name
请注意,在 AS:Description: 或 AS:CommandId: 字符串之后必须至少有一个空格。之后的所有内容,直到行尾,都被视为脚本描述或命令ID。将它们放入您的脚本文件中,加载器将检测它们并为您的脚本正确设置。
11.13.2. 面向管理员的Tigase脚本版本4.4.x更新
脚本功能在Tigase服务器中对于各种管理员任务非常有用。在服务器运行时加载新脚本或替换旧脚本的可能性为服务维护开辟了一个全新的领域。
在早期版本的Tigase服务器脚本功能仅在会话管理器组件中可用,而它在许多其他地方可能非常有用 - 连接管理器,MUC,PubSub,VHostManager 以及在为特定对象创建的全新自定义组件中更为重要。每次都重新发明wheel并为每个组件单独实现脚本功能是非常浪费的。
因此,脚本功能已在Tigase服务器的核心中实现。它现在是API的一部分,无需任何额外编码即可自动用于所有组件。详细的开发者指南将单独发布。
本文档从用户/管理员的角度描述了更改,因为有一些与新实现相关的可用性更改。
请注意。描述和屏幕截图取自Psi客户端,很可能在其他客户端上用于临时命令和服务发现的界面看起来不同。我建议使用 Psi客户端进行一些初始测试和实验,然后切换到您喜欢的应用程序以供您日常使用。
就像在Tigase中一样,您可以通过服务器上的XMPP服务发现访问所有功能。但是,一旦您连接到服务器,您就可以在那里看到一些变化。

列表中没有命令。它们隐藏在主服务发现列表中。您只能在列表中看到服务器主要组件。
出于多种原因,必须这样做。其中之一显然是对主服务器内容的更干净的访问。另一个可能更重要的是避免将不同组件的一长串命令混合在一起。不同组件的命令可以具有相同的名称/描述,它们甚至可以做类似的事情,但它们在不同的服务器组件上执行。为了避免任何混淆并尽量减少出错的机会,这些命令现在与其组件紧密相连。要访问特定组件的命令列表,您必须双击列表中的组件名称或在选择组件时单击窗口顶部的”Execute command”图标。
应显示一个新窗口,其中包含可用命令的下拉列表。所有命令都与所选组件相关,并在”inside the component environment”执行。您当然可以添加新命令或删除现有命令,当然还可以执行列表中显示的任何命令。

提醒一下,在窗口标题中您可以看到组件ID,您应该在运行任何命令之前检查它,以确保您不会意外破坏系统。

脚本添加窗口也做了一些小的改动。正如您在屏幕截图中看到的那样,添加了一个附加选项 - “Save to disk”。这意味着一旦您将脚本提交到服务器,它就会被写入硬盘驱动器,并将在下次启动时自动加载。
默认情况下启用此选项,因为这似乎是管理员希望保存他的新脚本以供以后重用的逻辑选择。但是,这需要正确配置服务器并授予对存储所有脚本的目录的写入权限。否则服务器将无法在硬盘上写入脚本文件。
与以前的版本一样,只有具有管理员权限的用户才能执行命令并访问服务器上的所有关键元素。但是,用户长时间要求进行另一项更改。在新版本中,所有管理员特定的元素都对其余用户隐藏。
服务器组件不会出现在服务发现中,用户看不到管理员命令,也无法执行它们。这并不是为了提高服务器的安全性,而是为了减少普通用户的困惑,否则他们会看到很多他们无论如何都无法使用的东西。
11.13.3. Tigase和Python
本文介绍了如何让Python在Tigase服务器中作为临时命令的脚本语言工作。第一部分是安装,第二部分是一些代码示例,解释了Python使用和其他一些语言之间的差异。
请注意,我们不是Python开发人员,这绝不是Python开发指南。所有代码示例仅用于展示可用的API,当然还有更好的方法以正确的Python风格来实现。如果您有任何建议或有更好的代码示例,我很乐意将它们包含在指南中。
安装
简而言之,安装非常简单:只需将本文附带的文件复制到您的Tigase安装中,将其复制到 libs/ 目录中。重新启动服务器,您就可以开始编写脚本和执行Python。
理论上,Tigase提供在 JSR-223 中定义的脚本支持。您可以使用任何支持JVM的语言。这还包括独立的python实现,JSR-223 插件充当桥梁。但是,这没有多大意义,因为您无法与JVM代码(Tigase API)进行交互。因此,您需要一种在 JVM 中执行的语言,并且可以轻松地在主应用程序(Tigase服务器)和脚本之间交换数据。

最好的方法是使用Jython实现。它在JVM中运行良好,更重要的是,它与Tigase服务器完美集成。 Tigase服务器使用 Jython-2.2.1 进行了测试,并确认可以正常工作。但是,建议使用 Jython-2.5.1 版本,并且所有示例都在安装此版本的情况下执行。请注意,Jython-2.5.0根本不工作。两个受支持的版本都可以从 Jython网站 下载。
版本 2.5.1 安装起来更简单一些。当您下载并运行Jython安装程序时,在您安装Jython的目录中找到 jython.jar 文件。将文件复制到Tigase的 libs/ 目录,然后一切准备就绪。请注意,为方便起见,此文件与本文所附文件相同。
版本 2.2.1 需要更多的工作。第一部分是一样的。然而,复制 jython.jar 文件是不够的。要让Jython与Tigase服务器一起工作,还需要一个文件。您必须单独安装JSR-223引擎。二进制文件必须解压缩,并且需要将 jython-engine.jar 文件复制到Tigase libs/ 目录。
检查Jython是否已正确安装以及是否启用了对Python的支持的最佳方法,即尝试向 Tigase 服务器提交新脚本。浏览服务器服务发现,选择”Session manager”组件并运行”Execute command”功能。此时应该出现一个新窗口,其中包含所有可用的临时命令的列表。选择”New command script”项并单击 “Execute”。此时应该出现临时命令对话框窗口。其中一个字段是”Language”,其中包含可用脚本语言的下拉列表。如果”python”在列表中,则表示一切正常并且启用了对Python的支持。

写Python脚本
Python脚本的工作方式与Groovy或其他语言脚本类似,但有一个显著差异。您不能从脚本本身调用”return” 。因此,您不能通过直接从脚本调用”return”语句来简单地传递脚本结果。
为了克服这个问题,Tigase提供了另一种传递脚本执行结果的方法。它在脚本完成时检查一个特殊变量的值:“result”和“packet”。通过为这些变量之一赋值,Python(或任何其他语言)可以将执行结果传回Tigase服务器。
result允许从脚本返回简单的文本(或字符串)。packet允许返回发送回给用户的Packet实例。
最简单的Python脚本可能如下所示:
result = "Hello world!"
有关如何加载和执行脚本的说明,请参阅在Tigase服务器中编写脚本的 介绍性文章。 Tigase 4.4.0及更高版本有一些小的变化,所以请查看描述新元素的 文章。
一个更高级的脚本示例要求用户提供实际脚本执行所需的参数:
from java.lang import *
from tigase.server import *
num1 = Command.getFieldValue(packet, "num1")
num2 = Command.getFieldValue(packet, "num2")
if num1 is None or num2 is None:
  res = Iq.commandResultForm(packet)
  Command.addTextField(res, "Note", "This is a Python script!")
  Command.addFieldValue(res, "num1", "")
  Command.addFieldValue(res, "num2", "")
  packet = res
else:
  result = num1 + num2
除了这个微小的差异之外,Tigase管理员命令的Python脚本的其余部分与所有其他语言相同。由于所有语言都可以通过这些特殊变量返回执行结果,因此可以说根本没有区别。
在开发人员指南中的 “组件实现 - 第6课 - 脚本支持” 文章中,我将介绍可用于脚本框架的Tigase服务器API。我的主要语言是 Groovy,因为它提供了与JVM 和Tigase API的最佳集成,但我也会尝试包含Python示例代码。