Проблема подключения TCP-клиента Spring Integration во 2-м сеансе запроса

У меня есть требование Spring Integration + spring, где я должен установить TCP-соединение клиента с удаленным сервером и отправить запрос, состоящий из тысяч записей, обработанных из весеннего пакета. Я использую MessageBuilder для полезной нагрузки и канала сообщений для отправки данных. Мы отправляем все записи, а затем отправляем запрос полезной нагрузки ответного сообщения, чтобы начать получать ответ от сервера. Сервер отвечает ответными данными, которые обрабатываются с помощью преобразователя и добавляются в канал очереди для последующего чтения.

@Configuration
@EnableIntegration
public class GatewayConfig {

    private static final Logger logger = LoggerFactory.getLogger(GatewayConfig.class);
    @Autowired
    private GatewayProperties properties;
    
    /**Abstract class for client connection factories.
     * 
     * @return AbstractClientConnectionFactory
     * @throws Exception 
     */
    
    @Bean
    public AbstractClientConnectionFactory clientCF() {
        AbstractClientConnectionFactory factory = new TcpNetClientConnectionFactory( "138.25.189.110",5030);
        factory.setSoKeepAlive(true);
        factory.setDeserializer(new ByteArraySingleTerminatorSerializer((byte) 13));
        return factory;
    }
    
    
    
    /**
     * Receives messages over TCP.
     * Specify the MessageChannel to which produced Messages should be sent.
     * @param connectionFactory
     * @return TcpReceivingChannelAdapter
     */
    @Bean
    public TcpReceivingChannelAdapter inboundAdapterClient(@Qualifier("clientCF")AbstractClientConnectionFactory connectionFactory) {
        TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
    //  adapter.setOutputChannelName(GatewayConstants.AGGREGATOR_PRE_INPUT_CHANNEL);
        adapter.setOutputChannelName(GatewayConstants.PRETRANSFORM_CHANNEL);
        adapter.setErrorChannelName(GatewayConstants.TCP_ERROR);
        adapter.setClientMode(true);
        adapter.setConnectionFactory(connectionFactory);
        return adapter;
    }

    
    @Bean(GatewayConstants.RECEIVE_CHANNEL_NAME)
    public QueueChannel receivingChannel() {
        
        return new QueueChannel();
    }
    
    @Bean
    @Transformer(inputChannel = GatewayConstants.PRETRANSFORM_CHANNEL, outputChannel = GatewayConstants.RECEIVE_CHANNEL_NAME)
    public Pretransform pretransformMet() {
        return new Pretransform();
    }
    
    
    /**
     * Sends messages over TCP
     * @param connectionFactory
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = GatewayConstants.SEND_TO_VENDOR_CHANNEL_NAME)
    public TcpSendingMessageHandler messageHandlerClient(@Qualifier("clientCF")AbstractClientConnectionFactory connectionFactory) {
        TcpSendingMessageHandler sendingHandler = new TcpSendingMessageHandler();
        sendingHandler.setConnectionFactory(connectionFactory);
        sendingHandler.setClientMode(true);
        
        return sendingHandler;
    }
    
    /**
     * 
     * @return
     */
    @Bean(GatewayConstants.TCP_ERROR)
    public MessageChannel tcpErrrorChannel() {
        return new DirectChannel();
    }
    
    @Bean(GatewayConstants.PRETRANSFORM_CHANNEL)
    public MessageChannel preReceiveChannel() {
        return new DirectChannel();
    }
    
    @Bean(GatewayConstants.BATCH_SEND_CHANNEL_NAME)
    public MessageChannel sendchannel() {
        return new DirectChannel();
    }
    
    /**
     * 
     * @return
     */
    @Bean(GatewayConstants.SEND_TO_VENDOR_CHANNEL_NAME)
    public MessageChannel sendToVendorChannel() {
        return new DirectChannel();
    }

Пакетное задание выполняется в полночь каждый день. После запуска/развертывания приложения запрос отправляется и ответ получен успешно, но на следующий день сервер не получает никаких данных. При отправке запроса нет исключений соединения tcp, но сервер не получает никаких данных на его конце.

Я даже установил для singleuse значение true, но получаю исключение времени выполнения, которое клиент не может установить для использования пения в true. Есть ли способ, которым я могу регистрировать каждый раз, когда соединение устанавливается, и состояние TCP-соединения перед отправкой запроса и после получения ответа? Благодарю вас за помощь и заранее благодарю.


person Pradyp    schedule 13.09.2020    source источник


Ответы (1)


Вы можете добавить bean-компонент ApplicationListener (или метод @EventListener) для получения всех видов TcpConnectionEvent (открыть, закрыть и т. д.).

См. документацию< /а>.

ИЗМЕНИТЬ

Просто добавьте это к одному из ваших бобов...

@EventListener
public void connectionEvent(TcpConnectionEvent event) {
    ...
}
person Gary Russell    schedule 14.09.2020
comment
Есть ли у нас какие-либо примеры реализации EventListener для событий подключения клиента TCP. - person Pradyp; 15.09.2020
comment
Спасибо, Гэри. Я вижу журналы отладки интеграции Spring, которые открываются и закрываются через TCP-сокет каждые 1 минуту. Я не ставил singleuse true, но почему то соединение закрывается и открывается каждую минуту.ClientCF: Added new connection: localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 ClientCF: Removed closed connection: localhost:5030:52987:3e541599-ad5c-4ca2-9a93-506894874dd5 Connection localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 established Available to read:0 Connection localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 established - person Pradyp; 15.09.2020
comment
Не оставляйте подобные вещи в комментариях; вместо этого отредактируйте вопрос и прокомментируйте, что вы это сделали. Скорее всего сервер закрывает незанятое соединение. Трассировка сети (например, Wireshark) подтвердит. - person Gary Russell; 15.09.2020
comment
Конечно, Гэри, я позабочусь об этом. Я использовал прослушиватель событий и смог зафиксировать открытие и закрытие TCP-соединения. Могу ли я вручную сбросить соединение? - person Pradyp; 30.09.2020
comment
Вы можете вызвать closeConnection() в фабрике соединений, используя свойство соединения connectionId. - person Gary Russell; 01.10.2020
comment
Спасибо, Гэри. При необходимости я могу открыть соединение с помощью getconnection, верно? - person Pradyp; 01.10.2020
comment
Да, можете, но поскольку у вас есть adapter.setClientMode(true);, адаптер повторно откроет соединение на основе retryInterval. Отправка сообщения исходящему адаптеру также приведет к открытию соединения, если это необходимо. - person Gary Russell; 01.10.2020