-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
PIP-191: Support batched message using entry filter #16680
Comments
I understand the problem, and I have already thought about it, because I am the author of some filters (especially the JMS Selectors Filter) but we have to clarify more this PIP.
|
I just want to copy the partial message properties(we call it batch properties here) to the main header of the entry, without modifying the payload or single message metadata. All messages in one batch must have the same batch properties (both key and value).
It seems that the protocol documents has not described the batch message main header. It just describes the
It seems that there is no compatibility problems. Because I just add properties to the main header , which is empty before, and there is no modification for the payload and single message metadata. The existing EntryFilters can be able to work well with the new |
Is this true now or do you plan to enforce it?
What does this contain? Property names to extract from the messages to be placed in the batch entry metadata properties? Regarding the extraction. Say I have Message 1 with property region=eu, and Message 2 with property region=us. The end result of batch metadata properties will be region=eu, us? |
Hi Asaf @asafm
This is what I plan to enforce it. The batch entry metadata properties is empty now
It contains the properties keys that will be put into the batch entry metadata properties. For example:
|
Ok, what you just wrote, if I understand correctly is pretty big and must be well documented in the proposal. You're saying that you will change the way batching works today. If today I have certain knobs which controls how batching is preparing: max batch size, timeout, max number of records and that's it, now you're changing it such that the batching will grouped by the properties defined ( Why not have list of values for property: region=us,eu ? |
Yes. This will generate smaller batches if
Good idea. Users should know which values they will use. It seems reasonable. |
What I am suggesting is to turn this idea a bit: Instead of batching per the same values of keys, batch all messages, and for each property save a list of values in the metadata. This way you are not affecting the latency on the client side or batch size, yet you still have the ability to filter batches based on metadata without deserializing it. |
Thanks for your suggestion @asafm . If I understand correctly, it means that all the properties, which need to be filted, will be put into the entry header meta. So the protocol will be like below:
But this will not work will for entry filter I think, the reason is that: For example, if our filter's condition is that :
so the expected result is that msg1 will be rejected and msg2 will be accepted. However because msg1 and msg2 are in the same entry, so the entry filter will not work well. In other words, entry filter doesn't support batched message now. |
Let me see if I understand correctly. Today, when an entry filter receives an entry, it gets an Entry that has: public interface Entry {
/**
* @return the data
*/
byte[] getData();
byte[] getDataAndRelease();
/**
* @return the entry length in bytes
*/
int getLength();
/**
* @return the data buffer for the entry
*/
ByteBuf getDataBuffer();
/**
* @return the position at which the entry was stored
*/
Position getPosition();
/**
* @return ledgerId of the position
*/
long getLedgerId();
/**
* @return entryId of the position
*/
long getEntryId();
/**
* Release the resources (data) allocated for this entry and recycle if all the resources are deallocated (ref-count
* of data reached to 0).
*/
boolean release();
} The Entry interface doesn't let you know if this is Batched Entry. You also get FilterContext: @Data
public class FilterContext {
private Subscription subscription;
private MessageMetadata msgMetadata;
private Consumer consumer; and in // differentiate single and batch message metadata
optional int32 num_messages_in_batch = 11 [default = 1]; Which enables you to know this entry is batched. The developer can determine what class would deserialize the entry byte array into a list of separate messages. So currently, given the entry is batched, the filter author can act on it only by paying the cost of deserializing it, right? You're saying we can alter the clients (all clients) to extract specific properties from each message and place those properties values in the message metadata of the Batched Entry. The filter can then use the values to decide if to reject/accept. So the only solution offered in this suggestion is to change the way messages are batched and collect the records into a batch only if they have the same values for the properties configured to be extracted. If this is ok and correct, I have notes on it:
|
Thank you for your patience @asafm . Yes, what you described above is correctly.
I will give a more detailed explanation in the PIP
I agree with you.
I'm not sure if I understand correctly. A batch with same properties will be published immediately if it reach the threshold. The only effect is that the batch size maybe smaller. So I think there is no need to take care of controling the memory in this PIP or introduce new knobs. Because the groupBy behavior will be done in the For details:
And
As we see above the |
Ok, regarding the memory I see that Regarding the actual implementation, I'm a bit puzzled. Why re-use BatchMessageContainerImpl which was geared towards a single batch and make it multi batch? Why not do like the BatchMessageKeyBasedContainer and create your own? You wrote that it will send messages out of order, but once you batch them in separate batches concurrently , this by design will make them out of order no? |
|
Can you explain how in your proposal, you keep the exact ordering of the messages as they were sent to the producer while separating them into different batches based on properties? |
Sure. There is no difference with normal batched sending, except we have to check Let me know if it is not clear enough or this doesn't explain the question correctly:) @asafm |
I'm genuinely asking again, as I still don't understand. Say I send M1( Now I send M2( I reasoned that you will a batch container per properties values set, so if I also send M3( When either batch reaches the trigger point (size/time), they will be sent, no? So once I understand the diagram, I might be able to figure out how it maintains order. In general, once understood, I believe that these question marks need to be explained in the PIP. |
Let me try to explain the current batch process first. @asafm
Also the A The "size or number of messages threshold" check action happens at pulsar/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java Lines 636 to 669 in eddbdd8
All above is current batch sending process. The key of keeping order is that, there will be only one batch exist at the same time, and the batch will be send to channel in a single thread pool. The single thread pool is the pulsar/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ProducerImpl.java Lines 2145 to 2155 in eddbdd8
What I will do in this proposal just is:
So regarding the case you gave above, the process will be:
|
Excellent explanation @AnonHxy - I finally understand the whole mechanism. So in effect, you're adding another trigger condition to send the batch, on top of the current max count, max size, and max delay: Once a message is requested to be added to a batch of its properties (as defined in the configuration) values are different from the records in the batch (i.e. 1st record properties values) than you trigger the batch flush (i.e send and clear). So the side effect of this behavior is that you can easily end up with tiny batches, perhaps even 1 record per batch. There is a good chance once they turn this feature on, they will lose all performance benefits of batching since the batches will be very small. It completely depends on the distribution of values. It might be a big trade-off you're asking from the user: You might trade off the performance of write and perhaps read, for getting the ability to have the server-side filter work for batches.
|
OK. Thanks for your suggestions @asafm . I have update the document and add the "Trade-off" part. And I also clarify in this part that this proposal gives a big chance that batched message can also using entry filter, especially when you have konw the distrbution of values. It will bring benfit because entry filter dosen't support batch message currently. |
The issue had no activity for 30 days, mark with Stale label. |
What ended up with this feature? |
There was a VOTE[1] about this PIP and end up with 1 bingding -1 and 1 non-bing +1. So maybe this feature need more discussion or be canceled @asafm |
The issue had no activity for 30 days, mark with Stale label. |
discuss mail-thread: https://lists.apache.org/thread/cdw5c2lpj5nwzl2zqyv8mphsqqv9vozj
Motivation
This PIP introduces a way to support batched message using entry filter without having to deserilize the entry, through restricting same properties of messages in one batch.
We already have a plug-in way to filter entries in broker, aka PIP-105 PIP 105: Support pluggable entry filter in Dispatcher #12269. But this way has some drawback:
Let's expain the current entry filters in detail. Skip to "Solution" part directly if you have already been clear about the drawback above.
Today, when an entry filter receives an entry, it gets an Entry that has:
The Entry interface doesn't let you know if this is Batched Entry.
You also get FilterContext:
and in MessageMetadata, you have
Which enables you to know this entry is batched.
The developer can determine what class would deserialize the entry byte array into a list of separate messages.
So currently, given the entry is batched, the filter developer can act on it only by paying the cost of deserializing it.
Soultions
How can we using entry filter with batched messages, and without having to deserilize the entry?
One of rejected alternatives
One of alternatives is that we can alter the producers to extract specific properties from each message and place those properties values in the message metadata of the Batched Entry. The filter can then use the values to decide if to reject/accept.
The problem is that if you have different values for a given property for each message in the batch, then the filter author can't provide a reject or accept for this entry since some messages are rejected, and some are accepted.
Soultion
So the only solution is to change the way messages are batched and collect the records into a batch only if they have the same values for the properties configured to be extracted. If a message is added to the producer and the properties are not the same as the batched records, it will trigger a send of this batch and start a new batch with that message.
In summary, this proposal introduces another trigger condition to send the batch, on top of the current max count, max size, and max delay: Once a message is requested to be added to a batch of its properties (partial properteis as defined in a new configuration) values are different from the records in the batch (i.e. 1st record properties values), it will trigger the batch flush (i.e send and clear).
API Changes
Because we know which key/value of properties will be used in our entry filter, so we only need pick the properties which will be used to appy this proposal. Add a producer config to specialize the properties key/value. Only messages have same key/value of properties in the config will apply this proposal.
restrictSameValuesInBatchProperties
type isMap<String, List<String>>
, the map'key is the properties key, and map'value is the properties values.restrictSameValuesInBatchProperties
is empty (default is empty), that means this grouped by properties will not take effect.restrictSameValuesInBatchProperties
will be placed into same batch.Implementation
org.apache.pulsar.client.impl.BatchMessageContainerImpl#add
, we extract the message properties and add it tometadata
:hasSameProperties
likehasSameSchema
. Messages with same properties can be added to the same batch. Once a message with different properties is added, the producer will triger flush and sending the batch.In summary, most of modification in this proposal just are:
Example
There is an example maybe helpful to understand this:
Let's set
restrictSameValuesInBatchProperties
=<region=us,eu; version=1,2>
This means only key named
region
values 'us' or 'eu', andversion
values '1' or'2' will be extracted to the batch meta propertiesThen we have a producer that sends the messges below in order:
msg1
with properties:<region: eu>
msg2
with properties:<region: eu>
msg3
with properties:<region: eu, version:1, tag:a>
msg4
with properties:<region: eu, version:1>
msg5
with properties:<region: us, version:1>
msg6
with properties:<region: us, version:2>
msg7
with properties:<region: us, version:5>
msg8
with properties:<region: us, version:6>
The process of properties extraction will be:
restrictSameValuesInBatchProperties
doesn't contains 'tag'. So msg3 and msg4 will put into the same batch.<region:us>
, and<version>
will be ignored because it's values doesn't exist inrestrictSameValuesInBatchProperties
.Just to summarize, the result will be:
Trade-off
The side effect of this behavior is that it can easily end up with tiny batches, perhaps even 1 record per batch. There is a good chance once they turn this feature on, they will lose all performance benefits of batching since the batches will be very small. It completely depends on the distribution of values.
In spite of this, we shoud clarify that, entry filter dosen't support batched messages currently. So this proposal gives a big chance that batched messages can also using entry filter. It bring great benefits especially when you have konw the distrbution of values.
Reject Alternatives
AbstractBatchMessageContainer
, sayingBatchMessagePropertiesBasedContainer
, keeping messages with same properties in a singlehashmap
entry, likeBatchMessageKeyBasedContainer
.Rejection reason: This will publish messages out of order
The text was updated successfully, but these errors were encountered: