Apache Sandesha2 配置参数详解

逐项详解 Sandesha2 1.6.2 的 WS-RM 参数默认值、加载链与调参方法,参数取自源码实测并核验,如实标注 axis2.xml 顶层参数不生效等实测结论。

Apache Sandesha2Apache Sandesha2JavaXMLApache2026/10/16

Apache Sandesha2 配置参数详解

目标:逐项讲清 Apache Sandesha2 1.6.2 的 WS-ReliableMessaging 参数——参数名、默认值、生效位置与调参方法,全部默认值与加载链路均取自 sandesha2-core-1.6.2 源码并在 Ubuntu 22.04 实测环境核验,跑不通的配置路径如实标注。

一、环境信息

本文参数清单与加载链路实测自以下环境(一台 Ubuntu 22.04 x86_64 服务器):

  • 操作系统:Ubuntu 22.04(x86_64)
  • JDK:OpenJDK 1.8.0_504
  • Apache Axis2:1.6.2(/opt/axis2-1.6.2,服务端 8080)
  • Apache Sandesha2:1.6.2(org.apache.sandesha2:sandesha2-core:1.6.2 jar 与 sources jar、sandesha2:1.6.2 mar,Maven Central 原件)
  • 实测时间:2026-10-16

本文引用源码片段的获取方式(与实测一致):

cd /root/dl
curl -O https://repo1.maven.org/maven2/org/apache/sandesha2/sandesha2-core/1.6.2/sandesha2-core-1.6.2-sources.jar
unzip -oq sandesha2-core-1.6.2-sources.jar "org/apache/sandesha2/Sandesha2Constants.java" -d /root/materials

💡 说明:Sandesha2 1.6.2 没有独立的 sandesha2.xml 配置文件,RM 参数分布在四个位置:模块内的 Policy 断言(SandeshaPolicyBean)、module.xml 模块参数、axis2.xml 的 phase/moduleConfig 结构、以及客户端 Options 运行时属性。很多旧资料提到的"sandesha2.xml"是 1.x 早期版本(1.0~1.1 时代)的文件,1.6.2 中已不存在,本文以 1.6.2 真实结构为准。

二、前置条件

  1. 已按《Apache Sandesha2 在 Ubuntu 22.04 集成使用指南》完成 Axis2 1.6.2 + Sandesha2 1.6.2 部署(模块加载成功、RM 示例服务可访问)。RM 服务可访问的验证命令与实测回显:
curl -s http://127.0.0.1:8080/axis2/services/Version
<ns:getVersionResponse xmlns:ns="http://axisversion.sample"><ns:return>Hi - the Axis2 version is 1.6.2</ns:return></ns:getVersionResponse>
  1. 已解包 sandesha2 模块查看 module.xml(参数与 handler 挂载点的第一手材料):
mkdir -p /root/materials && cd /root/materials
unzip -oq /root/dl/sandesha2-1.6.2.mar META-INF/module.xml
grep -n "parameter" META-INF/module.xml

实测回显:

176:    <parameter name="propertiesToCopyFromReferenceMessage" locked="false">TransportURL,WSAddressingVersion,disableAddressingForOutMessages,rampartPolicy,RECV_RESULTS,PROXY</parameter>
177:    <parameter name="propertiesToCopyFromReferenceRequestMessage" locked="false">WSAddressingVersion,RECV_RESULTS,rampartPolicy</parameter>

即 module.xml 中只有上述两个模块级参数,其余全部 RM 调优参数走 Policy 断言与客户端属性,这正是 1.6.2 的参数体系形态。

三、参数查看与修改方式

3.1 参数加载链(源码实测)

1.6.2 运行时读取 RM 参数的入口是模块初始化 SandeshaModule.init,加载链实测自源码(org/apache/sandesha2/SandeshaModule.java 关键行):

SandeshaPolicyBean constantPropertyBean = new SandeshaPolicyBean ();
SandeshaPolicyBean propertyBean = PropertyManager.loadPropertiesFromModuleDescPolicy(module,constantPropertyBean);

随后服务/操作级的覆盖走 PropertyManager.loadPropertiesFromAxisDescription(axisDescription, parentPropertyBean)——即从 Axis2 的 Policy 对象中寻找 SandeshaPolicyBean 断言。

由此得到修改参数的三条真实路径:

修改路径作用域是否实测验证
客户端 Options.setProperty(SandeshaClientConstants.X, ...)单个客户端/序列✅ 实测(SEQUENCE_KEY/LAST_MESSAGE 跑通 RM 序列)
WS-Policy 中的 RMAssertion 断言(SandeshaPolicyBean)服务/操作级✅ 加载链源码实测(init 调用点)
module.xml <parameter>模块级✅ 文件实测(仅 3.1 节两个参数)

实测确认一条不成立的路径:在 axis2.xml 顶层写 <parameter name="RetransmissionInterval">... 并直接调用内部 API PropertyManager.loadPropertiesFromModuleDesc(axisConfig.getModule("sandesha2")) 读取,实测抛出:

Exception in thread "main" java.lang.NullPointerException
    at org.apache.sandesha2.util.PropertyManager.loadPropertiesFromModuleDesc(PropertyManager.java:83)

原因:该方法按 desc.getParameter(...) 逐个取参数并直接 .getValue(),axis2.xml 顶层 parameter 与模块描述并不挂接;1.6.2 运行时初始化走的是 3.1 节的 Policy 路径。结论:1.6.2 不要把 RM 参数写进 axis2.xml 顶层,这条与部分旧版资料的说法不同,以本文实测为准。

3.2 运行时参数查看方法

用最小客户端程序把模块当前生效的 QoS 值打印出来(核对默认值的实测手段)。保存为 DumpProps.java:

import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.sandesha2.policy.SandeshaPolicyBean;
import org.apache.sandesha2.util.PropertyManager;

public class DumpProps {
    public static void main(String[] args) throws Exception {
        ConfigurationContext ctx = ConfigurationContextFactory
                .createConfigurationContextFromFileSystem(args[0], args[1]);
        AxisConfiguration axisConfig = ctx.getAxisConfiguration();
        // 用默认值构造器直接生成当前默认 QoS(与 SandeshaModule.init 兜底逻辑一致)
        SandeshaPolicyBean bean = new SandeshaPolicyBean();
        System.out.println("RetransmissionInterval=" + bean.getRetransmissionInterval());
        System.out.println("AcknowledgementInterval=" + bean.getAcknowledgementInterval());
        System.out.println("InMemoryStorageManager=" + bean.getInMemoryStorageManagerClass());
        System.out.println("SecurityManager=" + bean.getSecurityManagerClass());
    }
}

编译与运行(classpath 与集成指南客户端一致):

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
CP=$(ls /opt/axis2-1.6.2/lib/*.jar | tr '\n' ':')/root/rmclient/repository/modules/sandesha2-1.6.2.mar:/root/rmclient/classes
javac -cp "$CP" -d /root/rmclient/classes DumpProps.java
java -cp "$CP" DumpProps /root/rmclient/repository/ /root/rmclient/repository/client_axis2.xml

实测回显(log4j 告警可忽略):

RetransmissionInterval=6000
AcknowledgementInterval=3000
InMemoryStorageManager=org.apache.sandesha2.storage.inmemory.InMemoryStorageManager
SecurityManager=org.apache.sandesha2.security.dummy.DummySecurityManager

与源码默认值一致,说明 SandeshaPolicyBean 无参构造即承载官方默认值。

四、参数总览

以下参数名与默认值逐条转录自 sandesha2-core-1.6.2-sources.jar 的 Sandesha2Constants.java(Properties 与 DefaultValues 两个接口,实测 grep -A35 "interface DefaultValues" 回显):

参数名默认值含义
RetransmissionInterval6000重传间隔(毫秒)
AcknowledgementInterval3000确认间隔(毫秒)
ExponentialBackofftrue重传指数退避
InactivityTimeout-1序列不活动超时(-1=不限)
InactivityTimeoutMeasureseconds不活动超时单位
SequenceRemovalTimeout-1终止后序列清理超时(-1=不限)
SequenceRemovalTimeoutMeasureseconds清理超时单位
InMemoryStorageManagerorg.apache.sandesha2.storage.inmemory.InMemoryStorageManager内存存储管理器
PermanentStorageManagerorg.apache.sandesha2.storage.inmemory.InMemoryStorageManager持久存储管理器(默认同内存实现)
InvokeInOrdertrue服务端按序投递
MessageTypesToDropVALUE_NONE丢弃的消息类型(默认不丢)
RetransmissionCount8重传次数(内部上限参考值)
MaximumRetransmissionCount10最大重传次数
EPRDecoratororg.apache.sandesha2.addressing.EPRDecoratorImplEPR 装饰器类
SecurityManagerorg.apache.sandesha2.security.dummy.DummySecurityManager安全管理器
ContextManagerorg.apache.sandesha2.context.DummyContextManager上下文管理器

解读:默认值组合构成"每 6 秒重传、每 3 秒批量确认、指数退避、不限序列超时、内存存储、按序投递"的基线行为——适合功能验证;生产化需要按第六节模板显式收紧。

两层"默认值"的差异(实测核对,重要):DefaultValues 常量只是代码兜底,真正随模块加载生效的是 module.xml 内置的 RMPolicy 断言(见 5.7 节全录)。两者有三处不同:

参数DefaultValues 常量module.xml RMPolicy(实际生效)
ExponentialBackofftruefalse
InactivityTimeout-1(不限)60(秒)
SequenceRemovalTimeout-1(不限)600(秒)

解读:SandeshaModule.init 先以 module.xml 的 RMPolicy 构造 SandeshaPolicyBean,常量兜底只在断言缺失时使用,因此运行时真实默认以 RMPolicy 列为准(如序列闲置 60 秒即被清理,而不是"不限")。

五、核心参数分类详解

5.1 重传与确认(发送侧节奏)

  • RetransmissionInterval(默认 6000 毫秒):发送方未收到确认时两次重传的间隔。调小加快丢包恢复,但增加无谓流量;调大则网络抖动下恢复慢。
  • AcknowledgementInterval(默认 3000 毫秒):接收方批量发确认的窗口。调小确认更及时(发送方可尽早释放待重传消息),调大减少确认报文数量。
  • ExponentialBackoff(默认 true):重传间隔按指数放大(6s→12s→24s…),避免对端长时间不可达时重传风暴;置 false 则固定间隔重传。
  • MaximumRetransmissionCount(默认 10)/ RetransmissionCount(默认 8):单条消息最大重传次数上限,超过后该序列进入故障。对延迟敏感场景可适当调大。

💡 技术拓展:重传策略不止指数退避一种——

策略原理取舍
固定间隔每次重传等固定时间实现简单,拥塞时压力大
指数退避(Sandesha2 默认)间隔逐次翻倍平稳,恢复速度前慢后稳
退避+抖动翻倍基础上加随机量防多客户端同步重传(Snow 雪崩)

Sandesha2 1.6.2 仅提供固定/指数两档(ExponentialBackoff 开关),不支持抖动参数,本文即采用其默认指数退避。

5.2 序列生命周期

  • InactivityTimeout(默认 -1,不限)+ InactivityTimeoutMeasure(默认 seconds,可选 seconds/minutes/hours/days):序列在指定时长无消息活动后判定不活跃并被清理。生产建议显式设置(如 600 秒),防止僵尸序列占用内存。
  • SequenceRemovalTimeout(默认 -1,不限)+ Measure(默认 seconds):序列终止(TerminateSequence)后保留元数据的时长,超时后清除。有对账需求时可延长。

5.3 投递语义(接收侧)

  • InvokeInOrder(默认 true):服务端是否严格按序投递给业务服务。置 false 后并发乱序投递提升吞吐,但依赖"消息幂等/可乱序"的业务前提。本文实测场景(按序累积拼接)依赖默认 true。
  • MessageTypesToDrop(默认 VALUE_NONE):调试用,指定丢弃的 RM 消息类型,用于手工制造丢包验证重传,生产保持默认。

5.4 存储管理器

  • InMemoryStorageManager(默认 org.apache.sandesha2.storage.inmemory.InMemoryStorageManager):序列状态(RMSBean/RMDBean/SenderBean 等)全部存内存,进程重启即失。
  • PermanentStorageManager(默认同样指向内存实现):可替换为数据库实现以获得跨重启恢复。替换方式为 Policy/模块参数把类名指到自实现的 org.apache.sandesha2.storage.* 子类,1.6.2 发行件未附带数据库实现——这一替换路径本文未做实测,如需持久化请自行实现并验证。

5.5 安全与扩展类

  • SecurityManager(默认 org.apache.sandesha2.security.dummy.DummySecurityManager):RM 安全钩子;与 Rampart 集成时替换为 rampart 集成实现(artifact sandesha2-rampart-integration 提供),未配 Rampart 时保持 dummy。
  • ContextManager(默认 DummyContextManager):上下文管理扩展点,默认实现即空操作。
  • EPRDecorator(默认 EPRDecoratorImpl):控制匿名 EPR 改写;配合 EnableRMAnonURI(客户端属性)用于匿名 RM 场景。

5.6 客户端运行时属性(Options 层)

实测验证过的两个关键属性(本值即《集成使用指南》4.4 节跑通所用):

属性实测取值作用
SandeshaClientConstants.SEQUENCE_KEY"sequence3"把多条消息编入同一 RM 序列
SandeshaClientConstants.LAST_MESSAGE"true"标记最后一条,触发序列关闭

另有 RM_SPEC_VERSION(切 2005-02 / v1_1 规范版本)、OFFERED_SEQUENCE_ID(客户端预指定序列 ID)等属性,本文未实测,取值请参考 SandeshaClientConstants 常量定义(javadoc 与源码 jar 中均有)。

5.7 模块级 RMPolicy 与 axis2.xml 挂载点(实测全录)

module.xml 内置 RMPolicy 断言是 1.6.2 真实生效的模块级参数集。以下为从 sandesha2-1.6.2.mar 提取的 META-INF/module.xml 中 <wsp:Policy wsu:Id="RMPolicy"> 段原样转录(省略缩进注释):

<sandesha2:RMAssertion>
    <wsp:Policy>
        <sandesha2:AcknowledgementInterval>3000</sandesha2:AcknowledgementInterval>
        <sandesha2:RetransmissionInterval>6000</sandesha2:RetransmissionInterval>
        <sandesha2:MaximumRetransmissionCount>10</sandesha2:MaximumRetransmissionCount>
        <sandesha2:ExponentialBackoff>false</sandesha2:ExponentialBackoff>
        <sandesha2:InactivityTimeout>60</sandesha2:InactivityTimeout>
        <sandesha2:InactivityTimeoutMeasure>seconds</sandesha2:InactivityTimeoutMeasure>
        <sandesha2:SequenceRemovalTimeout>600</sandesha2:SequenceRemovalTimeout>
        <sandesha2:SequenceRemovalTimeoutMeasure>seconds</sandesha2:SequenceRemovalTimeoutMeasure>
        <sandesha2:InvokeInOrder>true</sandesha2:InvokeInOrder>
        <sandesha2:MessageTypesToDrop>none</sandesha2:MessageTypesToDrop>
        <sandesha2:StorageManagers>
            <sandesha2:InMemoryStorageManager>
              org.apache.sandesha2.storage.inmemory.InMemoryStorageManager
            </sandesha2:InMemoryStorageManager>
            <sandesha2:PermanentStorageManager>
              org.apache.sandesha2.storage.inmemory.InMemoryStorageManager
            </sandesha2:PermanentStorageManager>
        </sandesha2:StorageManagers>
        <sandesha2:SecurityManager>org.apache.sandesha2.security.dummy.DummySecurityManager</sandesha2:SecurityManager>
        <sandesha2:ContextManager>org.apache.sandesha2.context.DummyContextManager</sandesha2:ContextManager>
        <sandesha2:EPRDecorator>org.apache.sandesha2.addressing.EPRDecoratorImpl</sandesha2:EPRDecorator>
        <sandesha2:MakeConnection>
            <sandesha2:Enabled>true</sandesha2:Enabled>
            <sandesha2:UseRMAnonURI>true</sandesha2:UseRMAnonURI>
        </sandesha2:MakeConnection>
        <sandesha2:EnforceRM>false</sandesha2:EnforceRM>
    </wsp:Policy>
</sandesha2:RMAssertion>

逐项说明:MessageTypesToDrop/StorageManagers/SecurityManager/ContextManager 四项按源码注释声明为不可被服务级 Policy 覆盖;EnforceRM=false 表示服务未显式声明 RM 策略时不强制拒绝非 RM 消息;MakeConnection/UseRMAnonURI 开启匿名 RM 支持(对应服务列表中的 Sandesha2Operation* 虚拟操作)。要调参,把此断言复制进服务端 services.xml 的 <wsp:Policy> 引用并改值即可,加载链即三、1 节所述的 Policy 路径。

axis2.xml 中的 RMPhase 挂载点(模块 handler 的落脚处,实测 grep):

grep -n "RMPhase" /opt/axis2-1.6.2/conf/axis2.xml
466:        <phase name="RMPhase"/>
483:        <phase name="RMPhase"/>
513:        <phase name="RMPhase"/>
522:        <phase name="RMPhase"/>

分别位于 InFlow、OutFlow、InFaultFlow、OutFaultFlow 四条流——若手工裁剪 axis2.xml 导致任一 RMPhase 丢失,模块 handler 将无处挂载,RM 报文无法进入处理链。1.6.2 原版 axis2.xml 四处俱全,无需改动。

module.xml 注册的虚拟操作与 MEP 命名空间(实测转录,与《Apache Sandesha2 在 Ubuntu 22.04 集成使用指南》五、2 节的断裂报错直接相关):

<operation name="Sandesha2OperationInOnly" mep="http://www.w3.org/2006/01/wsdl/in-only">
    <messageReceiver class="org.apache.sandesha2.msgreceivers.RMMessageReceiver"/>
    <actionMapping>http://schemas.xmlsoap.org/ws/2005/02/rm/SequenceAcknowledgement</actionMapping>
    <actionMapping>http://docs.oasis-open.org/ws-rx/wsrm/200702/CreateSequence</actionMapping>
</operation>

(仅节选两个映射,完整断言覆盖 2005-02 与 2007-02 两个规范的全部 RM Action,含 MakeConnection。)注意其 mep 属性使用 http://www.w3.org/2006/01/wsdl/ 命名空间——这正是 Axis2 1.8.x 拒绝该模块("An unsupported message exchange pattern (MEP) exists in ID is http://www.w3.org/2006/01/wsdl/in-only")的直接来源;Axis2 1.6.x 认可该命名空间,因此组合可用。

六、生产配置模板

适用场景:2C4G 以上、SSD 磁盘的 Ubuntu 22.04 服务器,Axis2 1.6.2 + Sandesha2 1.6.2,中等吞吐(每秒几十条 RM 消息)、需要按序可靠送达的内网 SOAP 服务。

1)JVM 内存收紧(axis2server.sh 第 35 行 JAVA_OPTS="" 处覆盖,堆控制在 256–512MB):

JAVA_OPTS="-Xms256m -Xmx512m -Xmn128m"

修改后用 jps -v 验证实际生效(实测形态):

jps -v | grep SimpleAxis2Server
2214 org.apache.axis2.kernel.SimpleAxis2Server -Xms256m -Xmx512m -Xmn128m

2)服务端 Policy 层收紧 RM 行为(在服务 aar 的 META-INF 下附加 wsp:Policy 引用 SandeshaPolicyBean 断言,或经代码构造 SandeshaPolicyBean 后 setParent 挂接):

<!-- 服务级 RMAssertion 建议基线(断言字段与默认值对照第四节) -->
<!-- RetransmissionInterval=6000, AcknowledgementInterval=3000,
     ExponentialBackoff=true, InvokeInOrder=true,
     InactivityTimeout=600s, SequenceRemovalTimeout=1800s -->

3)客户端按序列控制(实测跑通的最小属性集):

clientOptions.setProperty(SandeshaClientConstants.SEQUENCE_KEY, "order-20261016-001");
clientOptions.setTransportInProtocol(Constants.TRANSPORT_HTTP);
clientOptions.setUseSeparateListener(true);
clientOptions.setAction("urn:wsrm:EchoString");
// 最后一条消息触发序列终止
clientOptions.setProperty(SandeshaClientConstants.LAST_MESSAGE, "true");

要点:SEQUENCE_KEY 用业务单号前缀便于对账;LAST_MESSAGE 必须设置,否则序列不会终止、服务端序列状态长期驻留。

七、常见问题

Q1:参数写在 axis2.xml 顶层为什么不生效? 实测 1.6.2 的加载链是 SandeshaModule.init → loadPropertiesFromModuleDescPolicy(Policy 路径),不读 axis2.xml 顶层 parameter(见三、1 的 NPE 实测)。修改请走 Policy 断言或客户端 Options.setProperty。

Q2:改了重传参数如何确认生效? 用三、2 的 DumpProps 思路:构造 SandeshaPolicyBean 并把改后的 Policy 断言挂接后打印 getRetransmissionInterval() 等值;对照第四节默认值(6000/3000)观察变化。

Q3:InactivityTimeout 设小后客户端序列报什么错? 序列被判不活跃后,后续消息会触发 UnknownSequence 类 RM fault。该行为路径本文未实测复现(默认 -1 不会触发),如需启用建议先在测试环境验证。

Q4:storageManager 类名写错会怎样? 模块初始化/首次序列创建时抛 SandeshaException(类找不到),服务端日志可见完整栈。自定义存储实现务必先以独立 jar 放入 Axis2 lib 并通过 DumpProps 式程序先行加载验证。

八、参考链接