[英]Pulsar function fails to deserialize message because of wrong schema type (JSON instead of AVRO)
當在 docker 中獨立運行 Pulsar 時,在特定情況下反序列化消息時,我們會面臨這個奇怪的問題。 我們使用的是 2.7.1 版。
我們有一個創建主題和函數的腳本,然后為 JSON 類型的麻煩主題創建模式。 整個模式是正確的,但類型不是。 這是發送任何消息之前的全部內容。 我們還啟用了set-is-allow-auto-update-schema
。
我們稱之為trouble-topic
,它由 2 個來源填充: ValidationFunction
和 Spring Boot 微服務。
ValidationFunction
驗證消息,如果消息有效,則將映射的消息發送到 Spring Boot 微服務使用的主題,然后在其上執行一些邏輯並將其發送到trouble-topic
,但如果驗證失敗,則直接向trouble-topic
發送消息trouble-topic
。
當使用 Spring Boot 微服務的sendAsync
和以下生產者時,模式會更新,將 AVRO 作為類型,並且TroubleFunction
讀取trouble-topic
之后工作正常:
pulsarClient
.newProducer(AvroSchema.of(OurClass.class))
.topic(troubleTopicName))
.create()
但是如果在此之前一些消息驗證失敗,並且在使用上述 Producer 之前將消息直接發送到trouble-topic
,我們會得到解析異常。 我們通過以下方式從函數發送消息:
context.newOutputMessage(troubleTopicName, AvroSchema.of(OurClass.class))
.value(value)
.sendAsync();
由於某種原因,這不會更新架構類型,並且架構類型仍然是 JSON。 我使用 pulsar admin CLI 驗證了每個步驟的模式類型。 當這種情況發生在微服務生產者第一次更新模式類型之前, TroubleFunction
讀取trouble-topic
失敗並出現以下錯誤:
11:43:49.322 [tenant/namespace/TroubleFunction-0] ERROR org.apache.pulsar.functions.instance.JavaInstanceRunnable - [tenant/namespace/TroubleFunction:0] Uncaught exception in Java Instance
org.apache.pulsar.client.api.SchemaSerializationException: com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 2)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (byte[])avro-serialized-msg-i-have-to-hide Parsing exception: cvc-complex-type.2.4.a: Invalid content was found starting with element 'ElementName'. One of '{"foo:bar":ElementName}' is expected."; line: 1, column: 2]
所以我的問題是這兩者之間有什么區別,為什么從函數發送消息沒有正確更新架構類型? 下面不是使用同一個Producer嗎? 還有沒有辦法解決這個問題,以便在初始化時設置模式類型或至少在從函數發送消息時更新?
首先,信用到期的信用。 我想有一天這會被很好地記錄下來,但現在不是。 我很幸運有一個 EAP 版本的 Apache Pulsar in Action 書,這個示例存儲庫用於展示一些 Pulsar 功能: https : //github.com/david-streamlio/GottaEat
我強烈推薦這本書,並為每個與 Pulsar 一起工作的人閱讀這些例子,在 pulsar slack 社區上有人提到它昨天剛從 MEAP 畢業,它應該很快就會有印刷版,所以看看吧。 也可以考慮加入 Pulsar slack。
回答:
這是一段代碼,讓我了解它應該如何工作:
Map<String, ConsumerConfig> inputSpecs = new HashMap<String, ConsumerConfig> ();
inputSpecs.put("persistent://orders/inbound/food-orders",
ConsumerConfig.builder().schemaType("avro").build());
FunctionConfig functionConfig =
FunctionConfig.builder()
...
.inputSpecs(inputSpecs)
...
.build();
使用LocalRunner時可以使用Java代碼來設置該功能,但使用pulsar admin cli(我們使用的)和rest api可以實現相同的配置。 您也可以使用函數配置文件,並在配置 yaml 中按以下方式指定它:
inputSpecs:
$topicName:
schemaType: AVRO
$topicName
始終采用以下格式: persistent://tenant/namespace/topic
一旦您為TroubleFunction
指定輸入規范,將使用正確的模式類型有效地創建模式,反序列化也將正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.