På ytnivå är det enda jag har frågor om beställning av inkrementerande väntegrupp och beställning av arbetet:
func (s *Scheduler) Enqueue(req interface{}) {
select {
case s.reqChan <- req:
s.wg.Add(1)
}
}
Jag tror inte att ovanstående kommer att orsaka mycket problem i praktiken med den här stora arbetsbelastningen, men jag tror att det kan vara ett logiskt tävlingstillstånd. Vid lägre nivåer av samtidighet och mindre arbetsstorlekar kan det ställa in ett meddelande, sedan byta till en goroutin som börjar arbeta med det meddelandet, SEDAN arbetet i väntegruppen.
Nästa är du säker på att process
Metoden är trådsäker?? Jag skulle anta att det, baserat på redis go-dokumentationen, fungerar med go run -race
har du någon utgång?
Vid något tillfälle är det helt rimligt och förväntas att prestanda sjunker. Jag skulle rekommendera att starta prestandatester för att se var latens och genomströmning börjar avta:
kanske en pool på 10, 100, 500, 1000, 2500, 5000, 10000, eller vad som är vettigt. IMO ser det ut som att det finns 3 viktiga variabler att ställa in:
- Storlek för arbetarpool
- Arbetsköbuffertstorlek
- Redis
MaxActive
Det största som hoppar ut är att det ser ut som redis.Pool är konfigurerat för att tillåta ett obegränsat antal anslutningar:
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)
},
}
// Maximalt antal anslutningar som tilldelas av poolen vid en given tidpunkt.// När noll finns det ingen gräns för antalet anslutningar i poolen. MaxActive int
Jag skulle personligen försöka förstå var och när prestationerna börjar sjunka med hänsyn till storleken på din personalpool. Detta kan göra det lättare att förstå vad ditt program begränsas av.