Flume自定义Sink到MySQL数据库

本文介绍了一种使用Apache Flume将数据写入MySQL数据库的方法。通过实现自定义的MysqlSink类,该方法能够从Flume Channel中批量读取事件,并将其插入到指定的MySQL表中。文章详细解释了如何配置MysqlSink,包括数据库连接参数和批处理大小。
摘要由CSDN通过智能技术生成
package com.yimen.data.flume.sink;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import java.sql.*;
import java.util.List;
import java.util.Map;
import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MysqlSink extends AbstractSink implements Configurable {

    private Logger LOG = LoggerFactory.getLogger(MysqlSink.class);
    private String hostname;
    private String port;
    private String databaseName;
    private String tableName;
    private String username;
    private String password;
    private String testtype;
    private PreparedStatement preparedStatement;
    private Connection conn;
    private int batchSize; //每次提交的批次大小

    public static final String TEST_TYPE = "testType";


    public MysqlSink() {
        LOG.info("MysqlSink start...");
    }

    /**实现Configurable接口中的方法:可获取配置文件中的属性*/
    public void configure(Context context) {
        hostname = context.getString("hostname");
        Preconditions.checkNotNull(hostname, "hostname must be set!!");
        port = context.getString("port");
        Preconditions.checkNotNull(port, "port must be set!!");
        databaseName = context.getString("databaseName");
        Preconditions.checkNotNull(databaseName, "databaseName must be set!!");
        tableName = context.getString("tableName");
        Preconditions.checkNotNull(tableName, "tableName must be set!!");
        username = context.getString("username");
        Preconditions.checkNotNull(username, "user must be set!!");
        password = context.getString("password");
        Preconditions.checkNotNull(password, "password must be set!!");
        testtype = context.getString("testtype");//获取指定类型过滤
        Preconditions.checkNotNull(password, "password must be set!!");
        batchSize = context.getInteger("batchSize", 100);
        Preconditions.checkNotNull(batchSize > 0, "batchSize must be a positive number!!");
    }

    @Override
    public void start() {
        super.start();
        try {
            //调用Class.forName()方法加载驱动程序
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        String url = "jdbc:mysql://" + hostname + ":" + port + "/" + databaseName;
        //调用DriverManager对象的getConnection()方法,获得一个Connection对象

        try {
            conn = DriverManager.getConnection(url, username, password);
            conn.setAutoCommit(false);
            //创建一个Statement对象
            preparedStatement = conn.prepareStatement("insert into " + tableName +
                    " (name,age,time) values (?,?,?)");

        } catch (SQLException e) {
            e.printStackTrace();
            System.exit(1);
        }

    }

    @Override
    public void stop() {
        super.stop();
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public Status process() throws EventDeliveryException {
        Status result = Status.READY;
        Channel channel = getChannel();
        Transaction transaction = channel.getTransaction();
        Event event = null;
        String content = "";
        String appType = "";
        
        transaction.begin();
        List<PerBean> lists = Lists.newArrayList();

        try {
            for (int i = 0; i < batchSize; i++) {
                event = channel.take();
                if (event != null) {
                    content = new String(event.getBody());
                    testType = event.getHeaders().get(TEST_TYPE);
                    if(testtype .equals(testType )){
                    	if(!"".equals(content )){
                    		PerBeanbean = JSON.parseObject(content, PerBean.class);
                        lists.add(bean);
                    	}             
                    }
                } else {
                    result = Status.BACKOFF;
                    break;
                }
            }
            if (lists != null && lists.size() > 0) {
                preparedStatement.clearBatch();
                for (PerBean bean : lists) {
                    preparedStatement.setObject(1, bean.getName());
                    //用setObject避免NullPointException
                    preparedStatement.setObject(2, bean.getAge()); 
                    preparedStatement.setTimestamp(4, new Timestamp(bean.getRp_date().getTime()));//java.util.date 转 java.sql.date                   
                    preparedStatement.addBatch();
                }
                preparedStatement.executeBatch();

                conn.commit();
            }
            transaction.commit();
        } catch (Throwable e) {
            try {
                transaction.rollback();
            } catch (Exception e2) {
                LOG.error("Exception in rollback. Rollback might not have been" +
                        "successful.", e2);
            }
            LOG.error("Failed to commit transaction." +
                    "Transaction rolled back.", e);
            Throwables.propagate(e);
        } finally {
            transaction.close();
        }
        return result;
    }

}
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值