mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
fix requests tracker concurrency
This commit is contained in:
parent
b5fc001bba
commit
df276c5538
@ -2423,51 +2423,53 @@ type requestTracker struct {
|
|||||||
err error
|
err error
|
||||||
after int
|
after int
|
||||||
|
|
||||||
|
// this block should be updated consistently
|
||||||
parallelLock sync.Mutex
|
parallelLock sync.Mutex
|
||||||
parallel int
|
shouldTrackParallelRequests bool
|
||||||
maxParallel int
|
parallelRequests int
|
||||||
|
maxParallelRequests int
|
||||||
delay time.Duration
|
parallelRequestDelay time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rt *requestTracker) errorReady() bool {
|
func (rt *requestTracker) trackParallelRequests() {
|
||||||
rt.Lock()
|
if !rt.shouldTrackParallelRequests {
|
||||||
defer rt.Unlock()
|
// do not track parallel requests unless specifically enabled
|
||||||
return rt.err != nil && rt.requests >= rt.after
|
return
|
||||||
}
|
|
||||||
|
|
||||||
func (rt *requestTracker) inc() {
|
|
||||||
rt.parallelLock.Lock()
|
|
||||||
rt.parallel++
|
|
||||||
if rt.maxParallel < rt.parallel {
|
|
||||||
rt.maxParallel = rt.parallel
|
|
||||||
}
|
}
|
||||||
rt.parallelLock.Unlock()
|
if rt.parallelLock.TryLock() {
|
||||||
|
// lock acquired: we are the only or the first concurrent request
|
||||||
|
// initialize the next set of parallel requests
|
||||||
|
rt.parallelRequests = 1
|
||||||
|
} else {
|
||||||
|
// lock is held by other requests
|
||||||
|
// now wait for the lock to increase the parallelRequests
|
||||||
|
rt.parallelLock.Lock()
|
||||||
|
rt.parallelRequests++
|
||||||
|
}
|
||||||
|
defer rt.parallelLock.Unlock()
|
||||||
|
// update the local maximum of parallel collisions
|
||||||
|
if rt.maxParallelRequests < rt.parallelRequests {
|
||||||
|
rt.maxParallelRequests = rt.parallelRequests
|
||||||
|
}
|
||||||
|
// increase the chance of collisions
|
||||||
|
if rt.parallelRequestDelay > 0 {
|
||||||
|
time.Sleep(rt.parallelRequestDelay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rt *requestTracker) incWithOptionalError() error {
|
||||||
rt.Lock()
|
rt.Lock()
|
||||||
defer rt.Unlock()
|
defer rt.Unlock()
|
||||||
rt.requests++
|
rt.requests++
|
||||||
if rt.delay != 0 {
|
if rt.err != nil && rt.requests >= rt.after {
|
||||||
time.Sleep(rt.delay)
|
// reset and pass the error
|
||||||
}
|
defer func() {
|
||||||
}
|
|
||||||
|
|
||||||
func (rt *requestTracker) reset() {
|
|
||||||
rt.parallelLock.Lock()
|
|
||||||
rt.parallel = 0
|
|
||||||
rt.parallelLock.Unlock()
|
|
||||||
|
|
||||||
rt.Lock()
|
|
||||||
defer rt.Unlock()
|
|
||||||
rt.err = nil
|
rt.err = nil
|
||||||
rt.after = 0
|
rt.after = 0
|
||||||
rt.delay = 0
|
}()
|
||||||
}
|
|
||||||
|
|
||||||
func (rt *requestTracker) getErr() error {
|
|
||||||
rt.Lock()
|
|
||||||
defer rt.Unlock()
|
|
||||||
return rt.err
|
return rt.err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRequestTracker(requests int, err error, after int) requestTracker {
|
func newRequestTracker(requests int, err error, after int) requestTracker {
|
||||||
@ -2512,10 +2514,9 @@ func newFakeObjectManager(informerFactory informers.SharedInformerFactory) *fake
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (om *fakeObjectManager) CreatePod(ctx context.Context, pod *v1.Pod) error {
|
func (om *fakeObjectManager) CreatePod(ctx context.Context, pod *v1.Pod) error {
|
||||||
defer om.createPodTracker.inc()
|
defer om.createPodTracker.trackParallelRequests()
|
||||||
if om.createPodTracker.errorReady() {
|
if err := om.createPodTracker.incWithOptionalError(); err != nil {
|
||||||
defer om.createPodTracker.reset()
|
return err
|
||||||
return om.createPodTracker.getErr()
|
|
||||||
}
|
}
|
||||||
pod.SetUID(types.UID(pod.Name + "-uid"))
|
pod.SetUID(types.UID(pod.Name + "-uid"))
|
||||||
return om.podsIndexer.Update(pod)
|
return om.podsIndexer.Update(pod)
|
||||||
@ -2526,19 +2527,17 @@ func (om *fakeObjectManager) GetPod(namespace, podName string) (*v1.Pod, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (om *fakeObjectManager) UpdatePod(pod *v1.Pod) error {
|
func (om *fakeObjectManager) UpdatePod(pod *v1.Pod) error {
|
||||||
defer om.updatePodTracker.inc()
|
defer om.updatePodTracker.trackParallelRequests()
|
||||||
if om.updatePodTracker.errorReady() {
|
if err := om.updatePodTracker.incWithOptionalError(); err != nil {
|
||||||
defer om.updatePodTracker.reset()
|
return err
|
||||||
return om.updatePodTracker.getErr()
|
|
||||||
}
|
}
|
||||||
return om.podsIndexer.Update(pod)
|
return om.podsIndexer.Update(pod)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *fakeObjectManager) DeletePod(pod *v1.Pod) error {
|
func (om *fakeObjectManager) DeletePod(pod *v1.Pod) error {
|
||||||
defer om.deletePodTracker.inc()
|
defer om.deletePodTracker.trackParallelRequests()
|
||||||
if om.deletePodTracker.errorReady() {
|
if err := om.deletePodTracker.incWithOptionalError(); err != nil {
|
||||||
defer om.deletePodTracker.reset()
|
return err
|
||||||
return om.deletePodTracker.getErr()
|
|
||||||
}
|
}
|
||||||
if key, err := controller.KeyFunc(pod); err != nil {
|
if key, err := controller.KeyFunc(pod); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2733,10 +2732,9 @@ func newFakeStatefulSetStatusUpdater(setInformer appsinformers.StatefulSetInform
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ssu *fakeStatefulSetStatusUpdater) UpdateStatefulSetStatus(ctx context.Context, set *apps.StatefulSet, status *apps.StatefulSetStatus) error {
|
func (ssu *fakeStatefulSetStatusUpdater) UpdateStatefulSetStatus(ctx context.Context, set *apps.StatefulSet, status *apps.StatefulSetStatus) error {
|
||||||
defer ssu.updateStatusTracker.inc()
|
defer ssu.updateStatusTracker.trackParallelRequests()
|
||||||
if ssu.updateStatusTracker.errorReady() {
|
if err := ssu.updateStatusTracker.incWithOptionalError(); err != nil {
|
||||||
defer ssu.updateStatusTracker.reset()
|
return err
|
||||||
return ssu.updateStatusTracker.err
|
|
||||||
}
|
}
|
||||||
set.Status = *status
|
set.Status = *status
|
||||||
ssu.setsIndexer.Update(set)
|
ssu.setsIndexer.Update(set)
|
||||||
@ -2985,7 +2983,8 @@ func parallelScale(t *testing.T, set *apps.StatefulSet, replicas, desiredReplica
|
|||||||
diff := desiredReplicas - replicas
|
diff := desiredReplicas - replicas
|
||||||
client := fake.NewSimpleClientset(set)
|
client := fake.NewSimpleClientset(set)
|
||||||
om, _, ssc := setupController(client)
|
om, _, ssc := setupController(client)
|
||||||
om.createPodTracker.delay = time.Millisecond
|
om.createPodTracker.shouldTrackParallelRequests = true
|
||||||
|
om.createPodTracker.parallelRequestDelay = time.Millisecond
|
||||||
|
|
||||||
*set.Spec.Replicas = replicas
|
*set.Spec.Replicas = replicas
|
||||||
if err := parallelScaleUpStatefulSetControl(set, ssc, om, invariants); err != nil {
|
if err := parallelScaleUpStatefulSetControl(set, ssc, om, invariants); err != nil {
|
||||||
@ -3017,8 +3016,8 @@ func parallelScale(t *testing.T, set *apps.StatefulSet, replicas, desiredReplica
|
|||||||
t.Errorf("Failed to scale statefulset to %v replicas, got %v replicas", desiredReplicas, set.Status.Replicas)
|
t.Errorf("Failed to scale statefulset to %v replicas, got %v replicas", desiredReplicas, set.Status.Replicas)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diff < -1 || diff > 1) && om.createPodTracker.maxParallel <= 1 {
|
if (diff < -1 || diff > 1) && om.createPodTracker.maxParallelRequests <= 1 {
|
||||||
t.Errorf("want max parallel requests > 1, got %v", om.createPodTracker.maxParallel)
|
t.Errorf("want max parallel requests > 1, got %v", om.createPodTracker.maxParallelRequests)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user