Sobes.tech
Principal

// Тапсырыс жаңартылған кезде, біз бірнеше қызметке (шетелдік) тапсырыс деректерін жіберуіміз керек // қызметтердің саны өсуде (мүмкін мыңдаған+) // біз код жаздық, бәрі жақсы болды, бірақ уақыт өте келе біздің қызмет көп ресурсты тұтынуға бастады func (s *orderService) SendOrder(ctx context.Context, hosts []string, order Order) { for i := 0; i < len(hosts); i++ { go func() { // Бұл ұзақ уақыттық желілік шақыру деп елестетейік response, err := s.httpClient.Send(ctx, hosts[i], order) if err != nil { s.logger.Error(ctx, "жіберу сәтсіз", err) return } s.logger.Info(ctx, "сәтті", response) }() } }

sobes.tech AI

AI-дан жауап

Көрсетілген кодта цикл айнымалысы i-ді горутина ішінде пайдалану мәселесі бар:

for i := 0; i < len(hosts); i++ {
    go func() {
        response, err := s.httpClient.Send(ctx, hosts[i], order)
        // ...
    }()
}

Мұнда i анонимді функция ішінде пайдаланылады, бірақ горутина іске қосылған кезде i мәні өзгеруі мүмкін, бұл қателерге әкеледі (мысалы, массив шекарасынан шығу).

Сонымен қатар, көптеген сервистер болған кезде (мыңдаған және одан да көп) бір уақытта мыңдаған горутин іске қосу ресурстарды шамадан тыс пайдалануына әкелуі мүмкін (жад, CPU, желі байланыстары).

Ұсыныстар:

  1. i айнымалысының жабысуын түзету:
for i := 0; i < len(hosts); i++ {
    host := hosts[i] // жергілікті көшірме
    go func(h string) {
        response, err := s.httpClient.Send(ctx, h, order)
        // ...
    }(host)
}
  1. Бір уақытта жұмыс істеп жатқан горутин санын шектеу:

Семафор немесе жұмысшылар пулын пайдалану арқылы бір уақытта тым көп горутин құруды болдырмау.

Мысал семаформен:

sem := make(chan struct{}, 100) // максимум 100 бір уақытта жұмыс істейтін горутин

for _, host := range hosts {
    sem <- struct{}{} // семафорды алу
    go func(h string) {
        defer func() { <-sem }() // семафорды босату
        response, err := s.httpClient.Send(ctx, h, order)
        if err != nil {
            s.logger.Error(ctx, "жіберу сәтсіз", err)
            return
        }
        s.logger.Info(ctx, "сәтті", response)
    }(host)
}

// барлық горутин аяқталғанын күту
for i := 0; i < cap(sem); i++ {
    sem <- struct{}{}
}
  1. Жұмысшы пулын пайдалану:

Белгілі бір саны бар жұмысшыларды құрып, олар хосттар каналынан оқып, сұраулар жібереді.

  1. Қателер мен тайм-ауттарды өңдеу:

Тұрақтылық үшін тайм-ауттарды бақылау және қателерді дұрыс өңдеу маңызды.

Осылайша, ресурстарды шамадан тыс пайдалануын болдырмау үшін параллелизмді бақылау және жабысу айнымалыларымен дұрыс жұмыс істеу керек.