Este tema presenta el conector de ApsaraMQ for RocketMQ.
Las instancias de ApsaraMQ for RocketMQ 4.x Standard Edition comparten un límite máximo elástico de 5,000 llamadas a la API por segundo. Si se supera este límite al conectar una instancia a Realtime Compute for Apache Flink, se activa el estrangulamiento, lo que puede desestabilizar sus trabajos de Flink. Por lo tanto, si utiliza o planea utilizar una instancia de RocketMQ Standard Edition para integrarse con Flink, evalúe cuidadosamente el impacto potencial. De ser posible, considere un middleware de mensajería alternativo, como Kafka, Simple Log Service (SLS) o DataHub. Si debe usar una instancia de ApsaraMQ for RocketMQ 4.x Standard Edition para grandes volúmenes de mensajes, envíe un ticket para solicitar una cuota de estrangulamiento mayor.
Contexto
ApsaraMQ for RocketMQ es un middleware de mensajería distribuida desarrollado por Alibaba Cloud basado en Apache RocketMQ. Ofrece baja latencia, alta concurrencia, alta disponibilidad y alta confiabilidad. ApsaraMQ for RocketMQ proporciona desacoplamiento asíncrono y suavizado de picos para sistemas de aplicaciones distribuidas. También incluye funciones para aplicaciones de Internet, como acumulación masiva de mensajes, alto rendimiento y reintentos confiables.
La siguiente tabla describe el conector de ApsaraMQ for RocketMQ.
|
Elemento |
Descripción |
|
Tipo compatible |
tabla de origen y tabla de destino |
|
Modo de ejecución |
solo modo streaming |
|
Formato de datos |
Formatos CSV y binario |
|
Métricas específicas del conector |
|
|
Tipo de API |
DataStream API (solo para RocketMQ 4.x) y SQL API |
|
Compatibilidad con actualizaciones o eliminaciones de datos en una tabla de destino |
Solo se admite la inserción de datos en una tabla de destino. No se admiten actualizaciones ni eliminaciones. |
Características
Las tablas de origen y destino de ApsaraMQ for RocketMQ admiten los siguientes campos de metadatos.
-
Campos para una tabla de origen
Campo
Tipo
Descripción
topic
VARCHAR METADATA VIRTUAL
El tema del mensaje.
queue-id
INT METADATA VIRTUAL
El ID de la cola.
queue-offset
BIGINT METADATA VIRTUAL
El desplazamiento de consumo.
msg-id
VARCHAR METADATA VIRTUAL
El ID del mensaje.
store-timestamp
TIMESTAMP(3) METADATA VIRTUAL
La marca de tiempo de almacenamiento del mensaje.
born-timestamp
TIMESTAMP(3) METADATA VIRTUAL
La marca de tiempo de generación del mensaje.
keys
VARCHAR METADATA VIRTUAL
Las claves del mensaje.
tags
VARCHAR METADATA VIRTUAL
Las etiquetas del mensaje.
-
Campos para una tabla de destino
Campo
Tipo
Descripción
keys
VARCHAR METADATA
Las claves del mensaje.
tags
VARCHAR METADATA
Las etiquetas del mensaje.
Requisitos previos
Debe haber creado un recurso de Message Queue for Apache RocketMQ. Para obtener instrucciones, consulte Create resources.
Limitaciones
ApsaraMQ for RocketMQ 5.x requiere el motor de computación en tiempo real de Flink VVR 8.0.3 o posterior.
El conector de ApsaraMQ for RocketMQ utiliza consumidores de tipo pull, lo que distribuye la carga de trabajo entre todas las subtareas.
Sintaxis
CREATE TABLE mq_source(
x varchar,
y varchar,
z varchar
) WITH (
'connector' = 'mq5',
'topic' = '<yourTopicName>',
'endpoint' = '<yourEndpoint>',
'consumerGroup' = '<yourConsumerGroup>'
);
Parámetros WITH
Generales
|
Parámetro |
Descripción |
Tipo |
Obligatorio |
Predeterminado |
Observaciones |
|
connector |
El tipo de conector. |
String |
Sí |
Ninguna |
|
|
endPoint |
El endpoint del servicio. |
String |
Sí |
Ninguna |
ApsaraMQ for RocketMQ proporciona dos tipos de endpoints:
Importante
Se recomienda utilizar un endpoint de VPC. Las conexiones de red pública pueden ser inestables debido a cambios dinámicos en las políticas de seguridad de red de Alibaba Cloud.
|
|
topic |
El nombre del tema. |
String |
Sí |
Ninguna |
Ninguna |
|
accessId |
|
String |
|
Ninguna |
Importante
Para evitar exponer su par de AccessKey, se recomienda utilizar un project variable para especificar el AccessKey ID y el AccessKey Secret.
|
|
accessKey |
|
String |
|
Ninguna |
|
|
tag |
La etiqueta de mensaje a la que se desea suscribir o escribir. |
String |
No |
Ninguna |
Nota
Cuando se usa como destino, este parámetro solo es compatible con RocketMQ 4.x. Para RocketMQ 5.x, especifique la etiqueta del mensaje en los campos de metadatos del destino. |
|
encoding |
El formato de codificación. |
String |
No |
UTF-8 |
Ninguna |
|
instanceID |
El ID de la instancia de Alibaba Cloud Message Queue for Apache RocketMQ. |
String |
No |
Ninguna |
Nota
Este parámetro solo es compatible con RocketMQ 4.x. |
Específicos del origen
|
Parámetro |
Descripción |
Tipo |
Obligatorio |
Predeterminado |
Observaciones |
|
consumerGroup |
El nombre del grupo de consumidores. |
String |
Sí |
Ninguna |
Ninguna |
|
pullIntervalMs |
El intervalo de sondeo en milisegundos para el origen cuando no hay datos disponibles. |
Int |
Sí |
Ninguna |
Unidad: milisegundos. No existe un mecanismo de estrangulamiento disponible. No puede establecer la tasa para leer datos de RocketMQ. Nota
Este parámetro solo es compatible con RocketMQ 4.x. |
|
timeZone |
La zona horaria. |
String |
No |
Ninguna |
Ejemplo: Asia/Shanghai. |
|
startTimeMs |
La hora de inicio para el consumo de datos. |
Long |
No |
Ninguna |
Una marca de tiempo en milisegundos. |
|
startMessageOffset |
El desplazamiento del mensaje desde el cual comenzar el consumo. |
Int |
No |
Ninguna |
Si se especifica este parámetro, la carga de datos comienza desde el desplazamiento indicado por |
|
lineDelimiter |
El delimitador de línea utilizado para analizar sintácticamente los registros. |
String |
No |
\n |
Ninguna |
|
fieldDelimiter |
El delimitador de campo. |
String |
No |
\u0001 |
El delimitador varía según el modo del terminal:
|
|
lengthCheck |
La política para comprobar el número de campos en cada registro. |
String |
No |
NONE |
Valores válidos:
|
|
columnErrorDebug |
Especifica si se debe habilitar el modo de depuración para errores de análisis de columnas. |
Boolean |
No |
false |
Si se establece en true, se imprimen registros detallados para las excepciones de análisis. |
|
pullBatchSize |
El número máximo de mensajes para extraer en un solo lote. |
Int |
No |
64 |
Compatible con VVR 8.0.7 y versiones posteriores. |
Específicos del destino
|
Parámetro |
Descripción |
Tipo |
Obligatorio |
Predeterminado |
Observaciones |
|
producerGroup |
El nombre del grupo de productores. |
String |
Sí |
Ninguna |
Ninguna |
|
retryTimes |
El número de veces para reintentar una operación de escritura con errores. |
Int |
No |
10 |
Ninguna |
|
sleepTimeMs |
El intervalo entre reintentos, en milisegundos. |
Long |
No |
5000 |
Ninguna |
|
partitionField |
El nombre del campo que se utilizará como clave de partición. |
String |
No |
Ninguna |
Este parámetro es obligatorio si el parámetro Nota
Compatible con VVR 8.0.5 y versiones posteriores. |
|
deliveryTimestampMode |
El modo de entrega para mensajes diferidos. Este parámetro funciona junto con el parámetro |
String |
No |
Ninguna |
Valores válidos:
Nota
Compatible con VVR 11.1 y versiones posteriores. |
|
deliveryTimestampType |
El tipo de referencia temporal para mensajes diferidos. |
String |
No |
processing_time |
Valores válidos:
Nota
Compatible con VVR 11.1 y versiones posteriores. |
|
deliveryTimestampValue |
La hora de entrega de un mensaje diferido. |
Long |
No |
Ninguna |
El significado de este parámetro depende del valor de
Nota
Compatible con VVR 11.1 y versiones posteriores. |
|
deliveryTimestampField |
Especifica el campo utilizado como hora de entrega para mensajes diferidos. El tipo de datos debe ser |
String |
No |
Ninguna |
Surte efecto cuando Nota
Compatible con VVR 11.1 y versiones posteriores. |
Mapeo de tipos
|
Tipo de Flink |
Tipo de RocketMQ |
|
BOOLEAN |
STRING |
|
VARBINARY |
|
|
VARCHAR |
|
|
TINYINT |
|
|
INTEGER |
|
|
BIGINT |
|
|
FLOAT |
|
|
DOUBLE |
|
|
DECIMAL |
Ejemplos
Ejemplos de tabla de origen
-
Formato CSV
Suponga que un mensaje contiene los siguientes registros de datos en formato CSV.
1,name,male 2,name,femaleNotaUn mensaje de Message Queue for Apache RocketMQ puede contener cero o más registros de datos, separados por
\n.Utilice la siguiente DDL en su trabajo de Flink para declarar una tabla de origen de 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' = ',' ); -
Formato binario
-
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;
-
Ejemplos de tabla de destino
-
Crear una tabla de destino
-
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>' );NotaPara mensajes de RocketMQ en formato binario, la DDL debe definir un único campo con el tipo de dato VARBINARY.
-
-
Crear una tabla de destino que asigne los campos de metadatos
keysytagsa la clave y etiqueta del mensaje-
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
Para leer y escribir datos mediante DataStream API, utilice el conector de DataStream correspondiente para conectarse a Realtime Compute for Apache Flink. Para obtener más información sobre cómo configurar un conector de DataStream, consulte Integrate DataStream connectors.
VVR proporciona MetaQSource para leer desde RocketMQ y MetaQOutputFormat, una implementación de OutputFormat, para escribir en RocketMQ. Los siguientes ejemplos muestran cómo leer desde RocketMQ y escribir en este servicio:
RocketMQ 5.x
En ApsaraMQ for RocketMQ 5.x, el key pair de acceso representa el nombre de usuario y la contraseña de la instancia. No es necesario configurar este par si accede a la instancia a través de una red interna y la autenticación ACL está deshabilitada.
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;
/**
* A demo that shows how to consume, convert, and then produce messages to 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 {
// Set up the streaming execution environment
Configuration conf = new Configuration();
// The following two configurations are for local debugging only. Delete them before you package the job and upload it to 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.*;
/**
* A demo that shows how to consume, convert, and then produce messages to 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 {
// Set up the streaming execution environment
Configuration conf = new Configuration();
// The following two configurations are for local debugging only. Delete them before you package the job and upload it to 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);
// Create and add the ApsaraMQ for RocketMQ source.
env.fromSource(createRocketMQSource(), WatermarkStrategy.noWatermarks(), "source")
// Convert the message body to uppercase.
.map(RocketMQDataStreamDemo2::convertMessages)
// Create and add the ApsaraMQ for RocketMQ sink.
.addSink(new OutputFormatSinkFunction<>(createRocketMQOutputFormat()))
.name(RocketMQDataStreamDemo2.class.getSimpleName());
// Compile and submit the job.
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: Conector de DataStream para MQ.
ApsaraMQ for RocketMQ 5.x: Conector de DataStream para MQ.
<!--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>
Para obtener más información sobre cómo configurar el endpoint de ApsaraMQ for RocketMQ, consulte Announcement on the settings of TCP internal endpoints.
Preguntas frecuentes
How does RocketMQ detect partition count changes during topic scaling?