- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在这里已经得到了一些帮助,这让我在我正在尝试的这个概念上取得了进展,但它仍然不太奏效,我遇到了一个我似乎无法解决的冲突。
我在这里尝试在流程图中说明我想要的内容 - 请注意,客户端可以是许多将发送 printjobs 的客户端,因此我们无法回复工作人员当时正在处理我们的工作,但对于大多数会的(高峰期不会,因为打印处理工作需要时间)。
type QueueElement struct {
jobid string
rw http.ResponseWriter
doneChan chan struct{}
}
type GlobalVars struct {
db *sql.DB
wg sync.WaitGroup
jobs chan QueueElement
}
func (gv *GlobalVars) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/StartJob":
fmt.Printf ("incoming\r\n")
doneC := make(chan struct{}, 1) //Buffered channel in order not to block the worker routine
newPrintJob := QueueElement{
doneChan: doneC,
jobid: "jobid",
}
gv.jobs <- newPrintJob
func(doneChan chan struct{},w http.ResponseWriter) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
select {
//If this triggers first, then this waiting goroutine would exit
//and nobody would be listeding the 'doneChan'. This is why it has to be buffered.
case <-ctx.Done():
fmt.Fprintf(w, "job is taking more than 5 seconds to complete\r\n")
fmt.Printf ("took longer than 5 secs\r\n")
case <-doneChan:
fmt.Fprintf(w, "instant reply from serveHTTP\r\n")
fmt.Printf ("instant\r\n")
}
}(doneC,w)
default:
fmt.Fprintf(w, "No such Api")
}
}
func worker(jobs <-chan QueueElement) {
for {
job := <-jobs
processExec ("START /i /b try.cmd")
fmt.Printf ("job done")
// processExec("START /i /b processAndPrint.exe -" + job.jobid)
job.doneChan <- struct{}{}
}
}
func main() {
db, err := sql.Open("sqlite3", "jobs.sqlite")
if err := db.Ping(); err != nil {
log.Fatal(err)
}
db.SetMaxOpenConns(1) // prevents locked database error
_, err = db.Exec(setupSQL)
if err != nil {
log.Fatal(err)
}
// create a GlobalVars instance
gv := GlobalVars{
db : db,
jobs: make(chan QueueElement),
}
go worker (gv.jobs)
// create an http.Server instance and specify our job manager as
// the handler for requests.
server := http.Server{
Handler: &gv,
Addr : ":8888",
}
// start server and accept connections.
log.Fatal(server.ListenAndServe())
}
上面的代码是 serveHTTP 和 worker 在此处帮助下的代码,最初 ServeHTTP 中的 func 是一个 go 例程,在这里对我来说整个冲突都出现了 - 这个概念是在 serveHTTP 中它产生了一个进程如果 worker 能够在 5 秒内及时处理作业,将会得到 worker 的回复。
如果工作能够在 1 秒内完成,我想在 1 秒后立即回复客户,如果需要 3 秒我想在 3 秒后回复,如果超过 5 秒我会发回回复5 秒后(如果工作需要 13 秒,我仍然想在 5 秒后回复)。从现在开始,客户端必须对作业进行轮询 - 但冲突是:
a) 当 ServeHTTP 退出时 - 然后 ResponseWriter 关闭 - 为了能够回复客户端,我们必须将答案写入 ResponseWriter。
b) 如果我阻止 serveHTTP(就像在下面的代码示例中,我没有将 func 称为 go 例程)那么它不仅会影响单个 API 调用,而且似乎会影响之后的所有其他调用,因此第一个调用将被及时正确服务,但在第一个调用之后同时进入的调用将被阻塞操作顺序延迟。
c) 如果我不阻止它 ex - 并将其更改为 go routine :
gv.jobs <- newPrintJob
go func(doneChan chan struct{},w http.ResponseWriter) {
然后没有延迟 - 可以调用许多 API - 但问题是 serveHTTP 立即存在并因此杀死 ResponseWriter 然后我无法回复客户端。
我不确定如何解决这个冲突,因为我不会对 serveHTTP 造成任何阻塞,所以我可以并行处理所有请求,但仍然能够回复有问题的 ResponseWriter。
有什么方法可以防止 serveHTTP 在函数退出时关闭响应编写器?
最佳答案
是的,您的观点是正确的“c) 如果我不阻止它 ex”。
为了保存响应编写器,您不应该在其中调用 go routine。相反,您应该将 ServeHTTP 作为 go-routine 调用,大多数 http 服务器实现都这样做。
这样您就不会阻止任何 api 调用,每个 api 调用将在不同的 go-routine 中运行,并被它们的功能阻止。
由于您的"jobs chan QueueElement" 是单个 channel (不是缓冲 channel ),因此您的所有进程都在"gv.jobs <- newPrintJob" 处被阻塞.
您应该使用缓冲 channel ,以便所有 api 调用都可以将其添加到队列中并根据工作完成或超时获得响应。
拥有缓冲 channel 也可以模拟打印机在现实世界中的内存限制。 (队列长度为 1 为特例)
关于go - 后台打印程序概念/API 和 channel : issue passing jobs to a queue from serveHTTP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56405281/
我想做的是分派(dispatch)一个 Job,然后在前一个 Job 完成后继续分派(dispatch)同一个 Job,这样就可以连续循环分派(dispatch) Job。如选项一所示,这以前是与数据
我想知道当一个过程通过一个作业执行时会发生什么,在它完成之前是作业调用该过程的下一次执行的时间。这是我创建的工作: DECLARE X NUMBER; BEGIN SYS.DB
我使用以下代码显示超时为 120 秒的 PowerShell 作业的结果。我想通过合并 Write-Progress(基于完成的作业数)来增强此代码。我尝试使用 this example然而,作为引用
我使用以下代码显示超时为 120 秒的 PowerShell 作业的结果。我想通过合并 Write-Progress(基于完成的作业数)来增强此代码。我尝试使用 this example然而,作为引用
这个关于 ECMAScript 规范(ECMA-262 第 8 版)的问题 这些天,我对作业和作业队列有点困惑。 这里有一些问题。 1:在ECMA-262中,有两种作业队列。一个是 ScriptJob
子进程是作业的一部分,由创建作业的进程启动。父进程尚未设置作业属性以允许脱离作业。需要在 JOB 上设置“JOB_OBJECT_LIMIT_BREAKAWAY_OK”标志以允许子进程脱离作业,但未设置
有没有人有类似于Path's Android Priority Job Queue的iOS作业队列?他们不介意与社区分享?我是 iOS 的新手,所以我不确定平台本身是否提供这样的解决方案。在 Andr
我正在关注 this在 Heroku 上安排我的 Django cron 作业。 程序文件: web: gunicorn tango.wsgi --log-file - clock: python c
UI协同程序指南包含有关如何管理UI协同程序生命周期的section。它说明了我们应该创建一个顶级Job实例,并将复合协程上下文contextJob + UI传递给我们启动的所有协程: launch(
我在 Spark 上创建了一个 Master 和一个 Worker。然后我创建了一个 Spark 流作业并尝试提交它,但在 Master 上它显示了一长串 java 错误 使用此命令启动主控: spa
我必须在 Spring Batch 上设置 jobparemeters,但使用 Spring Boot Batch 则无法轻松做到这一点。 我需要重新运行作业,但如果参数相同,spring-batch
众所周知,Apache Pig 是一种数据流语言。如果我编写了一个 Pig 脚本并且 Pig 决定拆分并运行两个或多个作业来执行手头的任务,那么 Pig 如何存储它从作业 1 传递到作业 2 的数据?
我以为他们指的是 Reducer 但在我的程序中我有 public static class MyMapper extends Mapper 和 public static class MyReduc
我需要创建一个恢复模式。 在我的模式中,我只能在给定的时间窗口内启 Action 业。 如果作业失败,它只会在下一个时间窗口重新启动,完成后我想开始为此窗口提前计划的计划作业。 作业之间的唯一区别是时
使用 play 框架 1.2.4 和 scala。我几乎没有类似的游戏工作 @OnApplicationStart class MyOtherJob extends Job { ... } @Ev
作业通知选项“作业成功时”和“作业完成时”有何区别。从表面上看,我假设“作业完成时”选项包含作业成功和作业失败,而“作业成功时”选项仅包含作业成功运行时。这是正确的吗? 最佳答案 作业成功时作业成功完
我正在尝试创建迁移,但由于以下错误而失败: Error from server (BadRequest): error when creating "kubernetes/migration-job.
Cron Job 和 hybris 中的 Job 有什么区别? 两者的创建/实现之间有什么区别? 最佳答案 下图描述了 Hybris 中 Jobs/Cronjobs 工作原理的完整 View
我正在运行多个作业,并且我希望每个作业都有一个单独的作业存储库(内存中实现)。 请在下面找到我尝试过的 bean 定义。请注意,我尝试指定具有作用域原型(prototype)的 bean。 我收到 j
Quartz 中是否有一种机制可以在启动另一个作业时删除现有作业?我需要暂停其他作业的原因是因为新作业需要所有资源可用,只有当其他作业未运行时才会如此。 这是一个示例: 我有 2 份工作:工作 A 和
我是一名优秀的程序员,十分优秀!