Spring integration 从SFTP出站网关获取输入流时没有消息

Spring integration 从SFTP出站网关获取输入流时没有消息,spring-integration,Spring Integration,有时从SFTP出站网关获取输入流时没有消息 这是后续问题 我在前面的问题中遇到的问题是,我没有像int:service activator中所示关闭流。然而,当我添加int:service激活器时,我似乎被迫添加int:poller 然而,当我添加int:poller时,我注意到有时现在在尝试获取流时,消息是空的。我发现一种解决方法是简单地重试。我用不同的文件进行了测试,似乎小文件会受到不利影响,而大文件则不会。因此,如果我不得不猜测,肯定存在一个竞争条件,在我尝试调用getInputStre

有时从SFTP出站网关获取输入流时没有消息

这是后续问题

我在前面的问题中遇到的问题是,我没有像int:service activator中所示关闭流。然而,当我添加int:service激活器时,我似乎被迫添加int:poller

然而,当我添加int:poller时,我注意到有时现在在尝试获取流时,消息是空的。我发现一种解决方法是简单地重试。我用不同的文件进行了测试,似乎小文件会受到不利影响,而大文件则不会。因此,如果我不得不猜测,肯定存在一个竞争条件,在我尝试调用getInputStream()之前int:service activator正在关闭会话,但我希望有人能解释这是否是实际发生的情况,以及是否有比重试更好的解决方案

谢谢

以下是出站网关配置:

<int-ftp:outbound-gateway session-factory="ftpClientFactory"
          request-channel="inboundGetStream" command="get" command-options="-stream"
          expression="payload" remote-directory="/" reply-channel="stream">
   </int-ftp:outbound-gateway>

   <int:channel id="stream">
          <int:queue/>
   </int:channel>

   <int:poller default="true" fixed-rate="50" />

   <int:service-activator input-channel="stream"
                 expression="payload.toString().equals('END') ? headers['file_remoteSession'].close() : null" />

以下是我获取InputStream的源:

   public InputStream openFileStream(final int retryCount, final String filename, final String directory)
                 throws Exception {
          InputStream is = null;
          for (int i = 1; i <= retryCount; ++i) {
                 if (inboundGetStream.send(MessageBuilder.withPayload(directory + "/" + filename).build(), ftpTimeout)) {
                       is = getInputStream();
                       if (is != null) {
                              break;
                       } else {
                              logger.info("Failed to obtain input stream so attempting retry " + i + " of " + retryCount);
                              Thread.sleep(ftpTimeout);
                       }
                 }
          }
          return is;
   }

   private InputStream getInputStream() {

          Message<?> msgs = stream.receive(ftpTimeout);

          if (msgs == null) {
                 return null;
          }

          InputStream is = (InputStream) msgs.getPayload();
          return is;
   }
public InputStream openFileStream(最终int retryCount、最终字符串文件名、最终字符串目录)
抛出异常{
InputStream=null;
for(int i=1;i msgs=stream.receive(ftpTimeout));
InputStream为=(InputStream)msgs.getPayload();
MessageHeaders mH=msgs.getHeaders();
Session Session=(Session)mH.get(“file_remoteSession”);
sss=新的SFTPStream会话(会话,is);
}
返回sss;
}

首先,您不需要
payload.toString().equals('END')
,因为看起来您在逻辑中没有使用

第二,你不需要那种难看的
,因为你可以完全访问代码中的消息。你只需获取
文件\u remoteSession
,将其转换到
会话中,并在逻辑结束时调用它的
.close()

是的,存在竞争条件,但它发生在代码中


你看,你有
队列频道
。从一开始你有一个消费者
流。接收(ftpTimeout);
。但是现在你引入了
。因此又有一个竞争消费者。拥有如此小的(
固定费率=“50”
)轮询间隔确实会导致您出现意外行为。

谢谢您的帮助,但我在插入文档以执行我想要的操作时遇到了问题。因此,您的意思是我不需要xml中的
,但可以通过某种方式从
Messag在我的
getInputStream
方法中直接获取
文件\u remoteSession
e
在我获得
InputStream
之后?因此我似乎可以从消息头中获得
文件\u remoteSession
。我可以在
getInputStream
方法中获得输入流后调用close吗???如果您愿意,您可以。但是这是正确的吗?您应该在完成
InputStream
时关闭它所有。例如,当您处理文件时,这一个与标准完全相似。因此,您应该处理来自该流的数据,并且只有在这之后才能关闭会话。否则,您将无法在关闭后处理该流。
public class SftpStreamSession {

    private Session<?> session;
    private InputStream inputStream;

    public void close() {
        inputStream.close();
        session.close();
    }
}
public SftpStreamSession openFileStream(final String filename, final String directory) throws Exception {

    SftpStreamSession sss = null;
    if (inboundGetStream.send(MessageBuilder.withPayload(directory + "/" + filename).build(), ftpTimeout)) {

        Message<?> msgs = stream.receive(ftpTimeout);

        InputStream is = (InputStream) msgs.getPayload();

        MessageHeaders mH = msgs.getHeaders();
        Session<?> session = (Session<?>) mH.get("file_remoteSession");

        sss = new SftpStreamSession(session, is);
    }

    return sss;
}