MST

星途 面试题库

面试题:Go 扇入扇出模式扩展性中的资源管理

在使用 Go 扇入扇出模式构建高扩展性系统时,资源管理是关键。例如,在大量扇出任务场景下,可能会产生许多 goroutine,容易导致资源耗尽。请说明如何通过有效的资源管理策略(如限制 goroutine 数量)来保证系统的扩展性和稳定性,并给出具体的 Go 代码示例,展示如何使用 semaphore 来限制扇出的 goroutine 数量。
27.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 资源管理策略
    • 限制goroutine数量:通过信号量(semaphore)机制来限制同时运行的goroutine数量。信号量可以看作是一个计数器,它记录了当前可用的资源数量(在这里就是允许同时运行的goroutine数量)。当一个goroutine想要开始执行时,它需要先获取信号量(将计数器减1),如果计数器为0,则表示资源已被占用,该goroutine需要等待。当goroutine执行完毕后,它会释放信号量(将计数器加1),这样其他等待的goroutine就有机会获取信号量并开始执行。
    • 资源清理:在goroutine内部,要确保及时清理不再使用的资源,如关闭文件描述符、数据库连接等,避免资源泄漏。
  2. Go代码示例
package main

import (
    "fmt"
    "sync"
)

// Semaphore结构体表示信号量
type Semaphore struct {
    tokens chan struct{}
}

// NewSemaphore创建一个指定数量令牌的信号量
func NewSemaphore(n int) *Semaphore {
    return &Semaphore{
        tokens: make(chan struct{}, n),
    }
}

// Acquire获取一个信号量令牌,如果没有可用令牌则阻塞
func (s *Semaphore) Acquire() {
    s.tokens <- struct{}{}
}

// Release释放一个信号量令牌
func (s *Semaphore) Release() {
    <-s.tokens
}

func main() {
    // 创建一个最多允许3个goroutine同时运行的信号量
    sem := NewSemaphore(3)
    var wg sync.WaitGroup

    // 模拟10个扇出任务
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            sem.Acquire()
            defer sem.Release()
            // 模拟任务执行
            fmt.Printf("Goroutine %d is running\n", id)
        }(i)
    }

    wg.Wait()
    fmt.Println("All goroutines have finished")
}

在上述代码中:

  • Semaphore结构体包含一个tokens通道,用于表示可用的信号量令牌。
  • NewSemaphore函数创建一个指定数量令牌的信号量。
  • Acquire方法获取一个信号量令牌,如果没有可用令牌则阻塞。
  • Release方法释放一个信号量令牌。
  • main函数中,创建了一个最多允许3个goroutine同时运行的信号量,并启动10个goroutine,每个goroutine在执行前先获取信号量,执行完毕后释放信号量,以此来限制同时运行的goroutine数量。