Golang微服务中并发技术的应用实践

Golang微服务中并发技术的应用实践 亲爱的论坛成员们,

我目前正在开发一个包含四个进程的微服务。这些进程之间存在依赖关系。具体来说:

  1. 进程 2 依赖于进程 1。
  2. 进程 3 和进程 4 依赖于进程 2。

我希望应用并发来提升性能,但不确定该如何进行。任何指导或最佳实践都将不胜感激。

谢谢!

2 回复

实现这一目标的方法有很多,我无法给出一个通用的示例,因为这取决于你的具体实现。Go语言通过Goroutines使得编写正确的并发代码变得容易,稍微学习一下Goroutines,你肯定会对如何在你的服务中实现这一点产生想法。

我推荐Rob Pike的演讲“并发不是并行”。它与你“如何着手”的问题没有直接关系,但或许能帮助你理解Go语言中的并发代码理论,以及为什么没有唯一的方法来做事情。

(我认为这个演讲可以在YouTube上找到,试着找一个能展示幻灯片的版本。)

更多关于Golang微服务中并发技术的应用实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang微服务中处理进程依赖的并发场景,推荐使用sync.WaitGroupchannel的组合方案。以下是具体实现:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    // 用于进程间通信的channel
    proc1Done := make(chan struct{})
    proc2Done := make(chan struct{})

    // 进程1
    wg.Add(1)
    go func() {
        defer wg.Done()
        fmt.Println("进程1开始执行")
        time.Sleep(1 * time.Second) // 模拟处理时间
        fmt.Println("进程1执行完成")
        close(proc1Done) // 通知进程1已完成
    }()

    // 进程2 - 依赖进程1
    wg.Add(1)
    go func() {
        defer wg.Done()
        <-proc1Done // 等待进程1完成
        fmt.Println("进程2开始执行")
        time.Sleep(1 * time.Second)
        fmt.Println("进程2执行完成")
        close(proc2Done) // 通知进程2已完成
    }()

    // 进程3 - 依赖进程2
    wg.Add(1)
    go func() {
        defer wg.Done()
        <-proc2Done // 等待进程2完成
        fmt.Println("进程3开始执行")
        time.Sleep(1 * time.Second)
        fmt.Println("进程3执行完成")
    }()

    // 进程4 - 依赖进程2
    wg.Add(1)
    go func() {
        defer wg.Done()
        <-proc2Done // 等待进程2完成
        fmt.Println("进程4开始执行")
        time.Sleep(1 * time.Second)
        fmt.Println("进程4执行完成")
    }()

    wg.Wait()
    fmt.Println("所有进程执行完成")
}

对于需要传递数据的场景,可以使用带缓冲的channel:

func processWithDataTransfer() {
    var wg sync.WaitGroup
    
    // 进程1产生数据
    dataChan := make(chan string, 10)
    
    wg.Add(1)
    go func() {
        defer wg.Done()
        defer close(dataChan)
        for i := 0; i < 5; i++ {
            data := fmt.Sprintf("data-%d", i)
            dataChan <- data
            fmt.Printf("进程1产生: %s\n", data)
        }
    }()

    // 进程2处理数据
    processedChan := make(chan string, 10)
    
    wg.Add(1)
    go func() {
        defer wg.Done()
        defer close(processedChan)
        for data := range dataChan {
            processed := fmt.Sprintf("processed-%s", data)
            processedChan <- processed
            fmt.Printf("进程2处理: %s -> %s\n", data, processed)
        }
    }()

    // 进程3和进程4并发处理结果
    for i := 3; i <= 4; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            for data := range processedChan {
                fmt.Printf("进程%d消费: %s\n", id, data)
            }
        }(i)
    }

    wg.Wait()
}

使用context处理超时和取消:

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

    var wg sync.WaitGroup
    proc1Done := make(chan struct{})

    // 进程1
    wg.Add(1)
    go func() {
        defer wg.Done()
        select {
        case <-time.After(2 * time.Second):
            fmt.Println("进程1完成")
            close(proc1Done)
        case <-ctx.Done():
            fmt.Println("进程1超时")
        }
    }()

    // 进程2
    wg.Add(1)
    go func() {
        defer wg.Done()
        select {
        case <-proc1Done:
            fmt.Println("进程2开始执行")
        case <-ctx.Done():
            fmt.Println("进程2取消")
        }
    }()

    wg.Wait()
}

这种模式确保了依赖关系的正确执行,同时充分利用了Golang的并发特性。

回到顶部