You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时正确修改JPOS Channel-Adapter的端口?

运行时动态配置JPOS Channel-Adapter的规范实现

问题背景

需要通过JSON POST请求接收用户指定的端口、ISO格式等参数,动态调整JPOS的Channel-Adapter连接配置。现有实现能完成端口切换并正常发送交易,但原端口仍持续尝试重连,不符合JPOS规范做法。

相关代码与配置如下:

Spring接收请求接口

@PostMapping(value = "/message", consumes = DEFAULT_CONTENT_TYPE, produces = 
               DEFAULT_CONTENT_TYPE)
void postIsoMessage(
        @RequestHeader(value = HEADER_CORRELATION_ID) String correlationId,
        @RequestBody JsonMessage requestMessage)
        throws Exception {
     // 处理JSON请求逻辑
       ...
      }

用户请求JSON示例

{
    "config": {
        "keyset": "KEYSET_1",
        "pinblockFmt": "01 - ISO 0 Format",
        "acq": {
            "format": "VISANET",
            "portNumber": 9405
        },
        "iss": {
            "format": "ISO4",
            "portNumber": 9488
        }
    }
}

原Channel-Adapter/Mux XML配置

<channel-adaptor name="iss-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
  <channel class="org.jpos.iso.channel.CSChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
    <property name="packager-config" value="src/main/resources/iso4.xml" />
    <property name="host" value="10.999.99.99" />
    <property name="port" value="9999" />
    <property name="timeout" value="300000" />
  </channel>
  <in>iss-channel-send</in>
  <out>iss-channel-receive</out>
  <reconnect-delay>10000</reconnect-delay>
</channel-adaptor>

<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="iss-mux" realm="acq-realm">
  <in>iss-channel-receive</in>
  <out>iss-channel-send</out>
  <ready>iss-channel.ready</ready>
  <request-listener class="AutoResponder"></request-listener>
</mux>

当前非规范实现

Q2 q2 = new Q2("src/main/java/deploy");
q2.start();
Thread.sleep(3000L);
QMUX qmux = NameRegistrar.getIfExists("mux.acq-mux");
ChannelAdaptor channel = NameRegistrar.getIfExists("iss-channel");
if (channel == null)
    System.out.println("channel doesn't exist");

else {
    channel.setPort(9488); 
    channel.startService(); // 从9999切换到9488端口
    NameRegistrar.register("iss-channel",channel);
    Thread.sleep(3000L);
}

try {
    if (qmux.isConnected()) {
        ISOMsg m = new ISOMsg();
        m.setMTI("0100");
        m.set(2, "4999999999999999");
        // ... 其他字段设置
        ISOMsg response = qmux.request(m, 5000);

当前方案的问题

日志显示新端口9488连接成功并正常交易,但原端口9999仍在尝试重连:

<log realm="channel/10.999.99.99:9488" at="2023-03-02T08:38:04.930" lifespan="3ms">
  <connect>
    Try 0 10.999.99.99:9488
  </connect>
</log>
<log realm="channel" at="2023-03-02T08:38:05.171" lifespan="2051ms">
  <connect>
    Try 0 10.999.99.99:9999
      Connection refused: connect
    Unable to connect
  </connect>
</log>

原因是未停止原Channel-Adapter服务就直接修改参数重启,原服务的重连线程仍在后台运行,导致同时存在两个连接尝试逻辑。

规范实现方式

JPOS推荐通过动态部署服务的方式实现运行时配置调整,核心是先停止原有服务,再根据请求参数重新配置并启动新服务:

步骤1:停止原有Channel-Adapter服务

ChannelAdaptor oldChannel = NameRegistrar.getIfExists("iss-channel");
if (oldChannel != null) {
    oldChannel.stopService();
    NameRegistrar.unregister("iss-channel");
    // 等待服务完全停止
    Thread.sleep(1000L);
}

步骤2:动态构建新的Channel-Adapter配置

可以通过API直接构建Channel和ChannelAdaptor实例,无需依赖XML文件:

// 构建CSChannel
CSChannel newChannel = new CSChannel();
newChannel.setLogger(Q2.getQ2().getLogger(), "iss-channel");
newChannel.setPackager(new GenericPackager("src/main/resources/iso4.xml"));
newChannel.setHost("10.999.99.99");
// 从请求中获取端口
newChannel.setPort(requestMessage.getConfig().getIss().getPortNumber());
newChannel.setTimeout(300000);

// 构建ChannelAdaptor
ChannelAdaptor newChannelAdaptor = new ChannelAdaptor();
newChannelAdaptor.setName("iss-channel");
newChannelAdaptor.setChannel(newChannel);
newChannelAdaptor.setInQueue("iss-channel-send");
newChannelAdaptor.setOutQueue("iss-channel-receive");
newChannelAdaptor.setReconnectDelay(10000);
newChannelAdaptor.setLogger(Q2.getQ2().getLogger(), "iss-channel");

步骤3:注册并启动新服务

// 注册到NameRegistrar
NameRegistrar.register("iss-channel", newChannelAdaptor);
// 启动服务
newChannelAdaptor.startService();
// 等待服务就绪
Thread.sleep(3000L);

可选:动态生成XML部署文件

如果偏好XML配置方式,可以生成临时XML文件,通过Q2的Deployer部署:

String configXml = String.format("""
<channel-adaptor name="iss-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
  <channel class="org.jpos.iso.channel.CSChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2">
    <property name="packager-config" value="src/main/resources/iso4.xml" />
    <property name="host" value="10.999.99.99" />
    <property name="port" value="%d" />
    <property name="timeout" value="300000" />
  </channel>
  <in>iss-channel-send</in>
  <out>iss-channel-receive</out>
  <reconnect-delay>10000</reconnect-delay>
</channel-adaptor>
""", requestMessage.getConfig().getIss().getPortNumber());

// 写入临时文件
File tempConfig = File.createTempFile("iss-channel", ".xml");
Files.writeString(tempConfig.toPath(), configXml);

// 部署到Q2
Q2.getQ2().getDeployer().deploy(tempConfig.getAbsolutePath());

疑问解答

  1. 当前iss-mux是否同时连接两个端口?
    不会。Mux关联的是指定的队列(iss-channel-send/iss-channel-receive),只有当前活跃的Channel-Adapter会向这些队列发送/接收消息。但原端口的重连线程仍在后台运行,会占用系统资源,且可能产生无效日志。

  2. 原端口重连会引发问题吗?
    会。长期运行会导致不必要的线程占用、网络连接尝试,甚至可能因为频繁重连触发目标主机的防火墙限制。必须停止原服务后再启动新配置,才能彻底终止原重连逻辑。

内容的提问来源于stack exchange,提问作者tytyty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:42:50