有没有办法在运行中更改tcp-inbound网关使用的端口?我想根据数据库中保留的配置设置tcp-inbound-gateway使用的端口和超时,并且能够在不重新启动应用程序的情况下动态更改它们。为此,我决定使用“publish-subscriber”模式和扩展TcpInboundGateway类:
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
对象是一个单例bean,当它被更改时,tcp入站网关开始实际上正在侦听新端口,但看起来它不会在流上进一步发送入站消息。以下是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>
配置中有logging-channel-adapter,可以在更改设置之前将任何请求记录到服务中而不会出现任何问题。之后,它没有,我看到虽然我能够通过telnet localhost <NEW_PORT>
连接到新端口但没有收到任何消息。有人可以看看如何实现理想的行为吗?
答案 0 :(得分:0)
快速查看代码表明它应该可以正常工作,所以我只是编写了一个快速的Spring Boot应用程序,它对我来说很好......
@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显示了如何使用该技术动态添加/删除流片段。它位于客户端,但可以在服务器端使用类似的技术来注册/取消注册您的网关和连接工厂。
答案 1 :(得分:0)
麻烦的原因是我。由于未在上面的代码中指定解串器,因此使用了默认解串器,并且它无法从输入字节流中划分入站消息。只有一行connectionFactory.setDeserializer(serializer);
解决了我花了一天时间的问题。