ITPub博客

首页 > > > Golang中的自动伸缩和自防御设计-2

Golang中的自动伸缩和自防御设计-2

作者:zhmw 时间:2019-12-24 10:08:49 0 删除 编辑

Golang进程间通信(Inter process communication)

如上所述,检测一个Worker进程是否有响应,简单方法是由每个Worker报告上一次完成作业的时间。如果Master进程发现某个Worker时间周期太长,则可以认为它没有响应,并将其替换为新的Worker。要实现这一点,Worker进程需要以某种方式与Master进程通信,以便在它完成任务时保存并通知Master当前时间。实现这一点的方式有很多:

读取和写入文件

设置本地队列系统,如Redis或RabbitMQ

使用Golang rpc包

通过本地网络连接传输数据

利用共享内存

设置命名管道(named pipes)

在我们的例子中,所传输的只是时间戳,而不是重要的客户数据,因此上述这些方式大多数都有些杀鸡用牛刀了。因此最终采取了简单的解决方案——通过Worker进程的标准输出管道进行通信。

通过exec.Command启动新进程后,进程的标准输出管道可通过如下方式得到:

stdoutPipe, err:=cmd.StdoutPipe()

 

一旦有了标准的输出管道,就可以运行goroutine并发地监听它。在goroutine中,可以使用扫描器从管道读取数据,如下所示。在Worker进程将数据写入标准输出管道时,将执行scanner.Text()并调用之后的业务代码。

scanner:=bufio.NewScanner(stdoutPipe)

forscanner.Scan() {

line:=scanner.Text()

// 此处可处理读取到的具体业务数据

}

 

无响应监测(Unresponsivenessdetection)

现在进程间通信已经就绪,可以使用它来实现对无响应的Worker进程进行检测。更新现有的Worker逻辑,使之在完成工作时使用Golang fmt包打印出当前时间。而时间戳将被扫描器捕获,并使用与打印时相同的格式解析时间。然后将time对象设置到相关Worker对象的LastJob字段中用于跟踪。

t, err:=time.Parse(time.RFC3339, line)

iferr!=nil {

// 此处为错误异常处理逻辑

} else {

worker.LastJob = t

}

 

回到定时扫描包含Worker进程的Map的goroutine程序中,现在可以比较每个Worker的当前时间和上一个作业时间。如果这个时间间隔太长,则终止该进程并重新启动新的Worker进程。

funcCheckWorker(procs*map[int]*Worker, worker*Worker, indexint) {

// 如果Worker进程响应时间间隔太长,则终止并重启新的进程

duration:=time.Now().Sub(worker.LastJob)

ifduration.Minutes() > 4 {

KillWorker(procs, index)

StartWorker(procs, index)

}

}

 

可以通过调用进程对象的Kill函数来杀死进程。这是由生成进程时获得的Command对象提供的。另一件需要做的事是从映射的Map中删除Worker对象。在终止异常的Worker之后,可以通过调用StartWorker函数来启动一个新的Worker。新Worker在映射的Map中使用的key与被终止的Worker进程相同——从而完成了Worker的替换逻辑。

funcKillWorker(procs*map[int]*Worker, indexint) {

worker:= (*procs)[index]

ifworker!=nil {

process:=worker.Command.Process

delete(*procs, index) // 从Map中删除无效Worker进程

err:=process.Kill() // 终止进程

iferr!=nil {

// 错误及异常处理

}

}

}

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69901620/viewspace-3157866/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-12-04

  • 博文量
    295
  • 访问量
    9529