Go语言并发模型与模式:Fan-out / Fan-in 模式

在并发系统中,Fan-out / Fan-in 模式是一种经典的设计方式,用于在多个 goroutine 之间进行任务分发和结果聚合,常用于提高处理吞吐量和并发能力。


一、什么是 Fan-out / Fan-in 模式?

  • Fan-out(扇出) :将任务从一个入口分发给多个 worker 并发执行。
  • Fan-in(扇入) :将多个 worker 的结果汇聚到一个通道中进行统一处理。

这种模式适用于"多产一收"的数据处理流程,如数据抓取、批量计算等。


二、基本结构图

csharp 复制代码
     ┌────────────┐
     │ 任务生产者 │
     └────┬───────┘
          │
      Fan-out
  ┌──────┴──────┐
  ▼      ▼      ▼
Worker Worker Worker
  │      │      │
  └──────┬──────┘
       Fan-in
         │
   ┌─────▼─────┐
   │ 结果处理器 │
   └───────────┘

三、代码示例

go 复制代码
package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func producer(count int) <-chan int {
    out := make(chan int)
    go func() {
        for i := 0; i < count; i++ {
            out <- i
        }
        close(out)
    }()
    return out
}

func worker(id int, in <-chan int) <-chan int {
    out := make(chan int)
    go func() {
        for job := range in {
            time.Sleep(time.Millisecond * time.Duration(rand.Intn(500))) // 模拟处理
            fmt.Printf("Worker %d processed job %d\n", id, job)
            out <- job * 2
        }
        close(out)
    }()
    return out
}

func merge(channels ...<-chan int) <-chan int {
    var wg sync.WaitGroup
    out := make(chan int)

    output := func(c <-chan int) {
        for val := range c {
            out <- val
        }
        wg.Done()
    }

    wg.Add(len(channels))
    for _, c := range channels {
        go output(c)
    }

    go func() {
        wg.Wait()
        close(out)
    }()
    return out
}

func main() {
    rand.Seed(time.Now().UnixNano())
    input := producer(10)

    // Fan-out:启动3个worker处理任务
    w1 := worker(1, input)
    w2 := worker(2, input)
    w3 := worker(3, input)

    // Fan-in:合并3个worker输出
    result := merge(w1, w2, w3)

    for res := range result {
        fmt.Println("结果:", res)
    }
}

四、应用场景

Fan-out / Fan-in 非常适合如下场景:

应用场景 示例
并发抓取网页 多个 URL 同时请求并聚合结果
批量图像处理 多图片缩放或加水印
数据清洗与计算 并发处理 CSV/日志数据
大量任务排队处理 多任务分发并收集结果

五、注意事项

✅ 优点:

  • • 利用多核并发,显著提高处理效率;
  • • 模块清晰,生产者-工作者-聚合器分离;
  • • 易于扩展和监控。

⚠️ 注意事项:

  • • 输入通道必须是"广播型",即可被多个 worker 消费;
  • • 合并函数 merge 要注意关闭输出通道;
  • • worker 中如有异常(如 panic)应提前恢复;
  • • 可加 context 实现取消控制;

六、小结

Fan-out / Fan-in 是构建并发处理流水线的核心模式,结合 goroutine 和 channel,可以构建高吞吐、高可扩展的数据处理系统。

相关推荐
阿里云云原生1 小时前
5 分钟零代码改造,让 Go 应用自动获得全链路可观测能力
云原生·go
开心就好20251 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
悟空码字1 小时前
告别“屎山代码”:AI 代码整洁器让老项目重获新生
后端·aigc·ai编程
小码哥_常2 小时前
大厂不宠@Transactional,背后藏着啥秘密?
后端
奋斗小强2 小时前
内存危机突围战:从原理辨析到线上实战,彻底搞懂 OOM 与内存泄漏
后端
小码哥_常2 小时前
Spring Boot接口防抖秘籍:告别“手抖”,守护数据一致性
后端
心之语歌2 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
None3212 小时前
【NestJs】基于Redlock装饰器分布式锁设计与实现
后端·node.js
初次攀爬者2 小时前
Kafka + KRaft模式架构基础介绍
后端·kafka
洛森唛2 小时前
Elasticsearch DSL 查询语法大全:从入门到精通
后端·elasticsearch