Maxwell recopila binlog y envía datos al clúster kafka a través de nginx en diferentes entornos de red

Maxwell se puede utilizar como una herramienta de sincronización de datos mediante la recopilación de cambios binlog de mysql en tiempo real.

Pero a veces, cuando la aplicación se implementa en un entorno remoto, los cambios de la base de datos mysql no se pueden enviar directamente al centro de datos a través de Maxwell para el análisis y la sincronización de datos. Esta vez, el método ngix se usa como un servidor proxy. .

La estructura es la siguiente:
Maxwell recopila binlog y envía datos al clúster kafka a través de nginx en diferentes entornos de red

1. Se distribuyen múltiples plataformas de aplicaciones en diferentes regiones. La base de datos remota de MySQL puede acceder a Internet.
2. En el centro de datos local, use el servicio nginx para representar varios clústeres de Kafka.
3. Asigne la ip del servidor nginx a través de la red pública IP + puerto, puede acceder a nginx a través de la ip de la red pública.

Después de pasar el diseño de arquitectura anterior, pero maxwell no admite el envío al servicio http, solo admite kafka, redis, etc.

Después de consultar el sitio web oficial de maxwell, descubrí que hay un método de productor personalizado. Esta vez, el método personalizado se utiliza para resolver el problema de que maxwell envía json a nginx por correo.

(Los colores en el código del texto están integrados en el sistema, por lo que no necesita prestar demasiada atención).

1. Trabajo de desarrollo de código

1. Use la idea, cree un proyecto Maven, agregue dependencia pom, principalmente diseñe http relacionado

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
    <version>4.1.2</version>
</dependency>

2. Agregue manualmente el archivo maxwell-1.22.3.jar al proyecto.
Maxwell recopila binlog y envía datos al clúster kafka a través de nginx en diferentes entornos de red

3. Cree la clase HttpUtil para llamar y enviar solicitudes de publicación

package com.test.utils;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class HttpUtil {

    public void doPost(String url, String json){

        CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        try {
            StringEntity s = new StringEntity(json.toString());
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            post.setEntity(s);
            HttpResponse res = httpclient.execute(post);      
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

4. Cree una clase personalizada de CustomProducer, heredando AbstractProducer

package com.test.producerfactory;

import com.test.utils.HttpUtil;
import com.zendesk.maxwell.MaxwellContext;
import com.zendesk.maxwell.producer.AbstractProducer;
import com.zendesk.maxwell.producer.EncryptionMode;
import com.zendesk.maxwell.producer.MaxwellOutputConfig;
import com.zendesk.maxwell.row.RowMap;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

public class CustomProducer extends AbstractProducer {
    private final String headerFormat;
    private final Collection<RowMap> txRows = new ArrayList<>();
    private final HttpUtil httpUtil=new HttpUtil();
    private static MaxwellOutputConfig config=new MaxwellOutputConfig();
    private String url="";
    private String server_id="0";
    private String encrypt=null;
    private String secretKey=null;    

    public CustomProducer(MaxwellContext context) {
        super(context);
        // this property would be 'custom_producer.header_format' in config.properties
        headerFormat = context.getConfig().customProducerProperties.getProperty("header_format", "Transaction: %xid% >>>\n");

        //从maxwell的配置文件中获取配置信息
        server_id=context.getConfig().customProducerProperties.getProperty("server_id");
        url=context.getConfig().customProducerProperties.getProperty("url");
        encrypt=context.getConfig().customProducerProperties.getProperty("encrypt");
        secretKey=context.getConfig().customProducerProperties.getProperty("secretKey");

        // 配置输出json字段包含serverID
        config.includesServerId=true;

        //配置是否加密数据
        if (encrypt.equals("data")){
            config.encryptionMode= EncryptionMode.ENCRYPT_DATA;
            config.secretKey=secretKey;
        }else if (encrypt.equals("all")){
            config.encryptionMode= EncryptionMode.ENCRYPT_ALL;
            config.secretKey=secretKey;
        }

    }

    @Override
    public void push(RowMap r) throws Exception
    {
        // filtering out DDL and heartbeat rows
        if(!r.shouldOutput(outputConfig)) {
            // though not strictly necessary (as skipping has no side effects), we store our position,
            // so maxwell won't have to "re-skip" this position if crashing and restarting.
            context.setPosition(r.getPosition());
            return;
        }

        //设置serverID
        r.setServerId(Long.parseLong(server_id));

        // store uncommitted row in buffer
        txRows.add(r);

        if(r.isTXCommit()) {
            // This row is the final and closing row of a transaction. Stream all rows of buffered
            // transaction to stdout
//            System.out.print(headerFormat.replace("%xid%", r.getXid().toString()));

            txRows.stream().map(CustomProducer::toJSON).forEach(string -> httpUtil.doPost(url,string));
            txRows.clear();
//            rows ++;

            // Only now, after finally having "persisted" all buffered rows to stdout is it safe to
            // store the producers position.
            context.setPosition(r.getPosition());
//            
        }
    }

    private static String toJSON(RowMap row) {
        try {
            return row.toJSON(config);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }   

}

5. Crear clase CustomProducerFactory

package com.test.producerfactory;

import com.zendesk.maxwell.MaxwellContext;
import com.zendesk.maxwell.producer.AbstractProducer;
import com.zendesk.maxwell.producer.ProducerFactory;

public class CustomProducerFactory implements ProducerFactory{

    @Override
    public AbstractProducer createProducer(MaxwellContext context) {
        return new CustomProducer(context);
    }
}

6. Utilice la herramienta idea para empaquetar el archivo data_sync.jar y transferirlo al directorio remoto maxwell lib.

Segundo, el trabajo de configuración

El trabajo de configuración se divide principalmente en configuración nginx y maxwell. Los elementos de configuración se presentan a continuación.

1, configuración nginx

Después de descargar Nginx y compilar el código fuente, debe agregar el complemento compatible con kafka
[root @ host1 nginx] #
./configure --add-module = / usr / local / src / ngx_kafka_module --add-module = / usr / logcal / nginx_tcp_proxy_module

No se introdujo el método de instalación de nginx. Después de instalar nginx, edite el archivo nginx.conf en el directorio / usr / local / nginx / conf

#user  nobody;
worker_processes  1;
error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;
pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;    
    keepalive_timeout  65;
    kafka;
    kafka_broker_list host2:9092 host3:9092 host4:9092;
    server {
        listen       19090;
        server_name  localhost;      

        location / {
            root   html;
        kafka_topic test1;  
            index  index.html index.htm;
        }       
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }        
    }       
}

Donde kafka_topic se envía al tema especificado después de recibir los datos.
kafka_broker_list: es el nodo intermediario y el puerto de kafka. Aquí, debido a que la resolución del host está configurada, se utiliza el nombre del host.

Después de completar la configuración de nginx y volver a cargar la configuración, puede usar un servidor en un segmento de red diferente al de kafka y nginx, y usar el siguiente comando para probar si nginx está disponible:
[root @ master ~] # curl http://58.30.1.xxx:19007/ -d "aaaaaa"

En el clúster kafka de la intranet, use el siguiente comando para verificar si kafka puede recibir datos:
[root @ host3 ~] # kafka-console-consumer --bootstrap-server kafkahost: 9092 --topic test1

Cuando se reciben datos en el clúster kafka, significa que los datos enviados por http se envían al clúster kafka a través de nginx.

2. Configuración de Maxwell, puede descargar el software maxwell a través del sitio web oficial, descomprimirlo en / opt / maxwell
(la instalación y el inicio específicos de maxwell que ya he introducido en detalle en el artículo anterior)

Utilice un consumidor de producción personalizado, cargue data_sync.jar dependiente en el directorio / opt / maxwell / lib después de descomprimir maxwell.

Cree un archivo config.properties en el directorio / opt / maxwell y escriba la configuración especificada:
vim config.properties

#[mysql]
user=maxwell   
password=123456  
host=hadoop1  
port=3306   
#[producer]
output_server_id=true   
custom_producer.factory=com.test.producerfactory.CustomProducerFactory  
custom_producer.server_id=23  
custom_producer.url=http://58.30.1.XX:19007/  
custom_producer.encrypt=data   
custom_producer.secretKey=0f1b122303xx44123  

Descripción del elemento de configuración:
usuario : #connect mysql nombre de usuario
contraseña : #connect mysql contraseña
host: # mysql host nombre (dirección IP)
puerto: #mysqlport

output_server_id: #Output server_id, utilizado para identificar los datos de la plataforma regional
custom_producer.factory: #Custom producción y consumo clase
custom_producer.server_id: #Defined server_id, consistente con server_id en my.cnf
custom_producer.url: #Data center está abierto al público Url

custom_producer.encrypt: # Método de encriptación, datos, todos, ninguno
custom_producer.secretKey: # Valor de clave secreta, el valor de clave secreta asignado por el punto del centro de datos, correspondencia uno a uno con server_id

Si se configura el cifrado de datos, después de recibir los datos, se requiere un descifrado adicional antes de que se puedan obtener los datos de binlog, y el método de descifrado se escribirá más adelante.

Una vez completada la configuración anterior, puede iniciar maxwell e iniciar los datos sincronizados con el centro de datos local. Cuando los datos se sincronizan con el clúster kafka local, puede usar el receptor de transmisión de chispa y chispa para su posterior procesamiento.

Supongo que te gusta

Origin blog.51cto.com/jxplpp/2486116
Recomendado
Clasificación