-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
May I ask if KEDA can take the initiative to consume the event itself? #5985
Comments
Hello, I think that I'm missing something 😞 |
Hello @JorTurFer , Thank your reply. my project requires the ability to scale up and down elastically. I have researched However, in my scenario, when the This can wake up the Although this way meets my demand, but it increases a lot of development costs. I have to develop a program to consume Actually, I have tried to use the type MyRedisScaler struct {
pb.ExternalScalerServer
redis *redis.Client
}
func NewScaler() *MyRedisScaler {
return &MyRedisScaler{
redis: redisClient.Client(),
ExternalScalerServer: pb.UnimplementedExternalScalerServer{},
}
}
func (scaler *MyRedisScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) {
fmt.Println("1111111111111111111")
listName, ok := scaledObject.ScalerMetadata["listName"]
if !ok {
return nil, fmt.Errorf("listName not found in metadata")
}
elements, err := scaler.redis.LRange(ctx, listName, 0, -1).Result()
if err != nil {
return nil, err
}
_, err = scaler.redis.Del(ctx, listName).Result()
if err != nil {
return nil, err
}
fmt.Println("1111111111111111111 list length: ", len(elements))
return &pb.IsActiveResponse{
Result: len(elements) > 0,
}, nil
}
func (scaler *MyRedisScaler) StreamIsActive(_ *pb.ScaledObjectRef, sias pb.ExternalScaler_StreamIsActiveServer) error {
return errors.New("external push is not supported")
}
func (scaler *MyRedisScaler) GetMetricSpec(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) {
fmt.Println("2222222222222222222")
listLength, ok := scaledObject.ScalerMetadata["listLength"]
fmt.Println("2222222222222222222 listLength: ", listLength)
if !ok {
return nil, fmt.Errorf("listLength not found in metadata")
}
listLengthInt64, err := strconv.ParseInt(listLength, 10, 64)
if err != nil {
return nil, err
}
return &pb.GetMetricSpecResponse{
MetricSpecs: []*pb.MetricSpec{
{
MetricName: "listLength",
TargetSize: listLengthInt64,
},
},
}, nil
}
func (scaler *MyRedisScaler) GetMetrics(ctx context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) {
fmt.Println("3333333333333333333")
listName, ok := metricRequest.ScaledObjectRef.ScalerMetadata["listName"]
if !ok {
return nil, fmt.Errorf("listName not found in metadata")
}
length, err := scaler.redis.LLen(ctx, listName).Result()
if err != nil {
fmt.Println("error: ", err)
return nil, err
}
fmt.Println("3333333333333333333 length: ", length)
return &pb.GetMetricsResponse{
MetricValues: []*pb.MetricValue{
{
MetricName: "listLength",
MetricValue: length,
},
},
}, nil
} I placed the consumption logic in _, err = scaler.redis.Del(ctx, listName).Result() However, I found that although the As a result, only the |
Hello
Sadly, this is not possible and we don't have plans to support it as KEDA doesn't modify in any manner the messages. I can suggest different options to achieve your goals:
I think that this doesn't matter if you want to scale 0->1->0 as the HPA works only during 1->N->1. The scaling from/to 0 is managed by KEDA operator and the cooldown period since the metric returns 0 and KEDA scales to 0 is customizable using the ScaledObject directly |
@JorTurFer Thank you for your advice. I'd love to use the HTTP add-on. it really fits my scenario. In fact, if it were my own project, I would choose the HTTP add-on directly. However, I am developing a company project, so there is a little worry that my boss might blame me for using a beta version. Haha. May I ask if there are any plans to release the production version of the HTTP add-on? And then, I want to ask a question about updating the HPA with KEDA. I have provided a video to show my case. If you have some free time, could you please take a look at this short video? I would be extremely grateful. 20240806-113258.mp4In this video, I started a gRPC server in my local for running a apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: scaledobject-nettools-11
namespace: ding-test
spec:
scaleTargetRef:
name: nettools
pollingInterval: 10
cooldownPeriod: 20
idleReplicaCount: 0
# initialCooldownPeriod: 10
minReplicaCount: 1
maxReplicaCount: 3
triggers:
- type: external
metadata:
scalerAddress: 172.28.130.168:13190
listName: nettools-test:keda:queue
listLength: "1"
databaseIndex: "6" # optional I developed a simple redis scaler: package scaler
import (
"context"
"errors"
"fmt"
"strconv"
pb "git.dp.tech/lebesgue/launching/externalscaler"
redisClient "git.dp.tech/lebesgue/launching/pkg"
"github.com/go-redis/redis/v8"
)
type MyRedisScaler struct {
pb.ExternalScalerServer
redis *redis.Client
}
func NewScaler() *MyRedisScaler {
return &MyRedisScaler{
redis: redisClient.Client(),
ExternalScalerServer: pb.UnimplementedExternalScalerServer{},
}
}
func (scaler *MyRedisScaler) IsActive(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) {
fmt.Println("1111111111111111111")
listName, ok := scaledObject.ScalerMetadata["listName"]
if !ok {
return nil, fmt.Errorf("listName not found in metadata")
}
elements, err := scaler.redis.LRange(ctx, listName, 0, -1).Result()
if err != nil {
return nil, err
}
_, err = scaler.redis.Del(ctx, listName).Result()
if err != nil {
return nil, err
}
fmt.Println("1111111111111111111 list length: ", len(elements))
return &pb.IsActiveResponse{
Result: len(elements) > 0,
}, nil
}
func (scaler *MyRedisScaler) StreamIsActive(_ *pb.ScaledObjectRef, sias pb.ExternalScaler_StreamIsActiveServer) error {
return errors.New("external push is not supported")
}
func (scaler *MyRedisScaler) GetMetricSpec(ctx context.Context, scaledObject *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) {
fmt.Println("2222222222222222222")
listLength, ok := scaledObject.ScalerMetadata["listLength"]
fmt.Println("2222222222222222222 listLength: ", listLength)
if !ok {
return nil, fmt.Errorf("listLength not found in metadata")
}
listLengthInt64, err := strconv.ParseInt(listLength, 10, 64)
if err != nil {
return nil, err
}
return &pb.GetMetricSpecResponse{
MetricSpecs: []*pb.MetricSpec{
{
MetricName: "listLength",
TargetSize: listLengthInt64,
},
},
}, nil
}
func (scaler *MyRedisScaler) GetMetrics(ctx context.Context, metricRequest *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) {
fmt.Println("3333333333333333333")
listName, ok := metricRequest.ScaledObjectRef.ScalerMetadata["listName"]
if !ok {
return nil, fmt.Errorf("listName not found in metadata")
}
length, err := scaler.redis.LLen(ctx, listName).Result()
if err != nil {
fmt.Println("error: ", err)
return nil, err
}
fmt.Println("3333333333333333333 length: ", length)
return &pb.GetMetricsResponse{
MetricValues: []*pb.MetricValue{
{
MetricName: "listLength",
MetricValue: length,
},
},
}, nil
} And I have a deployment which is controlled by this KEDA ScaledObject. At first, my Then I pushed 5 message into Thereafter, my external scaler was triggered by the order Afterwards, my Subsequently, My Pod was woke up: But in my ScaledObject config, I set the I have told KEDA my And after I sent 5 messages into redis-list, the So according to my understanding, I thought KEDA would update HPA's target to 5. And Pods should be scale up to 3. But I found the HPA targets was I don't know if it's my misunderstanding of KEDA? I originally thought that as soon as the current metrics value was returned in Thank you very much~ 🙏🙏🙏 |
Hello,
The OSS add-on GA roadmap is here -> kedacore/http-add-on#911 About your scaler, you're deleting the items from Redis during is active, so GetMetrics probably is returning 0. IsActive will be used to scale from 0 to 1 the workload but then, you need to expose the current value via GetMetrics to scale from 1 to N.
|
I have a rough idea of what I should do. Thank you for your patient explanation. 👍 |
You're welcome! just let me know if you have any doubt about it 😄 |
Proposal
May I ask if KEDA can take the initiative to consume the event itself? For example, when a producer inserts a message into MQ or Redis, does a component of KEDA automatically pop an event? In my scenario, I don't want to do roll polling with
pollingInterval
, and I just want something to trigger scaling up, without a real consumer(or KEDA itself). May I ask if there is a way?thanks~
Use-Case
No response
Is this a feature you are interested in implementing yourself?
Maybe
Anything else?
No response
The text was updated successfully, but these errors were encountered: