You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级sbt至1.5.8以上版本后AkkaHttpServer启动即停止问题

问题:sbt升级至1.6.X及以上版本后,Akka HTTP服务器启动即停止

现象

原本稳定运行的Akka HTTP应用,在将sbt从1.5.8升级到1.6.X、1.7.X、1.8.X或1.9.0版本后,出现以下问题:

  • 在sbt交互模式执行run命令,命令会直接退出回到sbt提示符
  • 执行sbt run命令,sbt会直接退出,服务器无法保持运行

sbt 1.6+版本运行日志

sbt:project> run
[info] running com.------.Application 
12:47:27.125 [Server-akka.actor.default-dispatcher-3] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
SLF4J: A number (1) of logging calls during the initialization phase have been intercepted and are
SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system.
SLF4J: See also https://www.slf4j.org/codes.html#replay
12:47:27.842 [Server-akka.actor.default-dispatcher-3] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
[success] Total time: 3 s, completed 22 Jun 2023, 12:47:28
12:47:28.241 [Server-akka.actor.default-dispatcher-3] INFO  akka.actor.typed.ActorSystem - Server online at http://0.0.0.0:8080/ for docker or http://127.0.0.1:8080
sbt:project> 

sbt 1.5.8版本运行日志

sbt:project> run
[info] running com.-------.Application 
13:13:13.093 [Server-akka.actor.default-dispatcher-3] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
SLF4J: A number (1) of logging calls during the initialization phase have been intercepted and are
SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system.
SLF4J: See also https://www.slf4j.org/codes.html#replay
13:13:13.481 [Server-akka.actor.default-dispatcher-3] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
13:13:13.730 [Server-akka.actor.default-dispatcher-3] INFO  akka.actor.typed.ActorSystem - Server online at http://0.0.0.0:8080/ for docker or http://127.0.0.1:8080

使用的依赖版本:

val AkkaVersion = "2.6.20" //apache 2.0 license
val AkkaHttpVersion = "10.2.10" //apache 2.0 license

原因分析

sbt 1.6.0及以上版本对run任务的默认行为做了调整:

  • 未启用fork模式时,sbt会在主线程执行完App trait的代码后立即标记任务完成并退出,不会等待Akka后台的ActorSystem线程。
  • 从日志可见,sbt先输出[success],之后Akka才输出服务器上线日志,说明主线程已结束,sbt直接终止了整个进程。
  • 而sbt 1.5.8版本中,主线程会被Akka的线程持有,保持进程持续运行。

解决方案

方案1:修改sbt的fork配置

在build.sbt中添加以下配置,启用fork模式并保持输入连接,让sbt等待子进程结束:

run / fork := true
run / connectInput := true

启用fork后,Akka服务器会在独立子进程中运行,sbt会一直等待子进程终止,直到你手动停止服务器。

方案2:修改应用代码,让主线程等待ActorSystem终止

在应用入口类中添加代码,让主线程阻塞等待ActorSystem终止,避免主线程提前结束:

import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import scala.concurrent.Await
import scala.concurrent.duration.Duration

object Application extends App {
  // 初始化ActorSystem
  val system = ActorSystem(Behaviors.setup { context =>
    // 这里添加Akka HTTP服务器的启动逻辑
    // ...
    
    Behaviors.empty
  }, "Server")

  // 阻塞主线程,等待ActorSystem终止
  Await.result(system.whenTerminated, Duration.Inf)
}

也可以使用非阻塞方式监听终止事件:

import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import scala.concurrent.ExecutionContext.Implicits.global

object Application extends App {
  val system = ActorSystem(Behaviors.setup { context =>
    // 启动Akka HTTP服务器逻辑
    // ...
    
    Behaviors.empty
  }, "Server")

  // 监听ActorSystem终止事件,终止时退出JVM
  system.whenTerminated.onComplete(_ => System.exit(0))
}

这两种方案都能让sbt的run任务保持运行,直到服务器被手动停止。


内容的提问来源于stack exchange,提问作者Roman Kazanovskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:15:41