我很高兴宣布Swift服务器生态系统的一个新的开源项目--Swift Service Lifecycle。服务生命周期是一个 Swift 包,旨在帮助服务器应用程序(也称为服务)管理其启动和关闭顺序。
它是什么?
大多数服务都有启动和关闭的工作流程逻辑,这往往对失败很敏感,而且很难做到正确。启动序列包括初始化线程池、运行数据迁移、预热缓存,以及其他形式的状态初始化,然后再接受流量或接受事件。关机序列包括释放那些持有文件描述符的资源或其他系统资源,如果不正确清除,这些资源可能会泄漏。
今天,服务器应用程序和框架必须自己想办法解决这个需求,这可能是容易出错的。为了使事情变得更安全、更容易,服务生命周期以一种安全、可重用和与框架无关的方式编纂了这种常见的需求。它被设计成可以与任何服务器框架集成,或直接在服务器应用程序的main 。
它是如何工作的?
使用这个库的推荐方式是在你的服务器应用程序的main 中创建一个ServiceLifecycle 实例,并在其中注册LifecycleTasks 。在调用start 函数时,ServiceLifecycle 将按照注册的顺序启动这些任务。
默认情况下,ServiceLifecycle 也注册了一个Signal 处理程序,它可以捕获INT 和TERM ,它们是现代部署平台中用于通信关闭请求的典型Signal。一旦捕捉到Signal ,关机顺序就开始了,而LifecycleTasks 则按照它们被注册的相反顺序被关闭。
例子
// Import the package.
import Lifecycle
// Initialize the `Lifecycle` container.
var lifecycle = ServiceLifecycle()
// Register a resource that should be shut down when the application exits.
//
// In this case, we are registering a SwiftNIO `EventLoopGroup`
// and passing its `syncShutdownGracefully` function to be called on shutdown.
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
lifecycle.registerShutdown(
name: "eventLoopGroup",
.sync(eventLoopGroup.syncShutdownGracefully)
)
// Register another resource that should be started when the application starts
// and shut down when the application exits.
//
// In this case, we are registering a contrived `DatabaseMigrator`
// and passing its `migrate` function to be called on startup
// and `shutdown` function to be called on shutdown.
let migrator = DatabaseMigrator(eventLoopGroup: eventLoopGroup)
lifecycle.register(
name: "migrator",
start: .async(migrator.migrate),
shutdown: .async(migrator.shutdown)
)
// Start the application.
//
// Start handlers passed using the `register` function
// will be called in the order they were registered in.
lifecycle.start() { error in
// start completion handler
// if an startup error occurred you can capture it here
if let error = error {
logger.error("failed starting \(self) ☠️: \(error)")
} else {
logger.info("\(self) started successfully 🚀")
}
}
// Wait for the application to exit
//
// This is a blocking operation that typically waits for a `Signal`.
// The `Signal` can be configured at `lifecycle.init`, and defaults to `INT` and `TERM`.
// Shutdown handlers passed using the `register` or `registerShutdown` functions
// will be called in the reverse order they were registered in.
lifecycle.wait()