2016-10-17 2 views
0

Есть ли способ изменить порт, используемый tcp-входящим шлюзом на лету? Я хотел бы установить порт и таймаут, используемые tcp-inbound-gateway на основе конфигурации, сохраняющейся в базе данных, и иметь возможность изменять их на лету без перезапуска приложения. Для того, чтобы сделать это, я решил использовать «публиковать-подписчик» модель и расширенный класс TcpInboundGateway:Как изменить порт, используемый tcp-ibound-gateway на лету

public class RuntimeInboundGateway extends TcpInboundGateway implements SettingsSubscriber { 

    @Autowired 
    private Settings settings; 

    @PostConstruct 
    public void subscribe() { 
     settings.subscribe(this); 
    } 

    @Override 
    public void onSettingsChanged(Settings settings) { 
     this.stop(); 
     AbstractByteArraySerializer serializer = new ByteArrayLfSerializer(); 
     TcpNetServerConnectionFactory connectionFactory = new TcpNetServerConnectionFactory(settings.getPort()); 
     connectionFactory.setSerializer(serializer); 
     connectionFactory.afterPropertiesSet(); 
     this.setConnectionFactory(connectionFactory); 
     this.afterPropertiesSet(); 
     this.start(); 
    } 
} 

Объект settings одноэлементно боб и при его изменении ТКТА въездного шлюз начинает действительно прослушивает новый порт но похоже, что он не отправляет входящие сообщения дальше по потоку. Вот выдержка из конфигурации XML:

<int-ip:tcp-connection-factory id="connFactory" type="server" port="${port}" 
            serializer="serializer" 
            deserializer="serializer"/> 

    <bean id="serializer" class="org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer"/> 

    <bean id="inboundGateway" class="com.example.RuntimeInboundGateway"> 
     <property name="connectionFactory" ref="connFactory"/> 
     <property name="requestChannel" ref="requestChannel"/> 
     <property name="replyChannel" ref="responseChannel"/> 
     <property name="errorChannel" ref="exceptionChannel"/> 
     <property name="autoStartup" value="true"/> 
    </bean> 

Существует вход-канальный адаптер в конфигурации, которая регистрирует все запросы в службу без каких-либо вопросов, пока настройки не будут изменены. После этого нет, и я не вижу сообщений, хотя я могу подключиться к новому порту с помощью telnet localhost <NEW_PORT>. Может ли кто-нибудь взглянуть и сказать, как можно добиться желаемого поведения?

ответ

0

Причиной неприятностей является я. Поскольку десериализатор не указан в коде выше, используется значение по умолчанию, и он не может разграничить входящие сообщения от входного потока байтов. Только одна строка connectionFactory.setDeserializer(serializer); решила проблему, которую я провел день.

0

быстрый взгляд на ваш код указал он должен работать нормально, так что я просто написал быстрое приложение Spring загрузки, и она работала хорошо для меня ...

@SpringBootApplication 
public class So40084223Application { 

    public static void main(String[] args) throws Exception { 
     ConfigurableApplicationContext ctx = SpringApplication.run(So40084223Application.class, args); 
     Socket socket = SocketFactory.getDefault().createSocket("localhost", 1234); 
     socket.getOutputStream().write("foo\r\n".getBytes()); 
     socket.close(); 
     QueueChannel queue = ctx.getBean("queue", QueueChannel.class); 
     System.out.println(queue.receive(10000)); 
     ctx.getBean(MyInboundGateway.class).recycle(1235); 
     socket = SocketFactory.getDefault().createSocket("localhost", 1235); 
     socket.getOutputStream().write("fooo\r\n".getBytes()); 
     socket.close(); 
     System.out.println(queue.receive(10000)); 
     ctx.close(); 
    } 

    @Bean 
    public TcpNetServerConnectionFactory cf() { 
     return new TcpNetServerConnectionFactory(1234); 
    } 

    @Bean 
    public MyInboundGateway gate(TcpNetServerConnectionFactory cf) { 
     MyInboundGateway gate = new MyInboundGateway(); 
     gate.setConnectionFactory(cf); 
     gate.setRequestChannel(queue()); 
     return gate; 
    } 

    @Bean 
    public QueueChannel queue() { 
     return new QueueChannel(); 
    } 

    public static class MyInboundGateway extends TcpInboundGateway implements ApplicationEventPublisherAware { 

     private ApplicationEventPublisher applicationEventPublisher; 

     @Override 
     public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { 
      this.applicationEventPublisher = applicationEventPublisher; 
     } 

     public void recycle(int port) { 
      stop(); 
      TcpNetServerConnectionFactory sf = new TcpNetServerConnectionFactory(port); 
      sf.setApplicationEventPublisher(this.applicationEventPublisher); 
      sf.afterPropertiesSet(); 
      setConnectionFactory(sf); 
      afterPropertiesSet(); 
      start(); 
     } 

    } 

} 

Я хотел бы включить ведение журнала DEBUG, чтобы увидеть, если это дает вам какие-то подсказки.

Вы также можете захотеть исследовать, используя вместо этого новый DSL dynamic flow registration. tcp-dynamic-client показывает, как использовать эту технику для добавления/удаления фрагментов потока на лету. Он находится на стороне клиента, но аналогичные методы могут использоваться на стороне сервера для регистрации/отмены регистрации вашего шлюза и фабрики соединений.

+0

Hi @Gary Russel, к моему стыду причину неприятностей - это я. Мы используем 'ByteArrayLfSerializer' как для сериализации, так и для десериализации сообщений, и я не установил десериализатор в свой код, используя десериализатор по умолчанию. Извините за беспокойство. Надеемся, что приведенные выше фрагменты кода помогут кому-то в будущем. – user6231016

+0

Обратите внимание, что если вы хотите получать TCP-события, вам необходимо ввести издателя событий в свою фабрику соединений, не связанных с весной. –

+0

Гэри, я некоторое время работал с весной-интеграцией и видел много вопросов о stackoverflow, где вы терпеливо помогаете людям, которые используют весеннюю интеграцию, чтобы найти ответы и решить проблемы, поэтому я хотел бы поблагодарить вас за вашу доброту и поддерживайте и говорите, что ваша помощь очень ценится. – user6231016

Смежные вопросы