ksqlDB に関する問題のトラブルシューティング

このガイドには、 ksqlDB に関する多くの問題に対処するトラブルシューティングの情報を記載しています。

SELECT クエリが停止しない

ksqlDB ストリーミングクエリは、明示的に停止させる必要があります。CLI で、Ctrl + C を使用して非永続的なクエリ(SELECT * FROM myTable EMIT CHANGES など)を停止させます。CREATE STREAM AS SELECT または CREATE TABLE AS SELECT により作成された永続的なクエリを停止させるには、TERMINATE ステートメントの TERMINATE query_id; を使用します。詳細については、「TERMINATE」を参照してください。

SELECT クエリが結果を返さない

ksqlDB のクエリが結果を返さず CLI がハングする場合は、 Ctrl + C を使用してクエリを停止させた後、以下のトピックを確認して問題を診断します。

クエリが正しいソーストピックに基づくものであることを検証する

DESCRIBE EXTENDED ステートメントを使用して、ストリームの Apache Kafka® ソーストピックを表示します。たとえば pageviews という名前の Kafka のトピックに pageviews というストリームがある場合は、CLI で以下のステートメントを入力します。

DESCRIBE PAGEVIEWS EXTENDED;

出力例は、ソーストピックを示しています。

Name                 : PAGEVIEWS
[...]
Kafka topic          : pageviews (partitions: 1, replication: 1)

ソーストピックにデータが入力されていることを検証する

Kafka ソーストピックにデータが入力されていないためにクエリの結果が空である可能性があります。kcat を使用してメッセージを消費し、サマリーをプリントします。

docker run --network ksql-troubleshooting_default --tty --interactive --rm \
          confluentinc/cp-kafkacat \
          kafkacat -b kafka:39092 \
          -C -t pageviews \
          -o beginning

出力例は、空のソーストピックを示しています。

% Reached end of topic pageviews [0] at offset 0

ソーストピックに新しいメッセージが到着していることを検証する

kcat がメッセージをプリントすると、トピックに入力されます。ただし 新しい メッセージを受信していない可能性はあります。デフォルトでは、ksqlDB はトピックの末尾から読み取ります。トピックに新しいメッセージが書き込まれていなければ、クエリは結果を返しません。

クエリを確認するために、以下のステートメントを使用して auto.offset.reset プロパティに earliest を割り当て、ksqlDB がトピックの先頭から読み取るように設定できます。

SET 'auto.offset.reset'='earliest';

出力例は、正しく行われた変更を示しています。

Successfully changed local property 'auto.offset.reset' from 'null' to 'earliest'

もう一度クエリを実行します。トピックの先頭から結果が得られるはずです。なお、クエリが最新のオフセットに到達しても新しいメッセージが到着していなければ、クエリがハングしているように見えることがあります。クエリは、単に次のメッセージを待っているだけです。Ctrl + C を使用してクエリを停止します。

クエリの述語が限定的でありすぎないことを検証する

前述の方法で問題が解決されない場合、クエリの述語が限定的すぎるためにすべてのレコードが除外されている可能性があります。WHERE 句と HAVING 句を削除し、もう一度クエリを実行してください。

逆シリアル化エラーがないことを検証する

ksqlDB は、メッセージのデータを逆シリアル化できなければクエリの結果を書き込みません。DESCRIBE EXTENDED ステートメントを使用して、ストリームの VALUE_FORMAT が、kcat がトピックについてプリントしたレコードのフォーマットと一致していることを確認します。CLI で以下のステートメントを入力します。

DESCRIBE pageviews EXTENDED;

出力例:

Name                 : PAGEVIEWS
[...]
Value format         : DELIMITED

DELIMITED トピックに関する kcat の出力例は以下のとおりです。

1541463125587,User_2,Page_74
1541463125823,User_2,Page_92
1541463125931,User_3,Page_44
% Reached end of topic pageviews [0] at offset 1538
1541463126232,User_1,Page_28
% Reached end of topic pageviews [0] at offset 1539
1541463126637,User_7,Page_64
% Reached end of topic pageviews [0] at offset 1540
1541463126786,User_1,Page_83
^C

シリアル化エラーについては メッセージ処理の失敗を確認する を確認してください。たとえば、クエリで VALUE_FORMAT に対して JSON を指定している場合にベースのトピックが JSON フォーマットで生成されていなければ、ksqlDB サーバーログに JsonParseException という警告が出力されます。以下に例を示します。

[2018-09-17 12:29:09,929] WARN task [0_10] Skipping record due to deserialization error. topic=[_confluent-metrics] partition=[10] offset=[70] (org.apache.kafka.streams.processor.internals.RecordDeserializer:86)
 org.apache.kafka.common.errors.SerializationException: KsqlJsonDeserializer failed to deserialize data for topic: _confluent-metrics
 Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ((CTRL-CHAR, code 127)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')

ksqlDB CLI が ksqlDB サーバーに接続しない

CLI を起動すると以下の警告が表示される場合があります。

**************** WARNING ******************
Remote server address may not be valid:
Error issuing GET to KSQL server

Caused by: java.net.SocketException: Connection reset
Caused by: Connection reset
*******************************************

CLI を使用して ksqlDB クエリを作成する際にも同様のエラーが表示される場合があります。

Error issuing POST to KSQL server
Caused by: java.net.SocketException: Connection reset
Caused by: Connection reset

どちらの場合も CLI は ksqlDB サーバーに接続することができません。以下のトピックを確認して問題を診断します。

ksqlDB CLI が正しいポートを使用していること検証する

デフォルトでは、サーバーはポート 8088 をリッスンします。詳細については、 |ksqldb| CLI の起動 を参照してください。

ksqlDB サーバーの構成が正しいことを検証する

ksqlDB サーバーの構成ファイルで、リスナーのリストにあるホストアドレスとポートが正しく構成されていることを確認します。ファイル内で listeners の設定を検索し、正しく設定されていることを検証します。

listeners=http://0.0.0.0:8088

または IPv6 経由で実行している場合は以下を確認します。

listeners=http://[::]:8088

詳細については、ksqlDB サーバーの起動 を参照してください。

ポートの競合がないことを検証する

ksqlDB サーバーがリッスンしているポートで別のプロセスが実行されている場合があります。以下のコマンドを使用して、ksqlDB サーバーに割り当てられたポートで実行されているプロセスのプロセス ID(PID)を取得します。以下のコマンドでは、デフォルトの 8088 ポートを確認します。

netstat -anv | egrep -w .*8088.*LISTEN

出力例:

tcp4  0 0  *.8088       *.*    LISTEN      131072 131072    46314      0

この例では 46314 が、ポート 8088 上でリッスンしているプロセスの PID です。次のコマンドを実行してプロセス 46314 に関する情報を取得します。

ps -wwwp 46314

出力例:

io.confluent.ksql.rest.server.KsqlServerMain ./config/ksql-server.properties

KsqlServerMain プロセスが表示されていなければ、KsqlServerMain が通常使用するポートを別のプロセスが使用しています。ksqlDB サーバーの構成ファイルで listeners の設定を検索し、正しいポートを取得します。正しいポートを使用して CLI を起動します。

詳細については、 ksqlDB サーバーの起動 および ksqlDB CLI の起動 を参照してください。

ウィンドウ化された集約の出力からストリームを作成できない

ksqlDB は構造化キーをサポートしていないため、ウィンドウ化された集約からストリームを作成できません。

ksqlDB が内部トピックをクリーンアップしない

Kafka クラスターに対して delete.topic.enable=true が構成されていることを確認します。詳細については、「deleteTopics」を参照してください。

Avro スキーマで複製されたトピックによりエラーが発生する

Confluent Replicator は、レプリケーション時にトピックの名前を変更します。関連する Avro スキーマがある場合、レプリケーション完了後にAvro スキーマと名前変更されたトピックとの照合は自動では行われません。

複製されたトピックに対して PRINT ステートメントを使用すると、Avro スキーマ ID が Schema Registry 内に存在することがわかります。ksqlDB は Avro メッセージを逆シリアル化できますが、CREATE STREAM ステートメントは正しく動作せず、逆シリアル化エラーが発生します。以下に例を示します。

CREATE STREAM pageviews_original (viewtime bigint, userid varchar, pageid varchar) WITH (kafka_topic='pageviews.replica', value_format='AVRO');

逆シリアル化エラーの出力例は以下のとおりです。

[2018-06-21 19:12:08,135] WARN task [1_6] Skipping record due to deserialization error. topic=[pageviews.replica] partition=[6] offset=[1663] (org.apache.kafka.streams.processor.internals.RecordDeserializer:86)
org.apache.kafka.connect.errors.DataException: pageviews.replica
        at io.confluent.connect.avro.AvroConverter.toConnectData(AvroConverter.java:97)
        at io.confluent.ksql.serde.connect.KsqlConnectDeserializer.deserialize(KsqlConnectDeserializer.java:48)
        at io.confluent.ksql.serde.connect.KsqlConnectDeserializer.deserialize(KsqlConnectDeserializer.java:27)

これを解決するには、複製されたトピックのサブジェクト名に対して Avro スキーマを手動で登録します。以下に例を示します。

# Original topic name = pageviews
# Replicated topic name = pageviews.replica
curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" --data "{\"schema\": $(curl -s http://localhost:8081/subjects/pageviews-value/versions/latest | jq '.schema')}" http://localhost:8081/subjects/pageviews.replica-value/versions

Snappy でエンコードされたメッセージが展開されない

/tmp ディレクトリが noexec に設定されていて書き込みアクセス権限がない場合は、書き込みアクセス権限があるディレクトリパスを snappy へ渡す必要があります。

-Dorg.xerial.snappy.tempdir=/path/to/newtmp

メッセージ処理の失敗を確認する

ksqlDB クエリの正常性を確認することができます。確認は、処理したメッセージの数を表示し、処理失敗の発生回数をカウントすることにより行います。

DESCRIBE EXTENDED ステートメントを使用して total-messagesfailed-messages-per-sec を表示し、メッセージ処理のメトリクスを取得します。なおこのメトリクスは、DESCRIBE ステートメントを実行しているサーバーのみのメトリクスです。

DESCRIBE GOOD_RATINGS EXTENDED;

出力例:

[...]
Local runtime statistics
------------------------
messages-per-sec:      1.10 total-messages:     2898 last-message: 9/17/18 1:48:47 PM UTC
 failed-messages:         0 failed-messages-per-sec:         0 last-failed: n/a
(Statistics of the local KSQL server interaction with the Kafka topic GOOD_RATINGS)

failed-messages の数が増えている場合は、クエリに問題がある可能性があります。処理失敗の主な原因については、 逆シリアル化エラー を参照してください。

ksqlDB のサーバーログを確認する

デフォルトでは、ksqlDB は大半のログメッセージを stdout に書き込みます。

Confluent CLI を使用して ksqlDB サーバーログでエラーを確認します。それには以下のコマンドを使用します。

confluent local services ksql-server log

詳細については、「Confluent CLI」を参照してください。

デフォルトのディレクトリ /usr/local/logs または CLI 起動時に割り当てた LOG_DIR にあるログを確認します。詳細については、 ksqlDB CLI の起動 を参照してください。

RPM または Debian パッケージを使用して Confluent Platform をインストールしている場合は、/var/log/confluent/ にログがあります。

Docker を使用して ksqlDB を実行している場合は、コンテナーのログに出力があります。以下はその例です。

docker logs <container-id>
docker-compose logs ksql-server