Go의 병렬 처리 일반 모드
하지만 고로틴이라고는 하지만 다양한 글씨가 있는데 어떤 게 좋을까요?함정은?기다리고 싶은 건 신경 쓰이는 거야.
그래서 이것은 제 개인적인 견해입니다. 제가 자주 사용하는 모델을 남기고 싶습니다.
패턴
errgroup
Go에 어떤 처리를 적었을 때 적당한 오류 처리는 끊어져도 끊길 수 없다고 생각해서 특수화된errgroup을 사용했습니다.
// サンプル準備
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
newArr := []int{}
// 並列処理を開始
eg := errgroup.Group{}
mutex := sync.Mutex{}
for _, v := range arr {
// ループする時はちゃんと値をコピーしないと1つが複数回実行されてしまう
v := v
eg.Go(func() error {
// 何かしらの処理(もしエラーが出たらerrを返す)
fmt.Println(v)
// 値をsliceやmapに格納する時は排他制御する
mutex.Lock()
newArr = append(newArr, v)
mutex.Unlock()
time.Sleep(time.Second * 1)
return nil
})
}
if err := eg.Wait(); err != nil { // 実行が終わるまで待つ
// エラーハンドリング
fmt.Println(err)
return
}
fmt.Println(newArr)
errgroup (최대 실행수 제어ver)
최대 동시 실행 건수가 예측되지 않을 때는 실행 수를 제한하려 하겠죠.
// サンプル準備
ctx := context.Background()
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
newArr := []int{}
// 並列処理を開始
eg := errgroup.Group{}
mutex := sync.Mutex{}
sem := semaphore.NewWeighted(3) // 最大数を3に設定
for _, v := range arr {
// ループする時はちゃんと値をコピーしないと1つが複数回実行されてしまう
v := v
sem.Acquire(ctx, 1)
eg.Go(func() error {
// 何かしらの処理(もしエラーが出たらerrを返す)
fmt.Println(v)
time.Sleep(time.Second * 1)
// 値をsliceやmapに格納する時は排他制御する
mutex.Lock()
newArr = append(newArr, v)
mutex.Unlock()
sem.Release(1)
return nil
})
}
if err := eg.Wait(); err != nil { // 実行が終わるまで待つ
// エラーハンドリング
fmt.Println(err)
return
}
fmt.Println(newArr)
이상은 (^q^)입니다.
응, 없어졌어!
아마 여러분들이 그렇게 생각하실 거예요. 하지만 저는 이 두 개만 사용했어요.
다른 것은 많지만 기본적으로 사용하지 않았다.
주의 사항
멈춰서 생각해봐요. 정말 병렬 처리가 필요한가요?
대전제로 병행 처리를 하지 않으면 사용하지 않는 것이 좋다.
재현성이 낮고 치명적인 버그가 박히기 쉽고 DB 등 예상 외의 부하를 감당하며 코드를 유지하는 엔지니어의 난이도가 높아지는 등이다.
따라서 5분~10분이면 되기 때문에 일단 멈추고 디자인을 재고해 I/F, 논리, 조회 등에 공을 들여야 한다.
그걸 바탕으로 유용하다고 판단할 수 있다면 사용하는 게 좋을 것 같아요.
최대 부하를 잘 상상해 보세요.
Go는 손쉽게 병행 처리가 가능하지만, 마음이 가볍고 다용도로 쓰일 경우 본격 촬영 환경에서 예상치 못한 부하를 감당하면서 큰 고장이 자주 발생한다.
나는 주로 아래의 몇 가지를 고려한다.
결과 보존에 주의
쉽게 잊어버리지만, 슬라이스와 맵을 배타적으로 제어하지 않으면 일치하지 않을 수 있습니다.
컴파일 오류를 눈치채지 못하면 자신이나 타인의 눈으로 확인하세요.(lint나 정적 분석을 통해 알 수 있나요?)
mutex := sync.Mutex{}
...
mutex.Lock()
newArr = append(newArr, v)
mutex.Unlock()
총결산
백엔드를 개발하면 협업자의 API가 느려지고 많은 DB 연결이 필요하며 API의 성능도 떨어진다.
이럴 때 병행 처리는 문제를 해결하는 카드이기 때문에 적절하게 사용하면 엔지니어 생활을 잘 할 수 있을 것 같아요.
Reference
이 문제에 관하여(Go의 병렬 처리 일반 모드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/aikizoku/articles/golang-goroutine텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)