På overfladeniveau er det eneste, jeg har spørgsmål om, bestilling af voksende ventegruppe og bestilling af arbejdet:
func (s *Scheduler) Enqueue(req interface{}) {
select {
case s.reqChan <- req:
s.wg.Add(1)
}
}
Jeg tror ikke, at ovenstående vil volde store problemer i praksis med denne store arbejdsbyrde, men jeg tror, det kan være en logisk racebetingelse. Ved lavere niveauer af samtidighed og mindre arbejdsstørrelser kan det sætte en besked i kø, derefter skifte til en goroutine, der starter arbejdet med den besked, SÅ arbejdet i ventegruppen.
Dernæst er du sikker på at process
metoden er trådsikker?? Jeg vil antage, at det, baseret på redis go-dokumentationen, gør løb med go run -race
har du noget output?
På et tidspunkt er det fuldstændig rimeligt og forventes, at ydeevnen falder. Jeg vil anbefale at starte ydeevnetests for at se, hvor latens og gennemløb begynder at falde:
måske en pulje på 10, 100, 500, 1000, 2500, 5000, 10000, eller hvad der nu giver mening. IMO ser det ud til, at der er 3 vigtige variabler at tune:
- Arbejdspuljestørrelse
- Work Queue Buffer Størrelse
- Redis
MaxActive
Den største ting, der springer ud, er, at det ligner redis. Pool er konfigureret til at tillade et ubegrænset antal forbindelser:
pool := &redis.Pool{
MaxIdle: 50,
IdleTimeout: 240 * time.Second,
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
Dial: func() (redis.Conn, error) {
return dial("tcp", address, password)
},
}
// Maksimalt antal forbindelser tildelt af puljen på et givet tidspunkt.// Når nul er der ingen grænse for antallet af forbindelser i puljen.MaxActive int
Jeg ville personligt forsøge at forstå, hvor og hvornår præstationerne begynder at falde med hensyn til størrelsen af din medarbejderpulje. Dette kan gøre det lettere at forstå, hvad dit program er begrænset af.