このトピックでは、ApsaraMQ for RocketMQ コネクタについて説明します。
ApsaraMQ for RocketMQ 4.x の Standard Edition インスタンスでは、API 呼び出しの上限が毎秒 5,000 回に設定されています。インスタンスを Realtime Compute for Apache Flink に接続する際にこの上限を超えると、速度制限がトリガーされ、Flink ジョブが不安定になる可能性があります。そのため、Standard Edition の RocketMQ インスタンスを使用して Flink と統合する場合、またはその予定がある場合は、潜在的な影響を慎重に評価してください。可能であれば、Kafka、Simple Log Service (SLS)、DataHub などの代替メッセージングミドルウェアの使用をご検討ください。大量のメッセージを処理するために ApsaraMQ for RocketMQ 4.x の Standard Edition インスタンスを使用する必要がある場合は、チケットを送信して、より高い速度制限クォータをリクエストしてください。
背景情報
ApsaraMQ for RocketMQ は、Alibaba Cloud が Apache RocketMQ をベースに開発した分散メッセージングミドルウェアです。低遅延、高い同時実行性、高可用性、高信頼性を提供します。ApsaraMQ for RocketMQ は、分散アプリケーションシステムの非同期デカップリングとピークシェービングを実現します。また、大量のメッセージ蓄積、高スループット、信頼性の高いリトライなど、インターネットアプリケーション向けの機能も提供します。
次の表に、ApsaraMQ for RocketMQ コネクタの詳細を説明します。
|
項目 |
説明 |
|
サポートされる型 |
ソーステーブルと結果テーブル |
|
実行モード |
ストリーミングモードのみ |
|
データフォーマット |
CSV 形式とバイナリ形式 |
|
コネクタ固有のメトリック |
|
|
API タイプ |
DataStream API (RocketMQ 4.x のみ) と SQL API |
|
結果テーブルでのデータの更新または削除のサポート |
結果テーブルへのデータ挿入のみがサポートされています。更新と削除はサポートされていません。 |
特徴
ApsaraMQ for RocketMQ のソーステーブルと結果テーブルは、次のメタデータフィールドをサポートしています。
-
ソーステーブルのフィールド
フィールド
型
説明
topic
VARCHAR METADATA VIRTUAL
メッセージトピック。
queue-id
INT METADATA VIRTUAL
キュー ID。
queue-offset
BIGINT METADATA VIRTUAL
消費オフセット。
msg-id
VARCHAR METADATA VIRTUAL
メッセージ ID。
store-timestamp
TIMESTAMP(3) METADATA VIRTUAL
メッセージストレージのタイムスタンプ。
born-timestamp
TIMESTAMP(3) METADATA VIRTUAL
メッセージ生成のタイムスタンプ。
keys
VARCHAR METADATA VIRTUAL
メッセージキー。
tags
VARCHAR METADATA VIRTUAL
メッセージタグ。
-
結果テーブルのフィールド
フィールド
型
説明
keys
VARCHAR METADATA
メッセージキー。
tags
VARCHAR METADATA
メッセージタグ。
前提条件
Message Queue for Apache RocketMQ リソースを作成済みであること。手順については、「リソースの作成」をご参照ください。
制限事項
-
ApsaraMQ for RocketMQ 5.x を使用するには、Flink リアルタイム計算エンジン VVR 8.0.3 以降が必要です。
-
ApsaraMQ for RocketMQ コネクタはプルコンシューマーを使用し、すべてのサブタスクにワークロードを分散します。
構文
CREATE TABLE mq_source(
x varchar,
y varchar,
z varchar
) WITH (
'connector' = 'mq5',
'topic' = '<yourTopicName>',
'endpoint' = '<yourEndpoint>',
'consumerGroup' = '<yourConsumerGroup>'
);
WITH パラメーター
一般
|
パラメーター |
説明 |
型 |
必須 |
デフォルト |
備考 |
|
connector |
コネクタタイプ。 |
String |
はい |
なし |
|
|
endPoint |
サービスエンドポイント。 |
String |
はい |
なし |
ApsaraMQ for RocketMQ は 2 種類のエンドポイントを提供します:
重要
VPC エンドポイントの使用を推奨します。パブリックネットワーク接続は、Alibaba Cloud のネットワークセキュリティポリシーの動的な変更により不安定になる可能性があります。
|
|
topic |
トピック名。 |
String |
はい |
なし |
なし |
|
accessId |
|
String |
|
なし |
重要
AccessKey ペアの漏洩を防ぐため、プロジェクト変数を使用して AccessKey ID と AccessKey Secret を指定することを推奨します。
|
|
accessKey |
|
String |
|
なし |
|
|
tag |
サブスクライブまたは書き込みを行うメッセージタグ。 |
String |
いいえ |
なし |
説明
結果テーブルとして使用する場合、このパラメーターは RocketMQ 4.x でのみサポートされます。RocketMQ 5.x の場合は、結果テーブルのメタデータフィールドでメッセージタグを指定します。 |
|
encoding |
エンコード形式。 |
String |
いいえ |
UTF-8 |
なし |
|
instanceID |
Alibaba Cloud Message Queue for Apache RocketMQ インスタンスの ID。 |
String |
いいえ |
なし |
説明
このパラメーターは RocketMQ 4.x でのみサポートされます。 |
ソース固有
|
パラメーター |
説明 |
型 |
必須 |
デフォルト |
備考 |
|
consumerGroup |
コンシューマーグループの名前。 |
String |
はい |
なし |
なし |
|
pullIntervalMs |
データがない場合にソースがポーリングする間隔 (ミリ秒)。 |
Int |
はい |
なし |
単位:ミリ秒。 速度制限メカニズムは利用できません。RocketMQ からデータを読み取るレートは設定できません。 説明
このパラメーターは RocketMQ 4.x でのみサポートされます。 |
|
timeZone |
タイムゾーン。 |
String |
いいえ |
なし |
例:Asia/Shanghai。 |
|
startTimeMs |
データ消費の開始時刻。 |
Long |
いいえ |
なし |
ミリ秒単位のタイムスタンプ。 |
|
startMessageOffset |
消費を開始するメッセージオフセット。 |
Int |
いいえ |
なし |
このパラメーターが指定されている場合、データのロードは |
|
lineDelimiter |
レコードの解析に使用される行区切り文字。 |
String |
いいえ |
\n |
なし |
|
fieldDelimiter |
フィールド区切り文字。 |
String |
いいえ |
\u0001 |
区切り文字はターミナルモードによって異なります:
|
|
lengthCheck |
各レコードのフィールド数を確認するポリシー。 |
String |
いいえ |
NONE |
有効な値:
|
|
columnErrorDebug |
列解析エラーのデバッグモードを有効にするかどうかを指定します。 |
Boolean |
いいえ |
false |
true に設定すると、解析例外の詳細なログが出力されます。 |
|
pullBatchSize |
1 回のバッチでプルするメッセージの最大数。 |
Int |
いいえ |
64 |
VVR 8.0.7 以降のバージョンでサポートされています。 |
シンク固有
|
パラメーター |
説明 |
型 |
必須 |
デフォルト |
備考 |
|
producerGroup |
プロデューサーグループの名前。 |
String |
はい |
なし |
なし |
|
retryTimes |
失敗した書き込み操作をリトライする回数。 |
Int |
いいえ |
10 |
なし |
|
sleepTimeMs |
リトライ間隔 (ミリ秒)。 |
Long |
いいえ |
5000 |
なし |
|
partitionField |
パーティションキーとして使用するフィールドの名前。 |
String |
いいえ |
なし |
説明
VVR 8.0.5 以降のバージョンでサポートされています。 |
|
deliveryTimestampMode |
遅延メッセージの配信モード。このパラメーターは |
String |
いいえ |
なし |
有効な値:
説明
VVR 11.1 以降のバージョンでサポートされています。 |
|
deliveryTimestampType |
遅延メッセージの時間参照タイプ。 |
String |
いいえ |
processing_time |
有効な値:
説明
VVR 11.1 以降のバージョンでサポートされています。 |
|
deliveryTimestampValue |
遅延メッセージの配信時間。 |
Long |
いいえ |
なし |
このパラメーターの意味は
説明
VVR 11.1 以降のバージョンでサポートされています。 |
|
deliveryTimestampField |
遅延メッセージの配信時間として使用されるフィールドを指定します。データ型は |
String |
いいえ |
なし |
説明
VVR 11.1 以降のバージョンでサポートされています。 |
型マッピング
|
Flink 型 |
RocketMQ 型 |
|
BOOLEAN |
STRING |
|
VARBINARY |
|
|
VARCHAR |
|
|
TINYINT |
|
|
INTEGER |
|
|
BIGINT |
|
|
FLOAT |
|
|
DOUBLE |
|
|
DECIMAL |
例
ソーステーブルの例
-
CSV 形式
あるメッセージに、次の CSV 形式のデータレコードが含まれているとします。
1,name,male 2,name,female説明Message Queue for Apache RocketMQ のメッセージには、
\nで区切られた 0 個以上のデータレコードを含めることができます。Flink ジョブで次の DDL を使用して、Message Queue for Apache RocketMQ ソーステーブルを宣言します。
-
RocketMQ 5.x
CREATE TABLE mq_source( id varchar, name varchar, gender varchar, topic varchar metadata virtual ) WITH ( 'connector' = 'mq5', 'topic' = 'mq-test', 'endpoint' = '<yourEndpoint>', 'consumerGroup' = 'mq-group', 'fieldDelimiter' = ',' );-
RocketMQ 4.x
CREATE TABLE mq_source( id varchar, name varchar, gender varchar, topic varchar metadata virtual ) WITH ( 'connector' = 'mq', 'topic' = 'mq-test', 'endpoint' = '<yourEndpoint>', 'pullIntervalMs' = '1000', 'accessId' = '${secret_values.ak_id}', 'accessKey' = '${secret_values.ak_secret}', 'consumerGroup' = 'mq-group', 'fieldDelimiter' = ',' ); -
-
バイナリ形式
-
RocketMQ 5.x
CREATE TEMPORARY TABLE source_table ( mess varbinary ) WITH ( 'connector' = 'mq5', 'endpoint' = '<yourEndpoint>', 'topic' = 'mq-test', 'consumerGroup' = 'mq-group' ); CREATE TEMPORARY TABLE out_table ( commodity varchar ) WITH ( 'connector' = 'print' ); INSERT INTO out_table select cast(mess as varchar) FROM source_table; -
RocketMQ 4.x
CREATE TEMPORARY TABLE source_table ( mess varbinary ) WITH ( 'connector' = 'mq', 'endpoint' = '<yourEndpoint>', 'pullIntervalMs' = '500', 'accessId' = '${secret_values.ak_id}', 'accessKey' = '${secret_values.ak_secret}', 'topic' = 'mq-test', 'consumerGroup' = 'mq-group' ); CREATE TEMPORARY TABLE out_table ( commodity varchar ) WITH ( 'connector' = 'print' ); INSERT INTO out_table select cast(mess as varchar) FROM source_table;
-
結果テーブルの例
-
結果テーブルの作成
-
RocketMQ 5.x
CREATE TABLE mq_sink ( id INTEGER, len BIGINT, content VARCHAR ) WITH ( 'connector'='mq5', 'endpoint'='<yourEndpoint>', 'topic'='<yourTopicName>', 'producerGroup'='<yourGroupName>' ); -
RocketMQ 4.x
CREATE TABLE mq_sink ( id INTEGER, len BIGINT, content VARCHAR ) WITH ( 'connector'='mq', 'endpoint'='<yourEndpoint>', 'accessId'='${secret_values.ak_id}', 'accessKey'='${secret_values.ak_secret}', 'topic'='<yourTopicName>', 'producerGroup'='<yourGroupName>' );説明バイナリ形式の RocketMQ メッセージの場合、DDL は VARBINARY データ型の単一フィールドを定義する必要があります。
-
-
keysおよびtagsメタデータフィールドをメッセージのキーとタグにマップする結果テーブルを作成します-
RocketMQ 5.x
CREATE TABLE mq_sink ( id INTEGER, len BIGINT, content VARCHAR, keys VARCHAR METADATA, tags VARCHAR METADATA ) WITH ( 'connector'='mq5', 'endpoint'='<yourEndpoint>', 'topic'='<yourTopicName>', 'producerGroup'='<yourGroupName>' ); -
RocketMQ 4.x
CREATE TABLE mq_sink ( id INTEGER, len BIGINT, content VARCHAR, keys VARCHAR METADATA, tags VARCHAR METADATA ) WITH ( 'connector'='mq', 'endpoint'='<yourEndpoint>', 'accessId'='${secret_values.ak_id}', 'accessKey'='${secret_values.ak_secret}', 'topic'='<yourTopicName>', 'producerGroup'='<yourGroupName>' );
-
DataStream API
DataStream API を使用してデータの読み取りおよび書き込みを行うには、対応する DataStream コネクタを使用して Realtime Compute for Apache Flink に接続します。詳細については、「DataStream コネクタを統合する」をご参照ください。
VVR は、RocketMQ から読み取るための MetaQSource と、RocketMQ に書き込むための OutputFormat の実装である MetaQOutputFormat を提供します。次の例は、RocketMQ からの読み取りと書き込みの方法を示しています:
RocketMQ 5.x
ApsaraMQ for RocketMQ 5.x では、AccessKey ペアはインスタンスのユーザー名とパスワードを表します。内部ネットワーク経由でインスタンスにアクセスし、ACL 認証が無効になっている場合は、このペアを設定する必要はありません。
import com.alibaba.ververica.connectors.common.sink.OutputFormatSinkFunction;
import com.alibaba.ververica.connectors.mq5.shaded.org.apache.rocketmq.common.message.MessageExt;
import com.alibaba.ververica.connectors.mq5.sink.RocketMQOutputFormat;
import com.alibaba.ververica.connectors.mq5.source.RocketMQSource;
import com.alibaba.ververica.connectors.mq5.source.reader.deserializer.RocketMQRecordDeserializationSchema;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
import java.util.Collections;
import java.util.List;
/**
* ApsaraMQ for RocketMQ へのメッセージの消費、変換、および生成方法を示すデモです。
*/
public class RocketMQ5DataStreamDemo {
public static final String ENDPOINT = "<yourEndpoint>";
public static final String ACCESS_ID = "<accessID>";
public static final String ACCESS_KEY = "<accessKey>";
public static final String SOURCE_TOPIC = "<sourceTopicName>";
public static final String CONSUMER_GROUP = "<consumerGroup>";
public static final String SINK_TOPIC = "<sinkTopicName>";
public static final String PRODUCER_GROUP = "<producerGroup>";
public static void main(String[] args) throws Exception {
// ストリーミング実行環境を設定します
Configuration conf = new Configuration();
// 次の 2 つの設定はローカルデバッグ専用です。ジョブをパッケージ化して Realtime Compute for Apache Flink にアップロードする前に削除してください。
conf.setString("pipeline.classpaths", "file://" + "The absolute path of the uber JAR");
conf.setString(
"classloader.parent-first-patterns.additional",
"com.alibaba.ververica.connectors.mq5.source.reader.deserializer.RocketMQRecordDeserializationSchema;com.alibaba.ververica.connectors.mq5.shaded.");
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(conf);
final DataStreamSource<String> ds =
env.fromSource(
RocketMQSource.<String>builder()
.setEndpoint(ENDPOINT)
.setAccessId(ACCESS_ID)
.setAccessKey(ACCESS_KEY)
.setTopic(SOURCE_TOPIC)
.setConsumerGroup(CONSUMER_GROUP)
.setDeserializationSchema(new MyDeserializer())
.setStartOffset(1)
.build(),
WatermarkStrategy.noWatermarks(),
"source");
ds.map(new ToMessage())
.addSink(
new OutputFormatSinkFunction<>(
new RocketMQOutputFormat.Builder()
.setEndpoint(ENDPOINT)
.setAccessId(ACCESS_ID)
.setAccessKey(ACCESS_KEY)
.setTopicName(SINK_TOPIC)
.setProducerGroup(PRODUCER_GROUP)
.build()));
env.execute();
}
private static class MyDeserializer implements RocketMQRecordDeserializationSchema<String> {
@Override
public void deserialize(List<MessageExt> record, Collector<String> out) {
for (MessageExt messageExt : record) {
out.collect(new String(messageExt.getBody()));
}
}
@Override
public TypeInformation<String> getProducedType() {
return Types.STRING;
}
}
private static class ToMessage implements MapFunction<String, List<MessageExt>> {
public ToMessage() {
}
@Override
public List<MessageExt> map(String s) {
final MessageExt message = new MessageExt();
message.setBody(s.getBytes());
message.setWaitStoreMsgOK(true);
return Collections.singletonList(message);
}
}
}
RocketMQ 4.x
import com.alibaba.ververica.connector.mq.shaded.com.alibaba.rocketmq.common.message.MessageExt;
import com.alibaba.ververica.connectors.common.sink.OutputFormatSinkFunction;
import com.alibaba.ververica.connectors.metaq.sink.MetaQOutputFormat;
import com.alibaba.ververica.connectors.metaq.source.MetaQSource;
import com.alibaba.ververica.connectors.metaq.source.reader.deserializer.MetaQRecordDeserializationSchema;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.connector.source.Boundedness;
import org.apache.flink.api.java.typeutils.ListTypeInfo;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import static com.alibaba.ververica.connector.mq.shaded.com.taobao.metaq.client.ExternConst.*;
/**
* ApsaraMQ for RocketMQ へのメッセージの消費、変換、および生成方法を示すデモです。
*/
public class RocketMQDataStreamDemo {
public static final String ENDPOINT = "<yourEndpoint>";
public static final String ACCESS_ID = "<accessID>";
public static final String ACCESS_KEY = "<accessKey>";
public static final String INSTANCE_ID = "<instanceID>";
public static final String SOURCE_TOPIC = "<sourceTopicName>";
public static final String CONSUMER_GROUP = "<consumerGroup>";
public static final String SINK_TOPIC = "<sinkTopicName>";
public static final String PRODUCER_GROUP = "<producerGroup>";
public static void main(String[] args) throws Exception {
// ストリーミング実行環境を設定します
Configuration conf = new Configuration();
// 次の 2 つの設定はローカルデバッグ専用です。ジョブをパッケージ化して Realtime Compute for Apache Flink にアップロードする前に削除してください。
conf.setString("pipeline.classpaths", "file://" + "The absolute path of the uber JAR");
conf.setString("classloader.parent-first-patterns.additional",
"com.alibaba.ververica.connectors.metaq.source.reader.deserializer.MetaQRecordDeserializationSchema;com.alibaba.ververica.connector.mq.shaded.");
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(conf);
// ApsaraMQ for RocketMQ ソースを作成して追加します。
env.fromSource(createRocketMQSource(), WatermarkStrategy.noWatermarks(), "source")
// メッセージ本文を大文字に変換します。
.map(RocketMQDataStreamDemo2::convertMessages)
// ApsaraMQ for RocketMQ 結果テーブルを作成して追加します。
.addSink(new OutputFormatSinkFunction<>(createRocketMQOutputFormat()))
.name(RocketMQDataStreamDemo2.class.getSimpleName());
// ジョブをコンパイルして送信します。
env.execute("RocketMQ connector end-to-end DataStream demo");
}
private static MetaQSource<MessageExt> createRocketMQSource() {
Properties mqProperties = createMQProperties();
return new MetaQSource<>(SOURCE_TOPIC,
CONSUMER_GROUP,
null, // always null
null, // tag of the messages to consume
Long.MAX_VALUE, // stop timestamp in milliseconds
-1, // start timestamp in milliseconds. Set to -1 to disable starting from an offset.
0, // start offset
300_000, // partition discovery interval
mqProperties,
Boundedness.CONTINUOUS_UNBOUNDED,
new MyDeserializationSchema());
}
private static MetaQOutputFormat createRocketMQOutputFormat() {
return new MetaQOutputFormat.Builder()
.setTopicName(SINK_TOPIC)
.setProducerGroup(PRODUCER_GROUP)
.setMqProperties(createMQProperties())
.build();
}
private static Properties createMQProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_ONS_CHANNEL, "ALIYUN");
properties.put(NAMESRV_ADDR, ENDPOINT);
properties.put(PROPERTY_ACCESSKEY, ACCESS_ID);
properties.put(PROPERTY_SECRETKEY, ACCESS_KEY);
properties.put(PROPERTY_ROCKET_AUTH_ENABLED, true);
properties.put(PROPERTY_INSTANCE_ID, INSTANCE_ID);
return properties;
}
private static List<MessageExt> convertMessages(MessageExt messages) {
return Collections.singletonList(messages);
}
public static class MyDeserializationSchema implements MetaQRecordDeserializationSchema<MessageExt> {
@Override
public void deserialize(List<MessageExt> list, Collector<MessageExt> collector) {
for (MessageExt messageExt : list) {
collector.collect(messageExt);
}
}
@Override
public TypeInformation<MessageExt> getProducedType() {
return TypeInformation.of(MessageExt.class);
}
}
}
}
}
XML
-
ApsaraMQ for RocketMQ 4.x:MQ DataStream コネクタ。
-
ApsaraMQ for RocketMQ 5.x:MQ DataStream コネクタ。
<!--ApsaraMQ for RocketMQ 5.x-->
<dependency>
<groupId>com.alibaba.ververica</groupId>
<artifactId>ververica-connector-mq5</artifactId>
<version>${vvr-version}</version>
<scope>provided</scope>
</dependency>
<!--ApsaraMQ for RocketMQ 4.x-->
<dependency>
<groupId>com.alibaba.ververica</groupId>
<artifactId>ververica-connector-mq</artifactId>
<version>${vvr-version}</version>
</dependency>
ApsaraMQ for RocketMQ のエンドポイントの設定に関する詳細については、「TCP 内部エンドポイントの設定に関するお知らせ」をご参照ください。