Apache Sandesha2 介绍与选型指南

介绍 Apache Sandesha2 在 Axis2 中的 WS-ReliableMessaging 模块定位、架构与特性,并基于 Ubuntu 22.04 实测给出停滞状态披露与新项目选型建议。

Apache Sandesha2Apache Sandesha2JavaApacheXML2026/10/16

Apache Sandesha2 介绍与选型指南

目标:讲清 Apache Sandesha2 是什么、在 Apache Axis2 中承担什么角色、能提供哪些可靠传输能力,并基于 2026-10 在 Ubuntu 22.04 服务器实测环境(JDK 8u504 / JDK 17.0.20.1)对版本沿革、坐标与兼容性的一手实测结论,给出"是否还值得选它"的明确建议。

一、环境信息

本文结论与引用的实测输出均来自以下环境(一台真实的 Ubuntu 22.04 x86_64 服务器):

  • 操作系统:Ubuntu 22.04(GNU/Linux 5.15.0-125-generic x86_64)
  • JDK:OpenJDK 17.0.20.1(build 17.0.20.1+1-1-22.04-Ubuntu)与 OpenJDK 1.8.0_504(build 1.8.0_504-8u504-ga-1ubuntu1~22.04.3-b01)
  • Apache Axis2:1.8.2(当前主线延续版本)与 1.6.2(与 Sandesha2 1.6.2 同期的历史版本)
  • Apache Sandesha2:1.6.2(Maven Central 发行,2012-04-30 构建,末版)
  • 实测时间:2026-10-16

Axis2 服务端版本实测核对(curl 调用 Axis2 自带 Version 服务回显):

<ns:getVersionResponse xmlns:ns="http://axisversion.sample"><ns:return>Hi - the Axis2 version is 1.6.2</ns:return></ns:getVersionResponse>

版本信息实测回显(Ubuntu 22.04 服务器上执行 java -version,JDK 8 侧):

java -version
openjdk version "1.8.0_504"
OpenJDK Runtime Environment (build 1.8.0_504-8u504-ga-1ubuntu1~22.04.3-b01)
OpenJDK 64-Bit Server VM (build 25.504-b01, mixed mode)

二、软件概述

Apache Sandesha2 是 Apache Axis2 的 WS-ReliableMessaging(WS-RM,可靠消息传送)实现模块。它在 Axis2 的 handler 管线之上,把"不可靠的 HTTP 请求"升级为"有序、去重、可重传、可确认"的可靠序列(Sequence)传输:客户端把若干业务消息组成一个 RM 序列逐条发送,服务端逐条确认(SequenceAcknowledgement),丢包或超时由发送端自动重传。

WS-ReliableMessaging 本身是一族规范,业界并存多个版本,实际选型时必须先弄清楚对端支持哪一种:

💡 技术拓展:WS-ReliableMessaging 规范版本对比——

规范版本命名空间说明
WS-RM 2005-02(提交稿)http://schemas.xmlsoap.org/ws/2005/02/rm早期事实标准,WCF/老 Metro 支持
WS-RM 1.1/1.2(OASIS)http://docs.oasis-open.org/ws-rx/wsrm/200702正式标准,Sandesha2 1.5+/CXF 支持
WS-ReliableMessaging Policyhttp://docs.oasis-open.org/ws-rx/wsrmp/200702配套策略断言规范

Sandesha2 1.6.2 的 module.xml 自述"实现了 WSRM submitted spec 与 WSRM 1.1 spec up to CD4",即同时兼容 2005-02 提交稿与 1.1 标准草案 CD4,可通过客户端选项切换。本文实测采用的是默认(2005-02)行为。

Sandesha2 的一个关键事实是:项目已长期停滞。最后一个版本 1.6.2 发布于 2012-04-30(Maven Central 的 POM 时间戳 1335771784000 实测对应 2012-04-30 UTC),此后再无更新;官方站点 ws.apache.org 的 Sandesha2 页面已不再维护。本文所有结论均以此为前提。

2.1 版本沿革(Maven Central 实测)

模块本体 org.apache.sandesha2:sandesha2(packaging=mar)在 Maven Central 上的全部版本,实测目录列表:

curl -s https://repo1.maven.org/maven2/org/apache/sandesha2/sandesha2/ | grep -oE 'href="[^"]+/"'
href="../"
href="1.1/"
href="1.2/"
href="1.3/"
href="1.4/"
href="1.6.0/"
href="1.6.1/"
href="1.6.2/"

即 1.1 → 1.2 → 1.3 → 1.4 → 1.6.0 → 1.6.1 → 1.6.2 共七个版本后停止演进;官方 Apache 归档目录(archive.apache.org/dist/ws/sandesha2/)实测只保留 0.9、1.0、1.1、1.2、1.3 的发行目录,1.4 及以后只能从 Maven Central 获取。

2.2 组内发行物清单(13 个 artifact,实测)

org.apache.sandesha2 组下全部 artifact 及实测/推断用途:

artifactpackaging用途依据
sandesha2marRM 模块本体(部署进 Axis2 modules/)实测解包(内含 module.xml 与全部 class)
sandesha2-corejar核心 API 与实现(class 与 resource.properties)实测解包、编译客户端使用
sandesha2-samplesjar(sources)RM 示例服务/客户端源码实测解包出 RMSampleService/SyncEchoClient 等
sandesha2-testsjar模块测试套件命名与 Maven Central 目录
sandesha2-interopjar互操作测试客户端同上
sandesha2-persistencejar持久化存储扩展同上
sandesha2-policyjarRM 策略断言相关同上
sandesha2-rampart-integrationjar与 Rampart 安全模块集成同上
sandesha2-client / sandesha2-client-constantsjar早期独立客户端组件(末版 1.1)Maven Central 元数据实测
sandesha2-parentpom父 POM同上
sandesha2-resource-bundlejar许可证等资源聚合同上
distributionzip(1.2)2007 年时代的二进制发行包(仅 1.2)Maven Central 元数据实测(lastUpdated 2007-06-09)

解读:现代集成只需要 sandesha2(mar)加 sandesha2-core(jar,用于客户端 classpath 与修复 mar 资源缺陷),其余为历史演进遗留。

2.3 RM 交互报文种类(module.xml 实测佐证)

Sandesha2 在业务消息之外引入的协议报文,可从 module.xml 注册的 actionMapping 实测枚举:CreateSequence/CreateSequenceResponse(建序列)、SequenceAcknowledgement(累积确认)、AckRequested(催确认)、CloseSequence(关闭序列)、TerminateSequence(终止并释放)、MakeConnection(匿名拉取)、fault(RM 故障),同时覆盖 2005-02 提交稿与 2007-02 规范两套 Action 命名空间。一次完整可靠调用的时序为:客户端 CreateSequence 建序列 → 逐条发送业务消息(携带 Sequence 头与 MessageNumber)→ 服务端周期性回 SequenceAcknowledgement → 最后一条消息标记 Last/关闭 → TerminateSequence 收尾。

三、核心架构

3.1 与 Apache Axis2 的模块关系

Sandesha2 不是独立进程,而是以 .mar(Module Archive,本质是带 META-INF/module.xml 的 jar)形式部署进 Axis2 仓库 repository/modules/ 的模块。它通过 module.xml 向 Axis2 注册自己插入各消息流的 handler:

实测从 sandesha2-1.6.2.mar 中提取的 META-INF/module.xml 节选(原样转录):

<module name="sandesha2" class="org.apache.sandesha2.SandeshaModule">

    <Description>
        This module implements WS-ReliableMessaging for Axis2. This implements both the WSRM submitted spec and up to the version CD4 of the new WSRM 1.1 spec.
    </Description>

    <InFlow>
        <handler name="SandeshaGlobalInHandler" class="org.apache.sandesha2.handlers.SandeshaGlobalInHandler">
            <!-- Global In handler should come before addressing dispatching -->
            <order phase="Dispatch" phaseFirst="true"/>
        </handler>
        <handler name="MessageContextCorrectionHandler" class="org.apache.sandesha2.handlers.MessageContextCorrectionHandler">
            <!-- A handler which handle the duplicate messages -->
            <order phase="Transport"/>
        </handler>
        <handler name="SequenceIDDispatcher" class="org.apache.sandesha2.handlers.SequenceIDDispatcher">
            <order phase="Addressing" before="AddressingBasedDispatcher"  />
        </handler>
        <handler name="SandeshaInHandler" class="org.apache.sandesha2.handlers.SandeshaInHandler">
            <order phase="RMPhase"/>
        </handler>
    </InFlow>
    ...

要点解读:

  • SandeshaGlobalInHandler 挂在 Dispatch 阶段最前,先于寻址分发拦截所有入站消息,做 RM 协议消息(CreateSequence/Acknowledgement 等)与应用消息的分流;
  • SandeshaInHandler/SandeshaOutHandler 挂在专用 RMPhase 阶段,处理序列头、去重与确认;
  • 该模块依赖 WS-Addressing(addressing 模块)协同工作,这是部署时必须同时启用 addressing 的原因。

3.2 运行时组成

Sandesha2 的核心类(实测解包 mar 归档可见的包结构)分为:

  • org.apache.sandesha2.workers:Sender/Invoker 两个后台工作线程池,分别负责消息重传发送与按序投递;
  • org.apache.sandesha2.storage:序列状态存储抽象(RMSBean/RMDBean/SenderBean 等序列状态 Bean),默认 InMemoryStorageManager(内存存储,重启即失);
  • org.apache.sandesha2.msgprocessors:各 RM 协议消息的处理器(CreateSequence、TerminateSequence、MakeConnection 等);
  • org.apache.sandesha2.policy:RM 策略断言(SandeshaPolicyBean)的构建与加载;
  • org.apache.sandesha2.client:SandeshaClient/SandeshaClientConstants 客户端控制 API。

💡 技术拓展:RM 序列状态的"存储管理器"决定可靠性的持久化程度——

实现原理取舍
InMemoryStorageManager(默认)序列状态放内存快;进程重启序列丢失,不满足"跨重启恢复"
PermanentStorageManager(可插拔)对接数据库等持久化介质重启可续传;需自行提供 JPA/JDBC 存储实现

Sandesha2 1.6.2 默认两者都指向 org.apache.sandesha2.storage.inmemory.InMemoryStorageManager(实测自 sandesha2-core-1.6.2 源码 Sandesha2Constants.Properties.DefaultValues),开箱即用但不具备跨重启恢复能力,这一点对选型很关键。

3.3 序列状态模型(sandesha2-core 实测解包)

序列的"可靠"建立在有状态的状态机上。实测解包 sandesha2-core-1.6.2.jar,存储层 Bean 与后台线程类清单如下(原样转录):

org/apache/sandesha2/storage/beans/RMSBean.class        11918  发送端序列状态
org/apache/sandesha2/storage/beans/RMDBean.class         5218  接收端序列状态
org/apache/sandesha2/storage/beans/RMSequenceBean.class  6596  序列状态公共父类
org/apache/sandesha2/storage/beans/SenderBean.class      7102  待重传消息队列条目
org/apache/sandesha2/storage/beans/InvokerBean.class     3034  待投递消息条目
org/apache/sandesha2/workers/Sender.class                20868  发送侧后台线程(重传驱动)
org/apache/sandesha2/workers/Invoker.class               11496  接收侧后台线程(按序投递驱动)

据此可以把一次 RM 调用的数据流概括为:业务线程把消息与 SenderBean 一起交给存储管理器 → Sender 线程按 RetransmissionInterval 周期检查并重发未确认条目 → 收到 SequenceAcknowledgement 后移除对应 SenderBean → 服务端 Invoker 线程按 MessageNumber 顺序把消息投递给业务服务。这也解释了默认内存存储的失效模式:上述全部状态都在内存里,进程重启即清零。

四、功能特性

以下特性均在本文实测环境验证过存在与行为(引用实测详见《Apache Sandesha2 在 Ubuntu 22.04 集成使用指南》):

  1. RM 序列与累积确认:客户端三条消息 echo1/echo2/echo3 走同一 sequence3 序列发送,服务端按序收到三条并逐一返回,客户端回调依次得到 echo1、echo1echo2、echo1echo2echo3(服务端按序列累积拼接),实测日志:
Callback 'Callback 1' got result:echo1
Callback 'Callback 2' got result:echo1echo2
Callback 'Callback 3' got result:echo1echo2echo3
'EchoString' service got text 'echo1' for the sequence 'sequence3'
'EchoString' service got text 'echo2' for the sequence 'sequence3'
'EchoString' service got text 'echo3' for the sequence 'sequence3'
  1. 双规范支持:默认 2005-02 提交稿,可经 SandeshaClientConstants.RM_SPEC_VERSION 切到 v1_1(该切换路径本文未实测);
  2. 服务端虚拟操作注入:engage sandesha2 后,服务自动多出一组 Sandesha2Operation* 虚拟操作用于 MakeConnection/匿名 RM 场景,实测服务列表(curl http://127.0.0.1:8080/axis2/services/ 节选):
<h3><a href="RMSampleService?wsdl">RMSampleService</a></h3>Available operations <ul><li>MTOMPing</li><li>Sandesha2OperationInOut</li><li>Sandesha2OperationOutIn</li><li>Sandesha2OperationOutOnly</li><li>Sandesha2OperationInOnly</li><li>ping</li><li>Sandesha2OperationDuplicateInOut</li><li>echoString</li><li>Sandesha2OperationDuplicateInOnly</li></ul>
  1. MakeConnection 与匿名 RM:为 WS-I 别名场景提供 EnableMakeConnection/EnableRMAnonURI 开关;
  2. 参数化 QoS:重传间隔、确认间隔、指数退避、按序投递等均由策略/模块参数控制(详见《Apache Sandesha2 配置参数详解》)。

五、适用场景与限制

5.1 适用场景

  • 存量 Axis2 1.0~1.6.x 应用需要"HTTP 之上不丢、不重、按序"的消息传送,且对端同样是 Axis2/Rampart 技术栈的遗留系统维护场景;
  • 无法引入新中间件(MQ/消息代理),只能以 Web Service 栈内协议解决可靠性的历史架构。

5.2 实测确认的限制(如实披露)

  1. 与 Axis2 1.8.x 兼容性已断裂(实测):把 Maven Central 下载的 sandesha2-1.6.2.mar 放入 Axis2 1.8.2 的 repository/modules/ 后启动,模块部署直接失败,服务端日志(节选,实测原文):
[ERROR] The sandesha2-1.6.2.mar module, which is not valid, caused Can't find resource for bundle org.apache.axis2.i18n.ProjectResourceBundle, key Processing Operations Modules with an error of An unsupported message exchange pattern (MEP) exists in ID is http://www.w3.org/2006/01/wsdl/in-only.
org.apache.axis2.deployment.DeploymentException: Can't find resource for bundle org.apache.axis2.i18n.ProjectResourceBundle, key Processing Operations Modules with an error of An unsupported message exchange pattern (MEP) exists in ID is http://www.w3.org/2006/01/wsdl/in-only.
    at org.apache.axis2.deployment.repository.util.ArchiveReader.readModuleArchive(ArchiveReader.java:564) ~[axis2-kernel-1.8.2.jar:1.8.2]

根因是 1.6.2 的 module.xml 使用了 WS-Addressing 2006/01 WSDL 命名空间的 MEP URI,Axis2 1.8.x 已不再支持该写法。因此 Sandesha2 1.6.2 实测可用的组合上限是 Axis2 1.6.x(1.6.2 实测通过)。

  1. Maven Central 发行件存在打包缺陷(实测):org.apache.sandesha2:sandesha2:1.6.2(packaging=mar)内缺少 org/apache/sandesha2/i18n/resource.properties(该资源在 sandesha2-core-1.6.2.jar 中实测存在,18399 字节),直接部署会在 SandeshaModule.init 处抛:
Caused by: java.util.MissingResourceException: Cannot find resource 'org.apache.sandesha2.i18n.resource'
    at org.apache.sandesha2.i18n.SandeshaMessageHelper.<clinit>(SandeshaMessageHelper.java:38)
[SimpleAxisServer] Shutting down. Error starting SimpleAxisServer

需把 core jar 中的 resource.properties 手工补进 mar 方可启动(《集成使用指南》给了实测修复步骤)。

  1. 只兼容旧 JDK 时代的运行时:实测 Axis2 1.6.2 启动脚本使用 -Djava.endorsed.dirs,JDK 9+ 环境直接拒绝;推荐 JDK 6/7/8。

  2. 版本沿革与下载渠道收窄(实测):官方 archive 目录 https://archive.apache.org/dist/ws/sandesha2/ 只保留 0.91.3 的旧发行目录;1.41.6.2 只能从 Maven Central 获取,且官方二进制发行包(bin zip)已不可寻。

5.3 兼容性实测矩阵(同机 Ubuntu 22.04 一手实测)

组合实测结果失败现象与根因
Axis2 1.6.2 + Sandesha2 1.6.2 + JDK 8✅ RM 序列跑通无
Axis2 1.6.2 + Sandesha2 1.6.2 + JDK 17❌ 服务端起不来-Djava.endorsed.dirs ... is not supported,JVM 拒绝创建(Axis2 1.6.2 启动脚本固定携带 endorsed dirs 参数)
Axis2 1.8.2 + Sandesha2 1.6.2 + JDK 17❌ 模块部署失败module.xml 的 MEP http://www.w3.org/2006/01/wsdl/in-only 不受支持,DeploymentException,模块被标记 invalid

补充说明:Axis2 1.8.2 的 bin 发行包自身还有一个与 Sandesha2 无关的脚本缺陷——bin/axis2server.sh 引用的启动类 org.apache.axis2.transport.SimpleAxis2Server 在 1.8.2 中已迁移为 org.apache.axis2.kernel.SimpleAxis2Server,实测直接运行报 ClassNotFoundException(可用正确类名手工启动,详见《Apache Sandesha2 在 Ubuntu 22.04 集成使用指南》五、2)。该缺陷不影响上述 Sandesha2 断裂结论:换用正确启动类后模块部署依然失败。

5.4 存量系统迁移评估清单

维护一个使用了 Sandesha2 的存量系统时,建议按以下清单核对(每项都有对应实测依据):

  1. 核对 Axis2 版本:解开发布物里 Axis2 的 repository/modules/,确认 sandesha2 mar 版本与 Axis2 版本;Axis2 ≥ 1.7 的栈实测不可与 Sandesha2 1.6.2 共存,需整体锁定在 Axis2 1.6.x;
  2. 核对 JDK:确认运行时 JDK ≤ 8,否则启动脚本与老字节码双重失败;
  3. 核对 mar 来源:Maven Central 的 sandesha2-1.6.2.mar 缺 i18n 资源(见 5.2 第 2 条),从旧发行包拷来的 mar 应先 unzip -l 检查是否含 org/apache/sandesha2/i18n/resource.properties;
  4. 核对存储管理器:默认内存存储,重启丢序列;若业务依赖"重启续传",检查是否真正部署了数据库版存储实现;
  5. 规划退出路径:以 Apache CXF WS-RM 或消息中间件为目标做演进,Sandesha2 只应作为过渡期维持手段。

5.5 新项目选型建议

对新项目明确不建议选 Sandesha2:无安全修复、无兼容性维护、绑定已停止演进的 Axis2 1.6.x 运行时。若确需 WS-RM,应选 Apache CXF(内置 WS-RM 1.1/1.2,持续维护);若可以跳出 WS-RM 协议本身,优先考虑消息中间件或 gRPC 等现代方案(见第六节)。

六、同类选型对比

Java 生态里能提供"可靠消息传送"能力的候选不止 Sandesha2 一个,横向对比如下:

方案形态RM 规范/机制维护状态适用
Apache Sandesha2 1.6.2Axis2 模块(.mar)WS-RM 2005-02 + 1.1 CD42012 年后停更,实测仅兼容 Axis2 1.6.x存量 Axis2 老系统维护
Apache CXF WS-RMCXF 功能特性WS-RM 1.1/1.2(OASIS)活跃维护新建 SOAP/WS-RM 互操作
Metro (JAX-WS RI)JAXB/JAX-WS 栈内WS-RM 1.1(HighPriority 架构)社区维护JAX-WS 存量应用
Windows WCF.NET 栈内WS-RM 2005-02/1.1.NET Framework 生态与 .NET 互操作遗留
消息中间件(ActiveMQ/RabbitMQ/Kafka)独立集群自有协议(AMQP 等)活跃新系统首选,异构解耦
gRPCRPC 框架HTTP/2 流 + 应用层重试活跃新系统、强类型多语言

关键差异与选型解读:

  • 维护状态是第一决策因子:Sandesha2 只剩"存量维护"价值,任何新集成都会把系统锁死在 Axis2 1.6.x + JDK 8 的历史栈上;
  • 若必须走 WS-RM 标准协议(对端是 WCF/老系统),CXF 是当前 Java 侧唯一活跃且标准符合度高的选择;
  • 若可靠性诉求本质是"不丢消息、削峰、异步解耦",WS-RM 并非唯一解,消息中间件在运维生态与水平扩展上全面占优。

💡 技术拓展:同样是"可靠传输",协议级与应用级方案的区别——

维度WS-RM(协议级)MQ(应用级)
可靠范围单个请求/响应消息序列消息全生命周期(含持久化、重投)
依赖双方同一 SOAP 栈 + WS-Addressing双方各自对接同一 MQ
扩展性受限于 HTTP 端点集群水平扩展成熟
适用既有 SOAP 系统间增强新系统架构主线

本文因主题是 Axis2 生态实测,实际验证的是 Sandesha2(协议级);新系统建议优先评估 MQ 方案。

七、参考链接