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

Support specifying MaxBytes in range request #14810

Closed
wants to merge 6 commits into from

Conversation

linxiulei
Copy link

fixes: #14809

server/storage/mvcc/kvstore_txn.go Outdated Show resolved Hide resolved
server/storage/mvcc/kvstore_txn.go Outdated Show resolved Hide resolved
server/storage/mvcc/kvstore_txn.go Outdated Show resolved Hide resolved
@ahrtr
Copy link
Member

ahrtr commented Nov 19, 2022

The new feature makes sense to me, only limiting the max number of entries isn't enough if each entry is too big.

When client specifies both limit and maxBytes, then server side truncates the result when whichever is satisfied first.

It should have no impact on Kubernetes, because the maxByte defaults to 0, which means no limit.

@ahrtr
Copy link
Member

ahrtr commented Nov 19, 2022

Please also add some common e2e/integration test. Since this PR is already too big, so I'm OK to add it in a separate PR.

@ahrtr ahrtr changed the title Support paginating by size Support specifying MaxBytes in range request Nov 19, 2022
@ahrtr
Copy link
Member

ahrtr commented Nov 19, 2022

When this PR gets merged, probably someone could enhance K8s side to support maxBytes as well. cc @dims @liggitt @deads2k @lavalamp

FYI. #14810 (comment)

Copy link
Member

@ahrtr ahrtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahrtr
Copy link
Member

ahrtr commented Nov 20, 2022

@linxiulei Please also add a changelog in https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.6.md, of course, can be in a separate PR.

TODO list:

  1. add e2e/integration test. Please see Support specifying MaxBytes in range request #14810 (comment);
  2. add changelog item.

@linxiulei
Copy link
Author

Will do. Thanks @ahrtr !

@@ -86,12 +86,16 @@ func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev i
}

limit := int(ro.Limit)
if limit <= 0 || limit > len(revpairs) {
if limit <= 0 || limit >= len(revpairs) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no-op

@serathius
Copy link
Member

I would like to see more tests before we merge this PR. This code is on a pretty important code path and there were already multiple edge cases not handled properly in this PR (for example maxBytes not working when sorting is enabled).

@linxiulei
Copy link
Author

I manually tested it when making changes, which I can put into e2e/integration in later PR.

./bin/etcdctl get a z --max-bytes 14 --sort-by CREATE --order DESCEND --limit 2 -w json | python -m json.tool
{
    "header": {
        "cluster_id": 14841639068965178418,
        "member_id": 10276657743932975437,
        "revision": 4,
        "raft_term": 15
    },
    "kvs": [
        {
            "key": "Yw==",
            "create_revision": 4,
            "mod_revision": 4,
            "version": 1,
            "value": "YmFy"
        }
    ],
    "more": true,
    "count": 3
}

What tests else do we need here?

serathius
serathius previously approved these changes Nov 21, 2022
Copy link
Member

@fuweid fuweid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM(non-binding)

It seems that it reduces that grpc unary API memory usage. The grpc http2 transport only releases the memory after last byte has been sent. I was thinking that if the Range can be streaming type, the List-All from kube-apiserver won't cause memory spike in ETCD side because the pending bytes in memory is limit by http2 stream/connection windows size. However, it might be hard to integrate.

This patch can chunk the data. Thanks! @linxiulei Help a lot.

@serathius
Copy link
Member

Would also want to get some feedback from K8s scalability people who have some experience with issue that this feature tries to fix. cc @mborsz

@serathius serathius dismissed their stale review November 21, 2022 19:23

want more feedback from K8s people

@mborsz
Copy link
Contributor

mborsz commented Nov 22, 2022

I think it would be worth discussing this with authors/reviewers of https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3157-watch-list which currently tries to solve similar (the same?) problem.

Probably it makes sense to get buy-in from sig-apimachinery that we will be able to use this in kube-apiserver before we make changes to etcd.

@linxiulei
Copy link
Author

I agree to get more buy-ins from k8s side to make this feature more appealing. But I do not think it should be a blocker for etcd as this feature can benefit other use cases other than k8s. Also getting buy-ins from k8s side involves more discussions and takes time.

Nonetheless, I will try to initiate some discussion within k8s.

totalBytes += int64(kv.Size())
if totalBytes > r.MaxBytes {
resp.More = true
rr.KVs = rr.KVs[:i]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the code correctly, it means we might be sending '0' items, it is, we might stuck completely,
giving empty responses and retries.

I think we should prioritize giving at least 1 item in such situation. And be very explicit that in this situation the maxBytes contract can be exceeded.
But this is the exact semantic discussion we should have with k8s api machinery team @mborsz @lavalamp

We also need to have tests for this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you understood correctly. The initial version was to return the result with size just exceeding the maxBytes so at least one item is returned. But this made the maxBytes a bit ambiguous.

Given the max object size is 1.5MB, we can warm users the maxBytes should be bigger than 1.5MB to avoid returning 0 items. WDYT?

@lavalamp
Copy link

When this PR gets merged, probably someone could enhance K8s side to support maxBytes as well

k8s would not directly expose this to end users, to be clear. (but thanks for the heads up!)

Signed-off-by: Eric Lin <exlin@google.com>
Signed-off-by: Eric Lin <exlin@google.com>
Run
1. ./script/genproto.sh
2. ./scripts/update_proto_annotations.sh

Signed-off-by: Eric Lin <exlin@google.com>
Signed-off-by: Eric Lin <exlin@google.com>
Signed-off-by: Eric Lin <exlin@google.com>
Signed-off-by: Eric Lin <exlin@google.com>
@linxiulei linxiulei force-pushed the size_paging branch 2 times, most recently from e97726b to 97d4b6c Compare December 30, 2022 10:23
@linxiulei
Copy link
Author

Please also add some common e2e/integration test. Since this PR is already too big, so I'm OK to add it in a separate PR.

I added a commit of e2e tests in the previous push

@codecov-commenter
Copy link

Codecov Report

Merging #14810 (97d4b6c) into main (4ae4d9f) will decrease coverage by 0.16%.
The diff coverage is 53.12%.

@@            Coverage Diff             @@
##             main   #14810      +/-   ##
==========================================
- Coverage   74.74%   74.57%   -0.17%     
==========================================
  Files         415      415              
  Lines       34287    34311      +24     
==========================================
- Hits        25629    25589      -40     
- Misses       7018     7071      +53     
- Partials     1640     1651      +11     
Flag Coverage Δ
all 74.57% <53.12%> (-0.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
server/storage/mvcc/kv.go 40.00% <ø> (ø)
client/v3/op.go 73.97% <12.50%> (-1.89%) ⬇️
server/etcdserver/txn/txn.go 89.19% <46.66%> (-1.65%) ⬇️
etcdctl/ctlv3/command/get_command.go 69.15% <100.00%> (+0.58%) ⬆️
server/storage/mvcc/kvstore_txn.go 76.80% <100.00%> (+0.61%) ⬆️
server/storage/mvcc/watchable_store.go 85.14% <0.00%> (-7.61%) ⬇️
client/v3/concurrency/mutex.go 61.03% <0.00%> (-5.20%) ⬇️
client/v3/leasing/txn.go 88.09% <0.00%> (-3.18%) ⬇️
server/etcdserver/cluster_util.go 70.35% <0.00%> (-3.17%) ⬇️
server/proxy/grpcproxy/watch.go 92.48% <0.00%> (-2.90%) ⬇️
... and 18 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@stale
Copy link

stale bot commented Apr 2, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 2, 2023
@stale stale bot closed this May 21, 2023
@linxiulei
Copy link
Author

/reopen

@ahrtr ahrtr removed the stale label Jul 24, 2023
@linxiulei
Copy link
Author

How can I re-open it? I am still active on this PR if maintainers are able to evaluate it

@ahrtr
Copy link
Member

ahrtr commented Jul 25, 2023

I am not able to reopen either. Please raise a new PR, thx

@fuweid
Copy link
Member

fuweid commented Jul 25, 2023

@linxiulei maybe it will be active after you repush?

@fuweid

This comment was marked as off-topic.

@linxiulei
Copy link
Author

repush didn't work either. Let me raise a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Support paginating by key-value size
8 participants