MST

星途 面试题库

面试题:Go语言Context包在复杂并发场景中的使用

假设你正在开发一个微服务系统,其中涉及多个服务之间的链式调用,每个服务又有多个子任务并发执行。在这个场景下,如何合理地传递和管理Context,以确保当客户端取消请求或者整个调用链超时时,所有相关的并发任务都能被正确取消?请详细阐述设计思路并给出关键代码片段。
45.7万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 全局Context传递:在整个微服务链式调用的入口处创建一个 Context,并将其传递给每一个下游服务。这个 Context 可以是 WithCancelWithTimeout 或者 WithDeadline 创建的,以便实现取消或超时功能。
  2. 子任务并发管理:对于每个服务内的多个并发子任务,将接收到的 Context 传递给每个子任务。每个子任务在执行过程中,需要定期检查 Context 的状态,一旦发现 Context 被取消或超时,立即停止执行。
  3. 传播取消信号:当某个服务接收到取消信号(通过 Context),它不仅要停止自身的子任务,还要将取消信号传递给下游服务,以确保整个调用链的一致性取消。

关键代码片段(以Go语言为例)

创建和传递Context

package main

import (
    "context"
    "fmt"
    "time"
)

// 模拟下游服务
func downstreamService(ctx context.Context) error {
    select {
    case <-ctx.Done():
        return ctx.Err()
    case <-time.After(2 * time.Second):
        fmt.Println("Downstream service completed")
        return nil
    }
}

// 模拟上游服务,包含并发子任务
func upstreamService(ctx context.Context) error {
    var errChan = make(chan error, 2)

    // 子任务1
    go func() {
        select {
        case <-ctx.Done():
            errChan <- ctx.Err()
            return
        case <-time.After(3 * time.Second):
            fmt.Println("Sub - task 1 completed")
            errChan <- nil
        }
    }()

    // 子任务2
    go func() {
        select {
        case <-ctx.Done():
            errChan <- ctx.Err()
            return
        case <-time.After(1 * time.Second):
            fmt.Println("Sub - task 2 completed")
            errChan <- nil
        }
    }()

    for i := 0; i < 2; i++ {
        err := <-errChan
        if err != nil {
            return err
        }
    }

    // 调用下游服务
    return downstreamService(ctx)
}

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    err := upstreamService(ctx)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

在上述代码中:

  1. main 函数创建了一个带超时的 Context 并传递给 upstreamService
  2. upstreamService 内部启动了两个并发子任务,每个子任务都监听 Context 的取消信号。同时,upstreamService 还调用了下游服务 downstreamService 并传递 Context
  3. downstreamService 同样监听 Context 的取消信号,以确保在超时或取消时能够正确响应。