Spring Boot 3启动时Logstash-logback-encoder连接超时排查
Spring Boot 3 启动初期Logstash TCP连接失败问题解决
问题背景
使用net.logstash.logback:logstash-logback-encoder:7.4的Spring Boot 3应用,启动初期会出现Logstash TCP连接拒绝的警告,后续每30秒重试可成功连接。原因是Spring Boot Docker Compose启动Logstash容器后,Logstash需等待Elasticsearch就绪才能完成初始化,而日志附加器在应用启动时就立即尝试连接。
错误日志
01:53:14,051 |-WARN in net.logstash.logback.appender.LogstashTcpSocketAppender[LOGSTASH] - Log destination localhost/<unresolved>:5000: connection failed. java.net.ConnectException: Connection refused at java.net.ConnectException: Connection refused at at java.base/sun.nio.ch.Net.pollConnect(Native Method) at at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) at at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:539) at at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:594) at at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) at at java.base/java.net.Socket.connect(Socket.java:633) at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.openSocket(AbstractLogstashTcpSocketAppender.java:765) at at net.logstash.logback.appender.AbstractLogstashTcpSocketAppender$TcpSendingEventHandler.onStart(AbstractLogstashTcpSocketAppender.java:691) at at net.logstash.logback.appender.AsyncDisruptorAppender$EventClearingEventHandler.onStart(AsyncDisruptorAppender.java:382) at at net.logstash.logback.encoder.com.lmax.disruptor.BatchEventProcessor.notifyStart(BatchEventProcessor.java:224) at at net.logstash.logback.encoder.com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:120) at at java.base/java.lang.Thread.run(Thread.java:833)
当前配置
Docker Compose配置
services: elasticsearch: image: elasticsearch:8.13.0 environment: - node.name=elasticsearch - cluster.name=es-docker-cluster - discovery.type=single-node - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - xpack.security.enabled=false volumes: - elasticsearch-data:/usr/share/elasticsearch/data ports: - "9200:9200" - "9300:9300" logstash: image: logstash:8.13.0 command: logstash -f /etc/logstash/conf.d/logstash.conf ports: - "5000:5000" # Expose the default Logstash TCP input port - "9600:9600" # Expose the Logstash monitoring port volumes: - ./logstash/config:/etc/logstash/conf.d depends_on: - elasticsearch kibana: image: kibana:8.13.0 environment: - SERVER_NAME=kibana - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 # - ELASTICSEARCH_USERNAME=kibana_system # - ELASTICSEARCH_PASSWORD=kibana_password # ${KIBANA_PASSWORD} ports: - "5601:5601" depends_on: - elasticsearch volumes: elasticsearch-data:
Logback配置(logback-spring.xml)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n</pattern> </encoder> </appender> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>localhost:5000</destination> <connectionTimeout>60 seconds</connectionTimeout> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> </appender> <root level="INFO"> <appender-ref ref="STDOUT"/> <appender-ref ref="LOGSTASH"/> </root> </configuration>
问题分析
connectionTimeout仅控制单次连接尝试的超时时间,无法解决"应用启动时Logstash未就绪"的问题。你需要调整连接重试策略,或延迟日志附加器的初始化时机,甚至让Spring Boot等待Logstash就绪后再启动。
解决方案
1. 优化Logback连接重试配置
在LogstashTcpSocketAppender中添加重试相关参数,控制首次重试延迟、最大延迟和指数退避策略,避免启动初期的频繁失败警告:
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>localhost:5000</destination> <connectionTimeout>60 seconds</connectionTimeout> <!-- 首次重试延迟 --> <reconnectionDelay>5 seconds</reconnectionDelay> <!-- 最大重试延迟,避免延迟无限增长 --> <maxReconnectionDelay>30 seconds</maxReconnectionDelay> <!-- 重试延迟倍数,实现指数退避 --> <reconnectionDelayMultiplier>1.5</reconnectionDelayMultiplier> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> </appender>
2. 启用延迟初始化(推荐)
让日志附加器延迟到第一次发送日志时才尝试连接,而不是应用启动时立即初始化。添加<lazyInit>true</lazyInit>:
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>localhost:5000</destination> <lazyInit>true</lazyInit> <connectionTimeout>60 seconds</connectionTimeout> <reconnectionDelay>5 seconds</reconnectionDelay> <maxReconnectionDelay>30 seconds</maxReconnectionDelay> <reconnectionDelayMultiplier>1.5</reconnectionDelayMultiplier> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> </appender>
3. 让Spring Boot等待Logstash就绪(彻底解决初期连接问题)
给Logstash添加健康检查,确保Spring Boot只有在Logstash真正就绪后才启动:
修改Docker Compose的logstash服务
logstash: image: logstash:8.13.0 command: logstash -f /etc/logstash/conf.d/logstash.conf ports: - "5000:5000" - "9600:9600" volumes: - ./logstash/config:/etc/logstash/conf.d depends_on: - elasticsearch # 添加健康检查 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9600/_node/plugins"] interval: 10s timeout: 5s retries: 5
在Spring Boot配置文件中添加等待策略
在application.properties或application.yml中配置:
# 等待logstash服务就绪后再启动应用 spring.docker.compose.wait.services=logstash spring.docker.compose.wait.strategy=health-check
总结
connectionTimeout不是解决启动初期连接失败的关键,需要配置重试策略和延迟初始化- 若要彻底避免连接失败警告,推荐结合Docker健康检查和Spring Boot的容器等待策略
内容的提问来源于stack exchange,提问作者JustAnotherDev
相关产品推荐
相关产品推荐

