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

[ISSUE#4468] Optimize broker buffer length initialization #4469

Merged
merged 12 commits into from Jun 22, 2022
Merged

[ISSUE#4468] Optimize broker buffer length initialization #4469

merged 12 commits into from Jun 22, 2022

Conversation

shengminw
Copy link
Contributor

What is the purpose of the change

Optimize encoder buffer initialization, expand buffer length to avoid message size exceeding when messageBodySize is on the boundry of maxMessageBodySize.

Brief changelog

  1. add maxMessageSize variable differing from maxMessageBodySize(default maxMessageSize = maxMessageBodySize + 64kb)

  2. add checking messagesize

  3. add junit test "testEncodeLongMessage()"

@coveralls
Copy link

coveralls commented Jun 16, 2022

Coverage Status

Coverage increased (+0.05%) to 52.062% when pulling 8fe4f31 on shengminw:develop into 32733e7 on apache:develop.

Comment on lines +1487 to +1489
//Reserve 64kb for encoding buffer outside body
int maxMessageSize = maxMessageBodySize + 64 * 1024;
byteBuf = alloc.directBuffer(maxMessageSize);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi, I wonder to know why it is 64KB?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Most of parameters in the message encoding are fixed length, only the properties and tpopic name content are variable. The maximum length of properties should be less than or equal to Short.MAX_VALUE, and the topic name content should be less than or equal to 127 bytes. Taking the maximum value, it adds up to about 33kb. Considering to reserve some space for subsequent adjustments, 64kb was chosen.

  • org.apache.rocketmq.client.Validators#TOPIC_MAX_LENGTH
public static final int TOPIC_MAX_LENGTH = 127;
  • org.apache.rocketmq.store.CommitLog.MessageExtEncoder#encode
if (propertiesLength > Short.MAX_VALUE) {
    log.warn("putMessage message properties length too long. length={}", propertiesData.length);
    return new PutMessageResult(PutMessageStatus.PROPERTIES_SIZE_EXCEEDED, null);
}

Note: The maximum length of the topic is set on the client side, and there is no open interface for modification. Besides, the broker side does not provide the parameter "TOPIC_MAX_LENGTH", so I directly select the extra space as a fixed value.

Copy link
Contributor

@tsunghanjacktsai tsunghanjacktsai left a comment

Choose a reason for hiding this comment

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

Hi,

Thx for your contribution in advance. But we could make a discuss if it is worth making this change.

The ByteBuffer used here was from Netty API, and it already had an implementation of autoscaling under it. Whenever the ByteBuf reaches the initialCapacity set by developers, it would start to autoscale by 4MB until maxCapacity (set by devs) or Integer.MAX_VALUE.

Of course, we do not want autoscaling it every time, but if the chance of exceeding the maxMessageBodySize is not that high, I don't see why we need to add another 64KB (from your changes) for ByteBuf.

@shengminw
Copy link
Contributor Author

shengminw commented Jun 17, 2022

Hi,

Thx for your contribution in advance. But we could make a discuss if it is worth making this change.

The ByteBuffer used here was from Netty API, and it already had an implementation of autoscaling under it. Whenever the ByteBuf reaches the initialCapacity set by developers, it would start to autoscale by 4MB until maxCapacity (set by devs) or Integer.MAX_VALUE.

Of course, we do not want autoscaling it every time, but if the chance of exceeding the maxMessageBodySize is not that high, I don't see why we need to add another 64KB (from your changes) for ByteBuf.

Yes, using bytebuf can achieve autoscaling, so in the current scenario, no error will be reported. But what I consider is that mq should have its own detection of the encoding length of the message, instead of relying on the self-autoscaling of bytebuf.

As for why it is 64kb, I have replied in a previous comment.

@tsunghanjacktsai
Copy link
Contributor

@shengminw Okay, that makes sense. Thx for your reply. Maybe @ni-ze would like to check this out.

@shengminw
Copy link
Contributor Author

@tsunghanjacktsai ok, thanks~

CommitLog.PutMessageThreadLocal putMessageThreadLocal = commitLog.getPutMessageThreadLocal().get();
PutMessageResult encodeResult1 = putMessageThreadLocal.getEncoder().encode(messageExtBrokerInner);
assertTrue(encodeResult1 == null);

Copy link
Member

Choose a reason for hiding this comment

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

@shengminw This test is for DefaultMessageStore.
So just use type conversion (DefaultMessageStore) messagestore, instead of reflection.

The reflection is not friendly for further evolution.

Copy link
Member

Choose a reason for hiding this comment

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

BTW, it maybe need another test for body size exactly equal to max message size.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, I will revise it.

@codecov-commenter
Copy link

codecov-commenter commented Jun 20, 2022

Codecov Report

Merging #4469 (8fe4f31) into develop (32733e7) will decrease coverage by 0.11%.
The diff coverage is 100.00%.

@@              Coverage Diff              @@
##             develop    #4469      +/-   ##
=============================================
- Coverage      48.16%   48.04%   -0.12%     
+ Complexity      5127     5103      -24     
=============================================
  Files            649      649              
  Lines          43021    43026       +5     
  Branches        5625     5626       +1     
=============================================
- Hits           20720    20672      -48     
- Misses         19798    19845      +47     
- Partials        2503     2509       +6     
Impacted Files Coverage Δ
...main/java/org/apache/rocketmq/store/CommitLog.java 76.45% <100.00%> (+1.18%) ⬆️
...rg/apache/rocketmq/common/stats/StatsSnapshot.java 84.61% <0.00%> (-15.39%) ⬇️
...ache/rocketmq/common/stats/MomentStatsItemSet.java 39.13% <0.00%> (-13.05%) ⬇️
.../apache/rocketmq/common/stats/MomentStatsItem.java 38.09% <0.00%> (-9.53%) ⬇️
...va/org/apache/rocketmq/store/FlushDiskWatcher.java 81.25% <0.00%> (-9.38%) ⬇️
...org/apache/rocketmq/store/ha/WaitNotifyObject.java 66.07% <0.00%> (-5.36%) ⬇️
...va/org/apache/rocketmq/common/stats/StatsItem.java 50.83% <0.00%> (-5.00%) ⬇️
...ketmq/client/impl/consumer/PullMessageService.java 71.11% <0.00%> (-4.45%) ⬇️
...ketmq/common/protocol/body/ConsumerConnection.java 95.83% <0.00%> (-4.17%) ⬇️
...lient/impl/consumer/DefaultMQPushConsumerImpl.java 40.84% <0.00%> (-3.00%) ⬇️
... and 11 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 32733e7...8fe4f31. Read the comment docs.

MessageExtEncoder(final int maxMessageBodySize) {
ByteBufAllocator alloc = UnpooledByteBufAllocator.DEFAULT;
byteBuf = alloc.directBuffer(maxMessageBodySize);
//Reserve 64kb for encoding buffer outside body
int maxMessageSize = maxMessageBodySize + 64 * 1024;
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, variable parameters, which is properties and topic name, is limited and properties before write into commitLog, if this two item length exceed limit, it won't reach here.

and I think it is a little weird to limit length base on an auto scalable ByteBuf.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, get to this step, properties(max 32kb) and topic name(max 127 bytes) are limited. But the full message length still may exceed 4M(maxMessageBodySize).
About whether it is neccessary to do this change, it's worth discussing. I think, in the previous version, maxMessageBodySize is also used to limit buffer length. So from my point of view, I think it is necessary to add.

@dongeforever dongeforever merged commit da01deb into apache:develop Jun 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants