【发布时间】:2022-06-22 01:32:14
【问题描述】:
简而言之,我有一个使用 spring 实现的套接字应用程序,我分享以下代码:
@SpringBootApplication
public class ExampleApp {
public static void main(String[] args) {
SpringApplication.run(ExampleApp.class, args);
}
@Bean
public AbstractServerConnectionFactory serverConnectionFactory() {
TcpNetServerConnectionFactory tcpNetServerConnectionFactory = new TcpNetServerConnectionFactory(1234);
return tcpNetServerConnectionFactory;
}
@Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
@Bean
public MessageChannel replyChannel() {
return new DirectChannel();
}
@Bean
public TcpReceivingChannelAdapter receivingChannelAdapter(AbstractServerConnectionFactory serverConnectionFactory, MessageChannel requestChannel) {
TcpReceivingChannelAdapter tcpReceivingChannelAdapter = new TcpReceivingChannelAdapter();
tcpReceivingChannelAdapter.setConnectionFactory(serverConnectionFactory);
tcpReceivingChannelAdapter.setOutputChannel(requestChannel);
return tcpReceivingChannelAdapter;
}
@Bean
@ServiceActivator(inputChannel = \"replyChannel\")
public TcpSendingMessageHandler tcpSendingMessageHandler(AbstractServerConnectionFactory serverConnectionFactory) {
TcpSendingMessageHandler tcpSendingMessageHandler = new TcpSendingMessageHandler();
tcpSendingMessageHandler.setConnectionFactory(serverConnectionFactory);
return tcpSendingMessageHandler;
}
@ServiceActivator(inputChannel = \"requestChannel\", outputChannel = \"replyChannel\")
public Message<String> processMessage(Message<String> message) {
Message<String> reply = MessageBuilder
.withPayload(\"OK\")
.setHeader(IpHeaders.CONNECTION_ID, message.getHeaders().get(IpHeaders.CONNECTION_ID, String.class))
.build();
return reply;
}
@Bean
public ApplicationListener<TcpConnectionEvent> listener(MessageChannel replyChannel) {
return tcpConnectionEvent -> {
if (tcpConnectionEvent instanceof TcpConnectionOpenEvent) {
Message<String> message = MessageBuilder
.withPayload(\"Hello client\")
.setHeader(IpHeaders.CONNECTION_ID, tcpConnectionEvent.getConnectionId())
.build();
replyChannel.send(message);
}
};
}
}
当我在本地运行这个应用程序时,一切都很好:
我只是使用 telnet(用于手动连接)并在那里连接,连接后几乎立即看到我的服务器问候语,并且我能够通过命令 -> 响应与服务器通信。
当我在 docker 容器中运行我的应用程序时 - 它有一些麻烦。基本上,它会立即将我连接到服务器,但我会看到延迟 6 秒的问候消息。它也不会回复我的命令,只是在此期间忽略它们。当它打印问候语时 - 它也会显示我的请求的响应。之后,我可以毫无问题地与服务器合作。
有没有人遇到过同样的问题?
UPD:仅作记录,该应用程序没有使用任何数据库,因此非常轻量级
UPD1:也许,问题出在我的 docker compose 文件中,看起来很简单:
app:
image: me/app:v1
container_name: app
build:
context: *ToAppRootDir*
dockerfile: *pathToDockerFile*
restart: always
environment:
- SERVER_PORT: 8080
- SOCKET_PORT: 8081
ports:
- \"8080:8080\"
- \"8081:8081\"
UPD2:最长的延迟是在首次连接期间,通常需要6秒。下一个连接也会有延迟,但最多需要 2 秒。
UPD3:而且,这个问题存在于容器内部通信中。我仅使用此应用程序进行了简单的 springBoot 集成测试-当我尝试连接并从套接字读取时-我正在接收 ReadTimeoutConnection
-
有机会从你那里看到一个简单的项目来玩吗?
-
@ArtemBilan 我将在接下来的 20 分钟内为它创建一份报告
-
@ArtemBilan 这里是一个 github 存储库 - github.com/Dexx322/sockets.demo
-
我必须在我的环境中等待 20 秒才能从 Docker 中的容器中获取
Hello client......看起来 Docker 中存在一些网络延迟,同时它试图解决它与客户端建立的套接字的问题。 -
@ArtemBilan 这很奇怪。容器内部通信也存在这个问题,我已经更新了帖子
标签: spring-boot docker-compose spring-integration telnet