SwiftQ 是一个用于服务器端 Swift 应用程序的分布式任务队列。 任务队列被用作一种在机器之间分配工作负载的机制。 SwiftQ 使用消息在客户端和工作进程之间进行通信。 在这种情况下,消息代理是 Redis。 SwiftQ 使用 可靠队列模式。 这确保了即使在发生网络问题或消费者崩溃的情况下,所有任务都能得到处理。 SwiftQ 可用于实时操作以及任务的延迟执行。 SwiftQ 可以由多个生产者和消费者组成,从而实现高可用性和水平扩展。
SwiftQ 用于在通常的 HTTP 请求-响应周期之外执行任务。 示例如下:
建议使用单独的 Redis 数据库以避免冲突的命名空间。
let redisConfig = RedisConfig(redisDB: 0, hostname: "127.0.0.1", port: 6379, password: nil)
let configuration = Configuration(pollingInterval: 1000,
enableScheduling: true,
concurrency: 4,
redisConfig: .development,
tasks: [EmailTask.self])
为了便于开发,RedisConfig 具有一个静态变量 development
,它返回一个具有默认主机名和端口的 RedisConfig。 pollingInterval
是 SwiftQ 轮询计划队列的间隔(以毫秒为单位)。 可以将 enableScheduling
设置为 false,以便禁用使用者轮询计划队列。 请注意,轮询仅用于监视使用 Redis 的 Sorted Set 类型的计划队列。 对于所有其他任务,Redis 的 BRPOPLPUSH 命令用于确定何时可以执行任务。 所有任务都必须注册,SwiftQ 才能处理它们。
定义一个生产者并将任务推送到任务队列中。
let producer = try SwiftQProducer(redisConfig: .development)
let demoTask = DemoTask()
try producer.enqueue(demoTask)
创建一个消费者。 一旦消费者启动,它将开始处理任务。 必须使用要消费的任务类型初始化消费者。
let consumer = try SwiftQConsumer(configuration)
consumer.start()
请注意,单个应用程序既可以是消费者也可以是生产者,这可能使部署比拥有专用于作为消费者的机器更容易。
每个任务都必须符合 Task 协议。 storage 属性允许 SwiftQ 在您的模型上存储额外的信息,例如 id、执行尝试次数等。 任务自动符合 Codable。 如果需要提供自定义编码逻辑,请在您的任务中包含 func encode(to encoder: Encoder) throws
。
final class EmailTask: Task {
let storage: Storage
let email: String
init(email: String) {
self.storage = Storage(EmailTask.self)
self.email = email
}
func execute() throws {
}
}
调度对于发送后续电子邮件或发送提醒等事情非常方便。 任何任务都可以被调度。
try producer.enqueue(task: demo, time: .seconds(30))
此任务将在 30 秒后运行。
注意:该任务不会完全在提供的时间触发。 相反,一旦该时间过去,该任务将从计划队列移动到工作队列,并将随着工作人员空闲下来处理它而完成。
定期任务有很多用途。 例如,Web 应用程序可以每 10 分钟轮询一次 API 以收集数据。 SwiftQ 将处理调用代码以调用 API、处理结果并将结果存储在持久数据库中,以供客户端稍后使用。
final class PollTask: PeriodicTask {
let storage: Storage
let url: String
init(url: String) {
self.storage = Storage(PollTask.self)
self.url = url
}
func execute() throws {
// Make request
}
var frequency: PeriodicTime {
return .daily(minute: 30, hour: 5)
}
}
此任务将在每天凌晨 5:30 运行。 定期任务必须符合 PeriodicTask 协议。
默认情况下,所有使用者都从同一个队列中消费任务。 您可能希望指定一个自定义队列,只有某些任务被路由到该队列。 为此,只需将其添加到您的任务中
var queue: String {
return "custom"
}
您还需要在消费者配置中指定自定义队列。
注意:消费者只能从一个队列中消费。
SwiftQ 在将任务发送到代理之前将其编码为 JSON。 因此,只能支持具有本机 JSON 表示形式的类型。 支持的类型有
{
"storage" : {
"retryCount" : 0,
"taskType" : "task",
"name" : "EmailTask",
"enqueuedAt" : 1507815271,
"uuid" : "90872C7C-FCC8-4130-9872-87C619489664"
},
"email" : "example@example.com"
}
使用以下内容更新您的 Package.swift 文件
.Package(url: "https://github.com/John-Connolly/SwiftQ.git", majorVersion: 0)