Spring集成出站通道适配器未关闭打开的套接字并使文件句柄处于打开状态

时间:2016-02-05 11:31:38

标签: spring spring-integration sftp jsch

我们在项目中使用spring集成适配器作为文件ftp,我们面临的问题是,适配器没有关闭打开的套接字连接。 因此,同一个受管服务器中的其他模块因“打开文件过多”而失败。套接字连接异常。有没有办法从通道适配器关闭未使用的打开套接字连接或者我们可以获取底层的jsch连接并从sftp通道适配器关闭套接字。

我们尝试过缓存会话工厂,并没有关闭打开的套接字。文件句柄不断堆积。提前感谢您的投入。

We have two xmls one with outboundAdapter and the other with InboundAdapter. These two are in different xmls as they are different jobs that are run using spring batch. We are expected to send files to a location. 

我们正在使用spring batch 2.2.0和spring integration 2.1.6以及spring integration 2.1.6。

以下是配置: 我们有一个会话工厂,它由cachingSession工厂包装:

<beans:bean id="sftpSessionFactory"
  class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
    <beans:property name="host" value="hostname"/>
    <beans:property name="privateKey" value="somepath"/>
    <beans:property name="port" value="22"/>
</beans:bean>

<bean id="cachingSessionFactory"
  class="org.springframework.integration.file.remote.session.CachingSessionFactory">
    <constructor-arg ref="sftpSessionFactory"/>
    <constructor-arg value="10"/>
    <property name="sessionWaitTimeout" value="1000"/>
</bean>
**and then we have a channel**
<int:channel id="ftpChannel" />

**and then we have the following outbound Channel adapter**
<int-sftp:outbound-channel-adapter id="sftpOutboundAdapter"
    session-factory="cachingSessionFactory"
    channel="inputChannel"
    charset="UTF-8"
    use-temporary-filename="false"/>

**With the above configuration we are using the ftpChannel to send the files by constructing a payload like this:**
message = MessageBuilder.withPayLoad(f).build() // MessageBuilder is //org.springframework.integration.support.MessageBuilder and f is the file

ftpChannel.send(message)

**In another inbound job, the following is the configuration of adapters:
Session factory:**



<beans:bean id="sftpSessionFactory2"
  class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
    <beans:property name="host" value="hostname"/>
    <beans:property name="privateKey" value="somepath"/>
    <beans:property name="port" value="22"/>
</beans:bean>
**Caching session factory:**
<bean id="cachingSessionFactory2"
class="org.springframework.integration.file.remote.session.CachingSessionFactory">
    <constructor-arg ref="sftpSessionFactory2"/>
    <constructor-arg value="10"/>
    <property name="sessionWaitTimeout" value="1000"/>
</bean>
 **and another channel:**
<int:channel id="ftpChannel2" />
 **Now we have the following adapter in this xml:**
<int-sftp:outbound-channel-adapter id="sftpInboundAdapter"
    session-factory="cachingSessionFactory2"
    channel="inputChannel"
    charset="UTF-8"
    use-temporary-filename="false"/>

在上面的xml中使用此配置,我们尝试从第一个xml中配置的cachingSessionFactory获取会话,从中获取会话,获取文件列表,然后使用ftpChannel2.send()发送一些文件并执行session.close()在finally块中。当我在session.close()之后执行session.isOpen()时,我看到返回true。

通过这两个作业,我可以看到很多打开的文件句柄,它们是套接字连接,我对如何关闭这些打开的套接字绝对毫无头绪。

1 个答案:

答案 0 :(得分:0)

只要您不使用缓存会话工厂 - 预期以保持会话打开以供下次使用,操作完成后会话将关闭。

如果启用DEBUG日志记录,您应该了解它的错误。

修改

只是运行它没有问题:

@Test
public void test() throws Exception {
    DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
    sf.setHost("10.0.0.3");
    sf.setUsername("ftptest");
    sf.setPassword("ftptest");
    FtpSession session = sf.getSession();
    Thread.sleep(10000);
    session.close();
    assertFalse(session.isOpen());
    System.out.println("closed");
    Thread.sleep(10000);
}

在第一次睡眠期间netstat -ntp显示套接字打开;套接字在收盘后消失。

会话 是套接字...

public void disconnect() throws IOException
{
    closeQuietly(_socket_);
    ...
}

<强> EDIT2

我忘记了在2.1.x中有cache-sessions属性(2.1.x很旧)。

我刚用这个测试(和2.1.6)......

<bean id="sftpSessionFactory"
    class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
    <property name="host" value="10.0.0.3" />
    <property name="privateKey" value="file:/somPathTo/.ssh/id_rsa" />
    <property name="port" value="22" />
    <property name="user" value="ftptest" />
</bean>

<int:channel id="inputChannel" />

<int-sftp:outbound-channel-adapter id="sftpOutboundAdapter"
    session-factory="sftpSessionFactory"
    channel="inputChannel"
    charset="UTF-8"
    cache-sessions="false"
    use-temporary-file-name="false"
    remote-directory="." />

public class Main {

    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
        File f = new File("foo.txt");
        FileOutputStream fos = new FileOutputStream(f);
        fos.write("bar".getBytes());
        fos.close();
        context.getBean("inputChannel", MessageChannel.class).send(MessageBuilder.withPayload(f).build());
        System.out.println("Sleeping - check socket");
        Thread.sleep(60000); // check socket
        context.close();
        System.exit(0);
    }

}

没有问题(插座关闭);如果我将cache-sessions设置为true,则套接字将按预期保持打开状态。

我注意到你没有remote-directory属性 - 这是非法的:

exactly one of 'remote-directory' or 'remote-directory-expression' is required on a remote file outbound adapter