Skip to content

[Bug] parseMessageMetadata error when broker entry metadata enable with high loading #22601

Closed

Description

@semistone

Search before asking

  • I searched in the issues and found nothing similar.

Read release policy

  • I understand that unsupported versions don't get bug fixes. I will attempt to reproduce the issue on a supported version of Pulsar client and Pulsar broker.

Version

  • 3.2.2
  • 3.1.2

Minimal reproduce step

publish event in about 6k QPS and 100Mbits/sec
with metaData
BatcherBuilder.KEY_BASED mode
and producer and send message by high concurrent/parallel producer process.
it happens only in almost real time consumer (almost zero backlog)

What did you expect to see?

no lost event

What did you see instead?

could see error log in broker and show
Failed to peek sticky key from the message metadata

it look like thread safe issue, because it happen randomly.
in 1M events, it only happen few times but the consumer will lose few events

Anything else?

the error similar to
#10967 but I think it's different issue.

the data in bookkeeper is correct.
I can download the event from bookkeeper and parse it successfully.
or consume the same event few minutes later and it could consume successfully.
but all subscriptions will get the same error in the same event in real time consumer(zero backlog).

I have traced source code.
it happens in
PersistentDispatcherMultipleConsumers.readEntriesComplete -> AbstractBaseDispatcher.filterEntriesForConsumer
-> Commands.peekAndCopyMessageMetadata

and I also print the ByteBuf contents,
it's I could clearly see the data isn't the same in bookkeeper

in normal event , the hex code usually start by 010e (magicCrc32c)

0000000      010e    9529    5fbc    0000    0a03    3a0a    6e69    7267

in one of our error event, the bytebuf have about 48 bytes strange data, then continue with normal data

0000000      0000    a610    0000    0000    0200    7239    0000    0000 <== from here
     
0000020      0200    1339    0000    0000    ea17    a8b0    8b8e    fa5e
        
0000040      2af0    2675    f645    1623    d17e    dc34    526d    ef44 <=== until here is garbage
          
0000060      010e    9529    5fbc    0000    0a03    3a0a    6e69    7267 <== from here is normal data

this is just an example, but sometimes the first few bytes are correct and something wrong after few bytes later.

I am still trying to debug when and how the ByteBuf returns incorrect data, and why it only happens during stress testing. It is still not easy to reproduce using the perf tool, but we can 100% reproduce it in our producer code.

Does anyone have any idea what could be causing this issue, and any suggestions on which library or class may have potential issues? Additionally, any suggestions on how to debug this issue or if I need to print any specific information to help identify the root cause would be appreciated. Thank you.

Are you willing to submit a PR?

  • I'm willing to submit a PR!

Activity

  1. lhotari commented on Apr 26, 2024

    @lhotari
    Member

    @semistone Just wondering if this could be related to apache/bookkeeper#4196?
    There might are also other recent ByteBuf retain/release fixes such as #22393 .
    In Bookkeeper, there's apache/bookkeeper#4289 pending release and apache/bookkeeper#4293 is pending review.

  2. semistone commented on May 1, 2024

    @semistone
    Author

    we still try to compare what's the different between our producer and perf tool
    will feedback later once we have any conclusion.

  3. semistone commented on May 2, 2024

    @semistone
    Author

    @lhotari
    we do many tests
    current broker setting is

    maxMessageSize=5242880
    

    and producer setting (small batch message and big max bytes)

    batchingMaxMessages: 500
    batchingMaxBytes: 3145728
    batchingMaxPublishDelayMicros: 500
    

    payload
    98% < 3K bytes
    2% between 10-20K bytes

    then it will show that error and publish throughput isn't good.

    but if we change to

    batchingMaxMessages: 1000
    batchingMaxBytes: 3145728
    batchingMaxPublishDelayMicros: 1000
    

    and filter all data bigger than 15K bytes
    then that error disappear

    so we decide to create
    one batch publisher to publish data < 15000 bytes
    and one chunk publisher to publish data >= 15000 bytes
    then it worked and performance is also better than previous test

    we still don't known why
    but at least we have workaround solution now.

    I don't how which batch producer configuration could fix this errors.
    if you have any suggestions, we will still try it .

    and we also publish in multi thread programs,
    seems like it's not directly related to loading but related to payload size
    but maybe if the publish rate is low, it's more difficult to reproduce .

    we also tried to reproduce by perf tool but it didn't always happen.

    thanks

  4. semistone commented on May 8, 2024

    @semistone
    Author

    I tried to upgrade to bookkeeper 4.17.0
    but still have the same issue :(

    [pulsar@cockroach308 lib]$ ls |grep bookkeeper
    org.apache.bookkeeper-bookkeeper-benchmark-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-common-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-common-allocator-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-perf-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-proto-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-server-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-slogger-api-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-slogger-slf4j-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-tools-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-tools-framework-4.17.0.jar
    org.apache.bookkeeper-bookkeeper-tools-ledger-4.17.0.jar
    org.apache.bookkeeper-circe-checksum-4.17.0.jar
    org.apache.bookkeeper-cpu-affinity-4.17.0.jar
    org.apache.bookkeeper.http-http-server-4.17.0.jar
    org.apache.bookkeeper.http-vertx-http-server-4.17.0.jar
    org.apache.bookkeeper-native-io-4.17.0.jar
    org.apache.bookkeeper-statelib-4.17.0.jar
    org.apache.bookkeeper.stats-bookkeeper-stats-api-4.17.0.jar
    org.apache.bookkeeper.stats-codahale-metrics-provider-4.17.0.jar
    org.apache.bookkeeper.stats-otel-metrics-provider-4.17.0.jar
    org.apache.bookkeeper.stats-prometheus-metrics-provider-4.17.0.jar
    org.apache.bookkeeper-stream-storage-cli-4.17.0.jar
    org.apache.bookkeeper-stream-storage-java-client-4.17.0.jar
    org.apache.bookkeeper-stream-storage-server-4.17.0.jar
    org.apache.bookkeeper-stream-storage-service-api-4.17.0.jar
    org.apache.bookkeeper-stream-storage-service-impl-4.17.0.jar
    org.apache.bookkeeper.tests-stream-storage-tests-common-4.17.0.jar
    org.apache.pulsar-pulsar-package-bookkeeper-storage-3.2.2.jar
    
  5. lhotari commented on May 8, 2024

    @lhotari
    Member

    we also tried to reproduce by perf tool but it didn't always happen.

    @semistone Please share a way how to reproduce it. It's not a problem if it's not always consistent. Fixing this issue will be a lot easier if there's at least some way to reproduce.

  6. lhotari commented on May 8, 2024

    @lhotari
    Member

    I tried to upgrade to bookkeeper 4.17.0
    but still have the same issue :(

    @semistone Thanks for testing this.

  7. semistone commented on May 8, 2024

    @semistone
    Author

    we also tried to reproduce by perf tool but it didn't always happen.

    @semistone Please share a way how to reproduce it. It's not a problem if it's not always consistent. Fixing this issue will be a lot easier if there's at least some way to reproduce.

    I will try to reproduce in perf tool.

  8. lhotari commented on May 8, 2024

    @lhotari
    Member

    @semistone since you have some way to reproduce this in your own tests, would you be able to test if this can be reproduced with dispatcherDispatchMessagesInSubscriptionThread=false?

    pulsar/conf/broker.conf

    Lines 435 to 436 in 80d4675

    # Dispatch messages and execute broker side filters in a per-subscription thread
    dispatcherDispatchMessagesInSubscriptionThread=true

    It impacts this code:

    // dispatch messages to a separate thread, but still in order for this subscription
    // sendMessagesToConsumers is responsible for running broker-side filters
    // that may be quite expensive
    if (serviceConfig.isDispatcherDispatchMessagesInSubscriptionThread()) {
    // setting sendInProgress here, because sendMessagesToConsumers will be executed
    // in a separate thread, and we want to prevent more reads
    acquireSendInProgress();
    dispatchMessagesThread.execute(() -> {
    if (sendMessagesToConsumers(readType, entries, false)) {
    updatePendingBytesToDispatch(-size);
    readMoreEntries();
    } else {
    updatePendingBytesToDispatch(-size);
    }
    });
    } else {
    if (sendMessagesToConsumers(readType, entries, true)) {
    updatePendingBytesToDispatch(-size);
    readMoreEntriesAsync();
    } else {
    updatePendingBytesToDispatch(-size);
    }
    }

  9. semistone commented on May 8, 2024

    @semistone
    Author

    I almost could reproduce by perf tool
    when very few payload > 30K bytes. others are 3K bytes
    then
    error happen when messageKeyGenerationMode=random
    if without messageKeyGenerationMode, then error disappear

    I guess in batch mode, payload size have some restriction.

    let me confirm again tomorrow to make sure I didn't make any stupid mistake during my test.

  10. semistone commented on May 9, 2024

    @semistone
    Author

    Hi @lhotari
    I update perf tool in
    https://github.com/semistone/pulsar/tree/debug_ssues_22601

    it only include one commit which modify PerformanceProducer.java to include
    big payload ( -bp 5 means 5 percent big payload)
    and BatcherBuilder.KEY_BASED (-kb)

    my consumer command is

    bin/pulsar-perf  consume persistent://my-tenant/my-namespace/my-topic-1   --auth-plugin org.apache.pulsar.client.impl.auth.AuthenticationTls --auth-params '{"tlsCertFile":"conf/superuser.cer","tlsKeyFile":"conf/superuser.key.pem"}' -n 10 -sp Latest -ss angus_test --batch-index-ack   -st Key_Shared 
    

    and producer command is

    bin/pulsar-perf produce persistent://my-tenant/my-namespace/my-topic-1 -r 6000 -kb -s 2000 -bp 5  -bm 1000  -b 1 -mk random  --auth-plugin org.apache.pulsar.client.impl.auth.AuthenticationTls --auth-params '{"tlsCertFile":"conf/superuser.cer","tlsKeyFile":"conf/superuser.key.pem"}' 
    

    that error happen when

    Batch builder is KEY_BASE
    with random event key
    and few big payload (in my environment 3% could reproduce 10% will crash producer)

    in my test
    I use normal payload 2K bytes , big payload 20K bytes
    if I removed any above conditions, that error will either reduced or disappear.

    when it happen it will have WARN message in pulsar-broker.log

    2024-05-09T01:12:35,246+0000 [pulsar-io-3-31] WARN  org.apache.pulsar.broker.service.ServerCnx - [/100.96.184.253:39710] Got exception java.lang.IllegalArgumentException: Invalid unknonwn tag type: 6
    or 
    2024-05-09T01:12:35,260+0000 [broker-topic-workers-OrderedExecutor-15-0] ERROR org.apache.pulsar.common.protocol.Commands - [persistent://budas/budas-preprod-internal/bud_stream_input-partition-1] [angus_test] Failed to peek sticky key from the message metadata
    java.lang.IllegalArgumentException: Invalid unknonwn tag type: 4
    

    unfortunately I can't preproduce in docker, I guess docker standalone is different from my pulsar cluster.
    my pulsar cluster is
    almost default config but with TLS auth in broker/bookkeeper/zookeeper.

    Please help to check it, if have any problem to reproduce this issue in your environment,
    then I will try to simplify my pulsar cluster to reproduce it.

    Thanks

  11. semistone commented on May 9, 2024

    @semistone
    Author

    @semistone since you have some way to reproduce this in your own tests, would you be able to test if this can be reproduced with dispatcherDispatchMessagesInSubscriptionThread=false?

    I tested, still the same

  12. lhotari commented on May 9, 2024

    @lhotari
    Member

    @semistone since you have some way to reproduce this in your own tests, would you be able to test if this can be reproduced with dispatcherDispatchMessagesInSubscriptionThread=false?

    I tested, still the same

    @semistone Thanks for testing. That tells that it's not related to switching the thread in

    // dispatch messages to a separate thread, but still in order for this subscription
    // sendMessagesToConsumers is responsible for running broker-side filters
    // that may be quite expensive
    if (serviceConfig.isDispatcherDispatchMessagesInSubscriptionThread()) {
    // setting sendInProgress here, because sendMessagesToConsumers will be executed
    // in a separate thread, and we want to prevent more reads
    acquireSendInProgress();
    dispatchMessagesThread.execute(() -> {
    if (sendMessagesToConsumers(readType, entries, false)) {
    updatePendingBytesToDispatch(-size);
    readMoreEntries();
    } else {
    updatePendingBytesToDispatch(-size);
    }
    });
    } else {
    if (sendMessagesToConsumers(readType, entries, true)) {
    updatePendingBytesToDispatch(-size);
    readMoreEntriesAsync();
    } else {
    updatePendingBytesToDispatch(-size);
    }
    }
    .

  13. semistone commented on May 17, 2024

    @semistone
    Author

    @lhotari
    I am checking when that byteBuf went wrong
    and in
    OpAddEntry.java
    I verify data when construct this object and save original data

    and during run(), I try to compare and print bytebuf

            if (ml.hasActiveCursors()) {
                // Avoid caching entries if no cursor has been created
                EntryImpl entry = EntryImpl.create(ledgerId, entryId, data);
                // ======= print log when data go wrong
                if (!Commands.hasChecksum(data)) {  
                    log.warn("no checksum in OpAddEntry1 origin {} data  {}, now {} data {}", dataString,
                            new String(Base64.encodeBase64(orgData))
                            , data.toString(), new String(Base64.encodeBase64(entry.getData())));
                }
    

    it show

    2024-05-17T07:29:16,476+0000 [BookKeeperClientWorker-OrderedExecutor-12-0] WARN  org.apache.bookkeeper.mledger.impl.OpAddEntry - no checksum in OpAddEntry1 
    origin PooledSlicedByteBuf(ridx: 13, widx: 2066, cap: 2066/2066, unwrapped: PooledUnsafeDirectByteBuf(ridx: 24211, widx: 24211, cap: 32768)) 
    
    data  DgEJYVBqAAAAKwoMaHlicmlkLTQ0MC0wEI8cGPTz0av4MTILLTEyMDM1NzAyOTNI0A+IAQAxMjM0NTY3ODkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwO... skip
    
    ,now PooledSlicedByteBuf(ridx: 13, widx: 2066, cap: 2066/2066, unwrapped: PooledUnsafeDirectByteBuf(ridx: 24211, widx: 24211, cap: 32768)) 
    
    data MzY5NDY5NTY5NjY5NzY5ODY5OTcwMDcwMTcwMjcw0av4MTILLTEyMDM1NzAyOTNI0A+IAQAxMjM0NTY3ODkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OT
    ... skip 
    

    the bytebuf object haven't changed, but the data in bytebuf have changed.
    it seem like the first few bytes(about 20) will be overwrited and rest of the data is still ok

    and it's PooledSlicedByteBuf and PooledUnsafeDirectByteBuf

    do you have any idea how to find who change the data inside bytebuf ?

  14. semistone commented on May 17, 2024

    @semistone
    Author

    I also test again
    if publish payload always 20K, it won't happen
    only happen when normal is 2K but some data bigger than 16K( sound like netty receive buffer size but I also try to increase it)
    and about 1000 qps

    I also checked the data again
    the wrong data look exactly like been overwrited by tail of previous payload

    and it not related to batch mode
    it happened when disable batch mode

  15. 43 remaining items

  16. lhotari commented on May 27, 2024

    @lhotari
    Member

    I can confirm that this issue reproduces with https://github.com/lhotari/pulsar-playground/tree/master/issues/issue22601/standalone_env / https://github.com/semistone/personal_notes/blob/main/pulsar_issue_22601/Test.md also with Netty 4.1.111.Final-SNAPSHOP and Bookkeeper 4.16.6-SNAPSHOT (with PR 4293 included). This is a different issue than what I reproduced in my microk8s based repro.

  17. lhotari commented on May 27, 2024

    @lhotari
    Member

    @semistone Your problem is caused by invalid TLS configuration. When TLS is enabled between Broker and Bookkeeper, you must set bookkeeperUseV2WireProtocol=false in broker.conf. In the autorecovery process, it is necessary to set useV2WireProtocol=false in bookkeeper.conf, if there's TLS enabled for autorecovery.
    It's possible that there's isn't much documentation to assist with this.

  18. lhotari commented on May 27, 2024

    @lhotari
    Member

    I found apache/bookkeeper#2071 and apache/bookkeeper#2085 which seem to indicate that running with bookkeeperUseV2WireProtocol=true is supported. However, I don't think that it has ever been stable when TLS is enabled between broker and bookkeeper. In the Apache Pulsar Helm chart, the chart will set bookkeeperUseV2WireProtocol=false when TLS is enabled between broker and bookkeeper.
    https://github.com/apache/pulsar-helm-chart/blob/3ecc2baab809389ede5e53f4ecf518fab0f13dad/charts/pulsar/templates/broker-configmap.yaml#L180-L196

  19. lhotari commented on May 27, 2024

    @lhotari
    Member

    Previous comment about bookkeeperUseV2WireProtocol #21421 (comment)

  20. lhotari commented on May 27, 2024

    @lhotari
    Member

    It looks like there's a feature that enables V3 protocol using a separate client when V2 is configured: apache/bookkeeper#2085 . As mentioned in the previous comments, I don't think that this has ever been proven to be stable when TLS is enabled.

  21. semistone commented on May 28, 2024

    @semistone
    Author

    @lhotari
    Thanks to point out that config issue
    I tested and verified it worked.

    also talk about our release history.

    actually we have notice that issue #21421 during our pre release load test and since that error logs have ledger id and entry id
    and it happens about 4 times during about 10M events.
    so we could still recover the data from bookkeeper manually or by auto fix tool.
    and we have about 10 consumers, only 1 consumer is too slow to consume data from bookkeeper
    so only one consumer been impacted and we could still wait bookkeeper side to fix that issue.
    and after upgrading bookkeeper version, it seems improved.

    but this error, the data in bookkeeper is correct. that why at beginning we didn't aware it's bookkeeper client issue
    it only happened about 10 times in 1M events if relative higher QPS.
    and there is no ledger/entry id in error logs.
    so it's impossible for us to fix the data.
    and it mainly impact real time consumer
    so we don't have choice but rollback our release.


    so I will use that settings in our broker setting
    and I will suggest to print ledger/entry id in case of that happen again (I could create PR if it's ok)
    then at least user could still re publish the data from bookkeeper.

    and I think it still need to report to bookkeeper team.
    seems those issues are already closed, I will create issue in bookkeeper tomorrow if there is no existed ticket to trace this issue.
    I will try to understand bookkeeper's code if I have time :)

    I already debug this issue for one month.
    Thanks for helping us.

  22. lhotari commented on May 28, 2024

    @lhotari
    Member

    Thanks to point out that config issue
    I tested and verified it worked.

    @semistone It seems that V2 should be supported also when using TLS. The downside of using V3 is that it's not very efficient and will add a lot of GC overhead. However some bug gets triggered and that's the reason why V3 is more stable when TLS is enabled between brokers and bookies.

    I was reviewing code for reference count bugs in Pulsar and I did find an issue in RangeCache (the broker cache implementation). I'll follow up with a PR to fix the issue soon. It's not related to the bookkeeper protocol version at all.

  23. lhotari commented on May 28, 2024

    @lhotari
    Member

    RangeCache race condition fix: #22789

  24. lhotari commented on May 28, 2024

    @lhotari
    Member

    I have made a fix to bookkeeper which fixes the issue: apache/bookkeeper#4404 .

    I tested with Pulsar 3.2.3 with bookkeeper.version set to 4.16.6-SNAPSHOT. Before compiling that locally, I compiled Bookkeeper branch-4.16 with PR 4404 changes included (branch-4.16 backport available at https://github.com/lhotari/bookkeeper/commits/lh-fix-tls-stability-with-V2-branch-4.16/).

    Compiling Bookkeeper 4.16.6-SNAPSHOT locally with apache/bookkeeper#4404 changes.

    git clone -b lh-fix-tls-stability-with-V2-branch-4.16 https://github.com/lhotari/bookkeeper
    cd bookkeeper
    mvn clean install -DskipTests
    

    Compiling local Pulsar v3.2.3 with Bookkeeper 4.16.6-SNAPSHOT (passing -Dbookkeeper.version=4.16.6-SNAPSHOT to maven build)

    git clone https://github.com/apache/pulsar
    cd pulsar
    git checkout v3.2.3
    mvn -Pcore-modules,-main clean install -Dbookkeeper.version=4.16.6-SNAPSHOT -DskipTests -Dspotbugs.skip=true -Dcheckstyle.skip=true
    # this is where the distribution is:
    cp distribution/server/target/apache-pulsar-3.2.3-bin.tar.gz ~
    
  25. semistone commented on May 29, 2024

    @semistone
    Author

    @lhotari
    I tested in standalone server. and it's all good.
    here is my test report
    https://github.com/semistone/personal_notes/blob/main/pulsar_issue_22601/20240528Test.md

    I will deploy to our cluster and test again few days later.

  26. semistone commented on Jun 3, 2024

    @semistone
    Author

    @lhotari
    I had tested
    pulsar 3.2.3 + bookkeeper 4.16.6-SNAPSHOT.jar + netty buffer 4.1.111.Final-SNAPSHOT

    and I think this issue had been fixed.
    I will test more scenario
    Thanks.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugThe PR fixed a bug or issue reported a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions