Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should scalers reuse opened connection/clients? #1121

Closed
zroubalik opened this issue Sep 9, 2020 · 6 comments · Fixed by #2187
Closed

Should scalers reuse opened connection/clients? #1121

zroubalik opened this issue Sep 9, 2020 · 6 comments · Fixed by #2187
Assignees
Labels
feature-request All issues for new features that have not been committed to
Milestone

Comments

@zroubalik
Copy link
Member

I have been thinking about this for some time. Currently we are creating a new Scaler (and creating a client and opening a connection) in every cycle after in the Scale Loop (after pollingInterval has passed) and we are doing the same in the Metrics Server when HPA is requesting the metrics.

This has some benefits, eg. if the pollingInterval is long, we don't need to keep the opened conection, use the memory resources etc. And if I am not mistaken, then ENV variables on the Target Deployment are evaluated in each cycle.

On the other hand, if the pollingInterval is not that long, we keep opening and closing the clients very often. This is not ideal from the performance perspective and we can as well flood the Event Source (eg. Kafka Broker) with many opened and closed connections.

What if we try to create the Scaler just once, and keep the reference on the Scaler (and if there is an error while accessing this scaler, we can recreate again). We should do it on both sides (in the Operator's Scale Loop and in the Metrics server).

Are there any downsides or problems? Or any other ideas?

@zroubalik zroubalik added needs-discussion feature-request All issues for new features that have not been committed to labels Sep 9, 2020
@zroubalik
Copy link
Member Author

CC @ahmelsayed @anirudhgarg

@arschles
Copy link
Contributor

Would #1133 be a step toward this? in the PR for this #1251 creates a long-lived HTTP client that has an internal connection pool

@zroubalik
Copy link
Member Author

@arschles yeah, that's definititely a step forward 👍

@ahmelsayed
Copy link
Contributor

Sorry for not replying to this earlier @zroubalik, I know I promised I'll but wanted to take a look at all the scalers, and how they implement connections to get a better feel for what would be the best option here.

The following scalers are the ones that create a client/connection on New*() and implement a Close() method.

scaler
azure_eventhub scaler
azure_log_analytics scaler
gcp_pub_sub scaler
influxdb scaler
kafka scaler
liiklus scaler
mongo scaler
mysql scaler
postgresql scaler
rabbitmq scaler
redis scaler
redis_streams scaler

All other scalers don't use connections, or use HTTP style clients that don't need to open/close connections.

Initially I thought a Scaler lifetime could be long, and thought the Scaler interface should make it easier for Scaler authors to handle that scenario, hence the Close() method on the interface. However, as you mentioned it's actually on every pollingInterval now, and we always create and close scalers right away.

The reason to recreate the scalers on every pollingInterval I think was to make sure to always use the latest connection secrets/auth parameters since we don't get notified on Secret or other changes. I think we can hash those values though and only recreate the scaler if those have changed. I did something similar for the external streaming GRPC scaler to make it so that if there are 1000 ScaledObjects pointing to the same GRPC server, they can all reuse the same connection instead of opening 1000 connections for no reason.

We have had few memory leaks (1, 2, 3) when those scalers are not closed, there is one code path now actually also missing to close those scalers (#1608), so I'd also like to improve that to make sure the interface of buildScalers() forces the caller to deal with closing scalers once they are done.

It'd be a slightly large change, but I'll work on it

@mboutet
Copy link
Contributor

mboutet commented Feb 19, 2021

@ahmelsayed, you can also add 1543642 to your memory leaks list

@tomkerkhove tomkerkhove added this to the v2.5.0 milestone Aug 17, 2021
@tomkerkhove
Copy link
Member

@ahmelsayed is working on this one and will aim for v2.5 🎉

ahmelsayed added a commit that referenced this issue Oct 12, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Oct 21, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
ahmelsayed added a commit that referenced this issue Nov 9, 2021
* Add ScalersCache to reuse scales unless they need changing

Closes #1121

Signed-off-by: Ahmed ElSayed <ahmels@microsoft.com>
@tomkerkhove tomkerkhove moved this to Backlog in Roadmap - KEDA Core Feb 10, 2022
SpiritZhou pushed a commit to SpiritZhou/keda that referenced this issue Jul 18, 2023
Signed-off-by: qvalentin <valentin.theodor@web.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request All issues for new features that have not been committed to
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants