Apache Vysper 介绍与选型指南

介绍 Apache Vysper 这个已停滞的 Java XMPP 服务器定位、RFC 3920/3921 与 RFC 6120/6121 协议基线、核心架构与模块特性,并基于 Ubuntu 22.04 实测给出与 ejabberd/Openfire/Prosody 的选型对比与新项目建议。

Apache VysperApache VysperXMPPJavaApache2026/10/16

Apache Vysper 介绍与选型指南

目标:说清 Apache Vysper 是什么、协议覆盖与架构如何、当前停滞状态有多严重,并在 Ubuntu 22.04 实测环境(Vysper 0.7 + JDK 8/7)下给出与 ejabberd、Openfire、Prosody 的选型对比结论,帮助读者判断"是否还值得把 Vysper 用于新项目"。

一、环境信息

本文实测环境如下,所有结论均在此环境验证:

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Vysper 版本:0.7(官方二进制发行包 vysper-0.7-bin.tar.gz,取自 Apache 归档站点)
  • JDK 组合一:Temurin OpenJDK 1.8.0_504-b01(64-Bit Server VM Temurin 25.504-b01)
  • JDK 组合二:Zulu OpenJDK 1.7.0_352-b01(Zulu 7.56.0.11-CA-linux64)
  • 监听端口:5222(客户端 TCP)、8080(启用 BOSH 后)
  • 安装目录:/opt/vysper/vysper-0.7
  • 实测账号:admin@vysper.org、user1@vysper.org、user2@vysper.org(密码均为测试口令)

💡 技术拓展:XMPP(Extensible Messaging and Presence Protocol,可扩展消息与呈现协议)是从 Jabber 演化而来的开放即时通讯协议,由 XMPP Standards Foundation(XSF)维护。常见 XMPP 服务器实现对比:

服务器语言特点维护状态
ejabberdErlang高并发、集群成熟、社区活跃活跃
OpenfireJava管理后台完善、插件体系丰富活跃
ProsodyLua轻量、配置简洁、模块化活跃
Apache VysperJavaApache 基金会出品、Spring/MINA 架构、可嵌入停滞(0.7 后停更)

本文主角是其中唯一"停滞"的 Apache Vysper,选型结论见第七节。

二、软件概述

2.1 项目定位与历史

Apache Vysper 是 Apache 软件基金会(ASF)旗下、托管于 MINA 项目的 XMPP 服务器实现,目标是交付 XMPP 协议核心与 IM 部分的完整服务端。其发行包内自述文件(ABOUT.txt)原文说明如下(实测摘录):

This project aims at delivering a server implementation of both the core and IM parts of the XMPP protocol
(as specified in RFCs 3920 [1] + 3921 [2]).

"Vysper" is pronounced like in "whisper".

即:Vysper 的目标是实现 RFC 3920(XMPP 核心)与 RFC 3921(XMPP 即时通讯与呈现)两个基础规范,名字发音同 "whisper"。

版本与时间线(以官方归档站点的发布记录为准):

  • 0.7 是该项目在 Apache 归档中的最后一个稳定发行版,发行包文件时间戳为 2011 年 2 月 13 日(实测 bin/run.sh、config/ 下所有文件的修改时间均为 2011-02-13);
  • 此后项目再无新版本发布,官方已将其归档在 archive.apache.org 的 MINA 目录下(路径 dist/mina/vysper/0.7/);
  • 项目主页与源码仓库均已归档,ABOUT.txt 中给出的源码获取方式仍指向 SVN 的 mina/vysper/trunk。

2.2 停滞状态如实披露

必须如实告知读者:Apache Vysper 自 0.7(2011 年)之后停止更新,至今已停滞十余年,Apache 官方归档目录中没有任何更新的发行版。这带来三个直接后果,均为实测证实:

  1. 老协议基线:0.7 实现的是 RFC 3920/3921(2004 年版 XMPP),而不是后续的 RFC 6120/6121(2011 年修订版),更不涉及现代 XMPP 的许多扩展;
  2. 老组件栈:发行包内置 Spring 3.0.5、MINA 2.0.2、Jetty 7.2.1、Ehcache 2.2.0 等组件(实测 lib/ 目录 53 个 jar 的文件名),这些组件本身也已停止维护多年;
  3. 老证书问题:发行包自带的 TLS 证书是 2005 年生成的 511 位 RSA 密钥 + MD5 签名(实测 keytool -list 回显见下文 5.2 节),现代客户端连接时普遍会因证书强度报警甚至拒绝握手。

2.3 发行包内容概览

官方二进制发行包解压后的结构(实测 ls 回显):

ABOUT.txt
ARCHITECTURE.txt
LICENSE.txt
NOTICE.txt
bin
config
lib
log

各目录职责:

路径内容说明
bin/run.sh、run.bat启动脚本,Unix 与 Windows 各一
config/spring-config.xml、log4j.xml、ehcache.xml、bogus_mina_tls.certSpring 主配置、日志配置、缓存配置、TLS 证书
lib/53 个 jarVysper 模块 jar 与全部依赖
log/vysper_server.log、stanza.log运行日志与协议报文日志(启动后生成)

lib/ 中值得注意的构件(实测 ls lib/ | grep 0.7 节选):

nbxml-0.7.jar
vysper-core-0.7.jar
xep0045-muc-0.7.jar
xep0060-pubsub-0.7.jar
xep0124-xep0206-bosh-0.7.jar
spec-compliance-0.7.jar

关键差异解读:vysper-core-0.7.jar 是服务器核心;xep0045-muc(多用户聊天)、xep0060-pubsub(发布订阅)、xep0124-xep0206-bosh(BOSH/HTTP 绑定)是三个独立模块 jar,是否生效取决于 spring-config.xml 中是否装配对应模块 Bean 或端点。

三、XMPP 协议简介(RFC 6120/6121)

谈 Vysper 的选型绕不开它实现的协议。XMPP 的现行标准是 2011 年 IETF 发布的修订版:**RFC 6120(XMPP Core,核心:XML 流、TLS、SASL、寻址与 stanza 路由)**与 RFC 6121(XMPP IM,即时通讯与呈现:花名册、订阅、消息与在线状态处理),两者分别取代 2004 年的 RFC 3920/3921。理解下面五个概念,就能看懂 Vysper 的模块划分与本文所有实测回显:

概念一句话解释对应 Vysper 实体
JID实体地址 user@domain/resource,如 user1@vysper.org/c1bind 后返回的完整 JID
XML 流两端之间先 <stream:stream> 开流,此后所有内容都装在这条流里stream:features 流特性协商
stanza流内的三种业务单元:message(消息)、presence(在线状态)、iq(请求/响应)stanza.log 逐条记录的对象
STARTTLS + SASL流先升 TLS 加密、再做身份认证,顺序不可颠倒SslFilter + SASL PLAIN
资源绑定认证后为会话指定 resource,JID 补全bind iq

Vysper 0.7 与 6120/6121 的关系要如实说:0.7 实现的是 3920/3921 基线。6120/6121 是对 3920/3921 的修订与明确化,核心语义连续(流协商、SASL、bind 的报文形态基本未变),所以 0.7 与实现新标准的现代客户端做基础互通是可行的——这一点有实测背书:Ubuntu 22.04 的 Python 3.10(实现 RFC 6120 语义)与 Vysper 0.7 完成 TLS→SASL→bind 全流程并互发消息成功(见 3.2 节实测)。但 6120/6121 引入的强制特性(如 SCRAM 认证机制、更严格的流协商细节与错误处理)0.7 均未跟进,不能宣称符合新标准。

3.1 一次 XMPP 会话长什么样

用裸 XMPP 流把一次完整会话拆开看(连接 Vysper 0.7 实测抓取,为便于阅读省略 xmlns 声明等次要属性):

  1. 开流:客户端发流头,声明目标域 vysper.org;
  2. 流特性:服务器回流头并携带 <stream:features>——实测显示 starttls 且 <required/>(明文通道只允许升级加密);
  3. STARTTLS:客户端发 <starttls/>,服务器应 <proceed/>,此后 TCP 通道变为 TLS 通道,双方重开一条加密流;
  4. SASL:在加密流里用 <auth mechanism='PLAIN'> 完成 SASL 认证,服务器应 <success/>,再重开一次流;
  5. bind + session:<iq type='set'><bind/></iq> 拿到带 resource 的完整 JID,<session/> 建立正式会话,此后即可互发 message。

实测全程回显(Python 标准库客户端,节选关键步骤):

>>> <?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='vysper.org' version='1.0'>
<<< <?xml version="1.0" encoding="UTF-8"?><stream:stream xmlns="jabber:client" ... from="vysper.org" version="1.0" id="cb18dacac90b44b9846792cd43622a7d"><stream:features ...><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required></required></starttls></stream:features>
>>> <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
<<< <proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"></proceed>
--- TLS established: TLSv1.2
>>> <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGFkbWluAHExdzJlM3I0</auth>
<<< <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></success>
>>> <iq type='set' id='b1'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>res5</resource></bind></iq>
<<< <iq xmlns="jabber:client" type="result" id="b1"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>user5@vysper.org/98979656783a4173a9bea01841e90059</jid></bind></iq>

每个概念都在回显里对上了号:流头与流特性(概念 2)、<required/> 的 STARTTLS(概念 4 前半)、<success/> 的 SASL(概念 4 后半)、返回完整 JID 的 bind(概念 1 与 5)。补全脚本的完整可用版本见《Ubuntu 22.04 安装 Apache Vysper 指南》第七节。

💡 技术拓展:RFC 6120 把"客户端到服务器"(c2s,5222)与"服务器到服务器"(s2s,5269)分为两个接入面。Vysper 0.7 只实现了 c2s,s2s 联帮(跨服务器互发消息)未提供——这也是它无法用于多域名/联邦场景的硬性原因之一。

3.2 协议互通实测结论

协议要素RFC 6120/6121 要求Vysper 0.7 实测表现判定
STARTTLS支持,c2s 建议升级流特性强制 <required/>符合
SASL必须支持PLAIN 可用;未提供 SCRAM 等现代机制部分(老基线)
资源绑定必须支持bind/session 正常符合
stanza 语义message/presence/iq单聊、MUC 群聊实测投递正常基本符合
s2s 联帮服务器间 5269未实现不符合
离线消息RFC 6121 offline storage(XEP-0160)未实现,接收方离线则丢弃不符合

一句话总结:Vysper 0.7 的协议实现覆盖了"能聊天"的最小闭环,RFC 6120/6121 时代的服务器必备项(联帮、离线存储、SCRAM 认证)均缺失,选型时按此预期评估。

四、核心架构

4.1 协议栈与运行时组件

Vysper 的架构从下到上分为四层(依据发行包 ARCHITECTURE.txt 与实测日志归纳):

层组件实测证据
网络传输层Apache MINA 2.0.2(TCP)/ Jetty 7.2.1(BOSH over HTTP)启动日志出现 org.apache.mina.filter.ssl.SslFilter;BOSH 响应头 Server: Jetty(7.2.1.v20101111)
XML 流解析层nbxml(Vysper 自研轻量 XML 解析器)lib/nbxml-0.7.jar 在启动 classpath 首位
服务器核心层vysper-core-0.7.jar:会话管理、stanza 路由、SASL 认证、资源绑定启动日志逐条加载 servicediscovery、roster 等模块
扩展模块层各 xep00XX-* 模块 jar启动日志显示 XEP-0092/0202/0054/0199/0049/0050/0133/0045 逐个 "adding module..."

两个运行时入口(实测 javap 回显):

public class org.apache.vysper.spring.ServerMain {
  public static void main(java.lang.String[]);
}
public class org.apache.vysper.xmpp.server.ServerMain {
  public static void main(java.lang.String[]) throws
      org.apache.vysper.xmpp.authorization.AccountCreationException, java.io.FileNotFoundException;
}

关键差异解读:Spring 运行时(org.apache.vysper.spring.ServerMain)读取 classpath 中的 spring-config.xml 装配服务器,是发行包 bin/run.sh 默认使用的方式;非 Spring 运行时(org.apache.vysper.xmpp.server.ServerMain)则把组件拼装写成代码,适合把 Vysper 嵌入到其他 Java 应用里。本文后续章节均使用 Spring 运行时。

💡 技术拓展:XMPP 客户端到服务器的接入方式不止 TCP 一种,Vysper 0.7 支持的接入传输对比:

传输方式规范Vysper 中的配置载体默认端口
TCP 直连RFC 3920TCPEndpoint Bean(默认启用)5222
BOSH(HTTP 长轮询)XEP-0124/0206BoshEndpoint Bean(默认注释,需手动启用)8080

本文实测环境最终两种端点同时启用,ss -tlnp 可同时看到 5222 与 8080 两条 LISTEN 记录,均归属同一个 java 进程。

4.2 存储层与模块体系

存储抽象(spring-config.xml 实测原文节选):

<bean id="inmemoryStorageRegistry" class="org.apache.vysper.storage.inmemory.MemoryStorageProviderRegistry" />

<bean id="jcrStorageRegistry" class="org.apache.vysper.storage.jcr.JcrStorageProviderRegistry" />

<!-- choose one of the storage registries -->
<alias name="inmemoryStorageRegistry" alias="storageRegistry" />

💡 技术拓展:Vysper 的账号、名册、花名册呈现等持久化依赖"存储提供者注册器",0.7 发行包内置两种实现:

实现类原理适用场景
MemoryStorageProviderRegistry全内存,重启即失演示、测试、嵌入式试用
JcrStorageProviderRegistry基于 JCR(Jackrabbit 内容仓库)落盘需要重启保留账号与数据的场景

发行包默认走内存实现(alias 指向 inmemoryStorageRegistry),本文实测也采用默认内存实现。

模块体系:Vysper 把协议扩展实现为独立 Module,启动时由 DefaultServerRuntimeContext 逐个注册。实测启动日志(节选):

05:32:45,585 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... servicediscovery (1.0beta)
05:32:45,587 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... roster (1.0beta)
05:32:45,627 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0092 Software Version (1.0)
05:32:45,628 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0202 Entity Time (1.0)
05:32:45,629 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0054 Vcard-temp (1.0)
05:32:45,629 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0199 XMPP Ping (2.0)
05:32:45,629 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0049 Private Data (1.2)
05:32:45,629 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0050 Ad-hoc Commands (1.2)
05:32:45,630 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0133 Service Administration (1.1)
05:32:45,632 | INFO  | org.apache.vysper.xmpp.server.DefaultServerRuntimeContext | adding module... XEP-0045 Multi-user chat (1.24)

4.3 实测功能验证一览

在实测环境中,用标准库 Python 客户端(协议交互脚本见《Apache Vysper 常用 CLI 命令与工具详解》)对 0.7 做了端到端验证,结果汇总:

功能结果实测证据
流协商 + 强制 STARTTLS通过流特性返回 <starttls ...><required/></starttls>,TLS 握手后进入 SASL
SASL PLAIN 认证通过<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
错误口令拒绝通过返回 <failure ...><not-authorized/></failure>
资源绑定 + 会话建立通过bind 返回完整 JID,session iq 返回 result
服务发现 disco#info/items通过返回特性列表与 chat.vysper.org 聊天室服务项
双账号单聊消息互通通过user1→user2、user2→user1 双向 message 均到达
多用户聊天(MUC)通过进房返回 owner/moderator 角色,群聊消息投递成功
BOSH(HTTP 绑定)通过POST /bosh/ 返回 200 与会话 sid
现代客户端 TLS 1.3失败→换证书后通过内置 2005 年证书时握手被拒;换 2048 位新证书后 openssl s_client 实测协商出 TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384

结论:0.7 在老 JDK 下核心 XMPP 功能完整可用,但生态兼容性停留在 2011 年水平。

五、功能特性

5.1 协议与扩展覆盖

按发行包自述与实测验证,Vysper 0.7 的功能覆盖如下:

类别规范/扩展状态实测情况
核心RFC 3920(XMPP Core:SASL、TLS、流、 stanza 路由)已实现STARTTLS 强制、PLAIN 认证、消息路由均实测通过
IMRFC 3921(XMPP IM:roster、presence、消息)已实现roster 模块随核心自动加载(启动日志可见)
多用户聊天XEP-0045已实现(模块 jar + 默认装配)进房/群聊消息实测通过,服务域 chat.vysper.org
发布订阅XEP-0060已实现(模块 jar 提供,默认未装配)默认配置中该 Bean 被注释,未实测
HTTP 绑定XEP-0124/0206(BOSH)已实现(默认注释,启用后实测通过)8080 端口实测
软件版本XEP-0092已实现启动日志可见
实体时间XEP-0202已实现启动日志可见
vCardXEP-0054已实现但缺持久化管理器启动日志报 no VcardTempPersistenceManager found
XMPP PingXEP-0199已实现启动日志可见
私有数据XEP-0049已实现但缺持久化管理器启动日志报 no PrivateDataPersistenceManager found
Ad-hoc 命令XEP-0050已实现服务发现特性含 http://jabber.org/protocol/commands
服务管理XEP-0133已实现启动日志可见,含 AddUser 命令处理器类
端到端加密等其他现代 XEP无0.7 时代之后的标准均未涉及

关键差异解读:核心 IM 能力(单聊、MUC、服务发现)实测完整;vCard/私有数据虽加载但因缺持久化管理器实际不可用;发布订阅需要自行解注释装配。整体上它是一个"能用但停留在 2011 年"的 XMPP 服务器。

5.2 安全特性

  • 强制 STARTTLS:实测客户端未升级 TLS 前流特性只返回 starttls 且标记 required,服务端不允许明文 SASL 认证,这是 0.7 默认且正确的安全姿态;
  • TLS 证书:默认使用发行包自带的 config/bogus_mina_tls.cert(JKS 格式,store 密码 boguspw)。实测 keytool -list 回显:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

bogus, Mar 7, 2005, PrivateKeyEntry,
Certificate fingerprint (SHA1): 14:2C:6E:33:6D:4C:DE:BD:FD:8B:96:6B:B6:31:10:56:4B:D0:9B:1F

Warning:
<bogus> uses the MD5withRSA signature algorithm which is considered a security risk.
<bogus> uses a 511-bit RSA key which is considered a security risk.
  • 账号口令:默认预置账号 admin@vysper.org 的口令是占位串 CHOOSE A SECURE PASSWORD,配置文件注释明确说明空口令会生成随机口令并打印到控制台(发行包设计上的安全兜底);
  • 已知限制:自带证书 511 位 RSA + MD5 + 2005 年过期,实测 openssl s_client 连接时报 EE certificate key too weak 与 certificate has expired,现代客户端的 TLS 1.3 握手随之失败;换 2048 位新证书后 TLS 1.3 实测协商成功——问题根源是证书而非 TLS 版本,生产化必须换证(完整换法与三方客户端回归见《Apache Vysper 配置参数详解》第六节)。

六、适用场景与限制

6.1 适合用 Vysper 的场景

结合实测,以下场景仍然可以考虑 Vysper 0.7:

  1. Java 技术栈的协议研究/教学:代码分层清晰(MINA 传输 → nbxml 解析 → 核心路由 → 模块扩展),且 stanza.log 会把每条 XMPP 报文记录下来(实测文件 log/stanza.log 逐行记录了 stream/starttls/auth 等事件),适合作为 XMPP 协议学习的观察样本;
  2. 老系统对接/考古:维护与 2011 年前后 XMPP 生态对接的遗留系统,或在老 JDK(7/8)环境里复现历史问题;
  3. 嵌入式试验:利用非 Spring 运行时或 Spring 运行时把 XMPP 能力嵌进 Java 应用做原型验证。

6.2 不适合的场景与硬限制

  • 新项目生产部署:项目停滞十余年,无安全补丁、无社区支持;自带证书在现代客户端下必然报警,TLS 1.3 直接不可用;
  • 高并发生产 IM:0.7 发布于 2011 年,MINA 2.0.2 等依赖的老版本在现代负载下没有经过验证;
  • 现代 XMPP 生态对接:不支持 RFC 6120/6121 之后的修订与主流现代 XEP(如现代移动推送方案),与当前主流客户端的兼容性没有保障;
  • JDK 版本约束:实测 0.7 需要在 JDK 7/8 上运行(更高版本 JDK 未验证,不建议尝试)。JDK 8(Temurin 1.8.0_504)是首选;JDK 7(Zulu 7.0_352)能启动、且在换用 2048 位新证书后客户端实测全部跑通,但配合内置 2005 年证书时 JDK 7 自身的算法约束会拒绝该证书导致任何客户端都无法握手(组合矩阵实测见《Ubuntu 22.04 安装 Apache Vysper 指南》第八节)。

七、同类选型对比

面向"今天要搭一套 XMPP 服务"的真实需求,把 Vysper 与三个活跃项目放在同一维度对比:

维度Apache Vysper 0.7ejabberdOpenfireProsody
实现语言JavaErlangJavaLua
维护状态停滞(2011 年后停更,Apache 归档)活跃活跃活跃
协议基线RFC 3920/3921 + 少量 XEPRFC 6120/6121 及大量现代 XEPRFC 6120/6121 及较多 XEPRFC 6120/6121 及大量现代 XEP
集群能力无实测依据(架构未内置)原生支持,成熟支持集群插件轻量集群方案有限
管理界面无(配置文件驱动)Web 管理台Web 管理台完善管理以配置+CLI 为主
扩展方式Spring Bean 装配模块 jarErlang 模块Java 插件Lua 社区模块
部署体量极小(发行包约 17MB,53 个 jar)中中(内置 JRE 发行版)小
适合人群研究者、遗留系统维护者生产 IM 主力选择偏好 Java 生态与开箱管理台追求轻量与简洁配置

关键差异与如何选:

  • 唯一要明确选 Vysper 的理由是"Java + 可嵌入 + Apache 许可 + 协议教学/考古";一旦涉及真实用户、真实安全要求,其余三项活跃项目全面胜出;
  • 新项目建议:直接选 ejabberd 或 Prosody(集群/生态见长或轻量优先),Java 团队想要图形管理台选 Openfire;Vysper 只作为研究对象或历史系统兼容层保留;
  • 版本获取注意:Vysper 只有 0.7 一个可用发行版,取自 archive.apache.org;其余三个项目请以各自官网当前发布版本为准,不要采信第三方转述的具体版本号。

八、参考链接