Golang Go语言 master-worker 模式,有不懂的地方,求解答
Golang Go语言 master-worker 模式,有不懂的地方,求解答
package main
import (
“fmt”
“math/rand”
“strconv”
“time”
)
type Payload struct {
name string
}
//任务
type Job struct {
Payload Payload
}
//任务队列
var JobQueue chan Job
// 执行者 消费者 工人
type Worker struct {
WorkerPool chan chan Job //对象池
JobChannel chan Job //通道里面拿
quit chan bool //
name string //工人的名字
}
// 调度器
type Dispatcher struct {
name string //调度的名字
maxWorkers int //获取 调试的大小
WorkerPool chan chan Job //注册和工人一样的通道
}
//打游戏
func (p *Payload) Play() {
fmt.Printf("%s 打 LOL 游戏…当前任务完成\n", p.name)
}
// 新建一个工人
func NewWorker(workerPool chan chan Job, name string) Worker {
fmt.Printf(“创建了一个工人,它的名字是:%s \n”, name)
//workerPool 确定 woker 的容量
return Worker{
name: name,
WorkerPool: workerPool,
JobChannel: make(chan Job),
quit: make(chan bool),
}
}
// 工人开始工作
func (w *Worker) Start() {
//开一个新的协程
go func() {
for {
//注册到对象池中,
w.WorkerPool <- w.JobChannel
fmt.Printf("[%s]把自己注册到 对象池中 \n", w.name)
select {
//接收到了新的任务
case job := <-w.JobChannel:
fmt.Printf("[%s] 工人接收到了任务 当前任务的长度是[%d]\n", w.name, len(w.WorkerPool))
job.Payload.Play()
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)
//接收到了任务
case <-w.quit:
fmt.Println(“结束任务”, w.name)
return
}
}
}()
}
func (w Worker) Stop() {
go func() {
w.quit <- true
}()
}
func NewDispatcher(maxWorkers int) *Dispatcher {
//容量为{maxWorkers}的 channel
pool := make(chan chan Job, maxWorkers)
return &Dispatcher{
WorkerPool: pool, // 将工人放到一个池中,可以理解成一个部门中
name: “调度者”, //调度者的名字
maxWorkers: maxWorkers, //这个调度者有好多个工人
}
}
func (d *Dispatcher) Run() {
// 开始运行
for i := 0; i < d.maxWorkers; i++ {
worker := NewWorker(d.WorkerPool, fmt.Sprintf(“work-%s”, strconv.Itoa(i)))
//开始工作
worker.Start()
}
//监控
go d.dispatch()
}
func (d *Dispatcher) dispatch() {
for {
select {
case job := <-JobQueue:
fmt.Println(“调度者,接收到一个工作任务”)
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)
// 调度者接收到一个工作任务
go func(job Job) {
//从现有的对象池中拿出一个
jobChannel := <-d.WorkerPool
fmt.Println(jobChannel)
fmt.Println(job)
jobChannel <- job
}(job)
default:
//fmt.Println("ok!!")
}
}
}
func initialize() {
maxWorkers := 1
maxQueue := 20
//初始化一个调试者,并指定它可以操作的 工人个数
dispatch := NewDispatcher(maxWorkers)
JobQueue = make(chan Job, maxQueue) //指定任务的队列长度
//并让它一直接运行
dispatch.Run()
}
func main() {
//初始化对象池
initialize()
for i := 0; i < 1; i++ {
p := Payload{
fmt.Sprintf(“玩家-[%s]”, strconv.Itoa(i)),
}
JobQueue <- Job{
Payload: p,
}
time.Sleep(time.Second)
}
close(JobQueue)
}
不懂的地方如下:
// w.WorkerPool <- w.JobChannel 这个流向不了解, 为什么下面的 select job := <-w.JobChannel: 还可以获得 channel 数据
func (w *Worker) Start() {
go func() {
for {
w.WorkerPool <- w.JobChannel
fmt.Printf("[%s]把自己注册到 对象池中 \n", w.name)
select {
//接收到了新的任务
case job := <-w.JobChannel:
fmt.Printf("[%s] 工人接收到了任务 当前任务的长度是[%d]\n", w.name, len(w.WorkerPool))
job.Payload.Play()
time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond)
//接收到了任务
case <-w.quit:
fmt.Println(“结束任务”, w.name)
return
}
}
}()
}
// dispatch
go func(job Job) {
//从现有的对象池中拿出一个
jobChannel := <-d.WorkerPool
fmt.Println(jobChannel)
fmt.Println(job)
jobChannel <- job //job 留向 jobChannel ??? 不懂
}(job)
大佬们帮忙帮忙!
更多关于Golang Go语言 master-worker 模式,有不懂的地方,求解答的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你仔细看下 WorkerPool,JobChannel 的 类型 , 仔细看。
更多关于Golang Go语言 master-worker 模式,有不懂的地方,求解答的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
WorkerPool 通道的通道,JobChannel 通道, <br>w.WorkerPool <- w.JobChannel 从 JobChannel 流向了 WorkerPool,<br><br>初始化的时候 JobChannel 是 nil 怎么流向 WorkerPool, 注册到对象池的呢?<br><br>
我好像明白了
jobChannel := <-d.WorkerPool
jobChannel <- job //其实是 w.JobChannel <- job
所以
select {
//会接受到新流入的 channel
case job := <-w.JobChannel:
感谢感谢!
关于Golang中master-worker模式的疑问,以下是一些专业解答:
Master-worker模式是常用的并行计算模式,其核心思想是系统由两类进程协作工作:Master进程和Worker进程。Master进程负责接收和分配任务,而Worker进程则负责处理子任务。当Worker进程处理完子任务后,会将结果返回给Master进程,由Master进程进行归纳和总结。
在Golang中实现master-worker模式,通常需要定义Master和Worker结构体,并实现相应的方法。Master结构体需要维护任务队列、Worker进程队列和子任务结果集,而Worker结构体则需要实现任务处理逻辑。
在实现过程中,需要注意以下几点:
- 任务划分:Master进程需要根据任务需求,合理地将任务划分为多个子任务。
- 任务分配:Master进程需要将子任务分配给各个Worker进程,并确保负载均衡,避免某些Worker进程过载而其他Worker进程空闲。
- 结果汇总:Worker进程处理完子任务后,需要将结果发送回Master进程。Master进程需要对这些结果进行归纳和总结,以得出最终的任务结果。
此外,在实现master-worker模式时,还需要考虑容错处理、通信优化和资源监控与调度等方面的问题,以确保系统的稳定性和高效性。