MST

星途 面试题库

面试题:Go 中如何实现固定 worker 工作池的基本负载均衡

在 Go 语言里,假设要创建一个固定 worker 数量的工作池,并实现简单的负载均衡来处理任务。请描述实现思路,并给出核心代码示例,要求说明任务的分发逻辑和 worker 的工作流程。
43.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 创建任务队列:使用 Go 语言的 channel 作为任务队列,用于存储待处理的任务。
  2. 创建 worker 池:根据设定的固定 worker 数量,启动相应数量的 goroutine 作为 worker,每个 worker 从任务队列中取出任务并处理。
  3. 任务分发:将任务发送到任务队列中,由 worker 自动从队列中获取任务,实现简单的负载均衡,即哪个 worker 空闲,就从队列中取出任务进行处理。
  4. 关闭机制:提供一种机制来关闭任务队列和 worker,确保程序能优雅退出。

核心代码示例

package main

import (
    "fmt"
    "sync"
)

// Task 定义任务结构
type Task struct {
    ID int
    // 可根据实际需求添加更多任务相关字段
}

// Worker 定义 worker 结构
type Worker struct {
    ID int
    wg *sync.WaitGroup
}

// 处理任务的函数
func (w *Worker) processTask(task Task) {
    fmt.Printf("Worker %d is processing task %d\n", w.ID, task.ID)
    // 实际任务处理逻辑,这里用打印模拟
}

// 启动 worker
func (w *Worker) start(taskQueue chan Task) {
    defer w.wg.Done()
    for task := range taskQueue {
        w.processTask(task)
    }
}

func main() {
    const workerCount = 3
    const taskCount = 10

    var wg sync.WaitGroup
    taskQueue := make(chan Task)

    // 创建 worker 池
    for i := 0; i < workerCount; i++ {
        worker := Worker{
            ID: i + 1,
            wg: &wg,
        }
        wg.Add(1)
        go worker.start(taskQueue)
    }

    // 分发任务
    for i := 0; i < taskCount; i++ {
        task := Task{ID: i + 1}
        taskQueue <- task
    }

    // 关闭任务队列,通知 worker 停止
    close(taskQueue)
    // 等待所有 worker 完成任务
    wg.Wait()
}

任务分发逻辑

main 函数中,通过 for 循环将任务发送到 taskQueue 中。只要 taskQueue 有空间(没有满),任务就可以发送进去,而不用关心哪个 worker 会处理这个任务。

worker 的工作流程

  1. 每个 worker 启动一个 goroutine,调用 start 方法。
  2. start 方法通过 for... rangetaskQueue 中接收任务。
  3. 接收到任务后,调用 processTask 方法处理任务。
  4. taskQueue 关闭时,for... range 循环结束,worker 的 goroutine 也随之结束。