面试题答案
一键面试简单并发负载均衡
- 原理:通过
goroutine
来并行处理任务,channel
用于在不同goroutine
之间传递任务和结果。主goroutine
将任务发送到任务channel
,多个工作goroutine
从任务channel
中接收任务并处理,处理结果通过结果channel
返回。 - 代码示例:
package main
import (
"fmt"
)
func worker(id int, tasks <-chan int, results chan<- int) {
for task := range tasks {
fmt.Printf("Worker %d started task %d\n", id, task)
result := task * task
fmt.Printf("Worker %d finished task %d with result %d\n", id, task, result)
results <- result
}
}
func main() {
const numWorkers = 3
const numTasks = 5
tasks := make(chan int, numTasks)
results := make(chan int, numTasks)
// 启动工作goroutine
for i := 0; i < numWorkers; i++ {
go worker(i, tasks, results)
}
// 发送任务
for i := 0; i < numTasks; i++ {
tasks <- i
}
close(tasks)
// 收集结果
for i := 0; i < numTasks; i++ {
fmt.Printf("Result: %d\n", <-results)
}
close(results)
}
扩展到并行负载均衡
- 原理:并行负载均衡意味着在不同的计算资源(如多核CPU)上并行执行任务。Go语言的运行时系统会自动将
goroutine
调度到多个操作系统线程上,充分利用多核资源。为了更好地利用多核,可以适当增加工作goroutine
的数量,并且合理分配任务,避免某个goroutine
负载过重。 - 代码示例调整:
package main
import (
"fmt"
"runtime"
)
func worker(id int, tasks <-chan int, results chan<- int) {
for task := range tasks {
fmt.Printf("Worker %d started task %d\n", id, task)
result := task * task
fmt.Printf("Worker %d finished task %d with result %d\n", id, task, result)
results <- result
}
}
func main() {
// 设置最大的CPU核数使用数
runtime.GOMAXPROCS(runtime.NumCPU())
const numWorkers = runtime.NumCPU() * 2
const numTasks = 10
tasks := make(chan int, numTasks)
results := make(chan int, numTasks)
// 启动工作goroutine
for i := 0; i < numWorkers; i++ {
go worker(i, tasks, results)
}
// 发送任务
for i := 0; i < numTasks; i++ {
tasks <- i
}
close(tasks)
// 收集结果
for i := 0; i < numTasks; i++ {
fmt.Printf("Result: %d\n", <-results)
}
close(results)
}
在上述代码中,通过runtime.GOMAXPROCS(runtime.NumCPU())
设置Go运行时使用的最大CPU核数,numWorkers
设置为CPU核数的两倍,以更好地利用多核资源进行并行处理。这样在多核CPU环境下,任务可以并行执行,实现并行负载均衡。