All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.neoremind.fountain.BinlogSyncerImpl Maven / Gradle / Ivy

package net.neoremind.fountain;

import java.util.List;

import net.neoremind.fountain.common.mq.FountainMQ;
import net.neoremind.fountain.datasource.DatasourceConfigure;
import net.neoremind.fountain.eventposition.AbstractProxyDisposeEventPosition;
import net.neoremind.fountain.eventposition.AsyncFixedRateDisposeEventPosition;
import net.neoremind.fountain.eventposition.DisposeEventPositionBridge;
import net.neoremind.fountain.eventposition.ReadonlyDisposeEventPosition;
import net.neoremind.fountain.eventposition.RegistableDisposeEventPosition;
import net.neoremind.fountain.exception.BinlogSyncInitException;
import net.neoremind.fountain.producer.DefaultProducer;
import net.neoremind.fountain.producer.datasource.BinlogDataSource;
import net.neoremind.fountain.producer.datasource.MysqlBinlogDataSource;
import net.neoremind.fountain.producer.datasource.ha.HAMysqlBinlogDataSource;
import net.neoremind.fountain.producer.datasource.slaveid.RandomSlaveIdGenerateStrategy;
import net.neoremind.fountain.producer.datasource.slaveid.SlaveIdGenerateStrategy;
import net.neoremind.fountain.producer.dispatch.DefaultDispatchWorkflow;
import net.neoremind.fountain.producer.dispatch.DispatchWorkflow;
import net.neoremind.fountain.producer.dispatch.fountainmq.FoutainMQTransport;
import net.neoremind.fountain.producer.parser.impl.DefaultParser;
import net.neoremind.fountain.util.CollectionUtil;

/**
 * Binlog同步器实现
 *
 * @author zhangxu
 */
public class BinlogSyncerImpl implements BinlogSyncer, Callbackable> {

    /**
     * 字符串不为空的条件验证
     */
    private AbstractClosurePredicate stringNotNull;

    /**
     * 基本类型或者装箱类型是否为默认值的条件验证
     */
    private AbstractClosurePredicate primitiveOrWrapperDefaultValue;

    /**
     * slaveId生成策略
     */
    private SlaveIdGenerateStrategy slaveIdGenerateStrategy;

    /**
     * consumer用于保存同步点的桥接器
     *
     * @see DisposeEventPositionBridge
     */
    private DisposeEventPositionBridge bridge;

    /**
     * binlog消息增量的处理生成者
     */
    private DefaultProducer producer;

    /**
     * slaveId的范围,用于随机生成策略
     */
    private int[] slaveIdRange = new int[] {100, 5000};

    /**
     * 默认构造方法
     */
    public BinlogSyncerImpl() {
        stringNotNull = new StringNotNullClosurePredicate();
        primitiveOrWrapperDefaultValue =
                new PrimitiveOrWrapperDefaultValueClosurePredicate();
        slaveIdGenerateStrategy = new RandomSlaveIdGenerateStrategy();
        ((RandomSlaveIdGenerateStrategy) slaveIdGenerateStrategy).setStart(slaveIdRange[0]);
        ((RandomSlaveIdGenerateStrategy) slaveIdGenerateStrategy).setEnd(slaveIdRange[1]);
    }

    /**
     * 构造方法
     *
     * @param builder 根据builder构造对象
     * @param bridge  consumer用于保存同步点的桥接器
     */
    public BinlogSyncerImpl(BinlogSyncBuilder builder, DisposeEventPositionBridge bridge) {
        this();
        this.bridge = bridge;
        try {
            Preconditions.checkArgument(builder.getDataSource() != null, "Datasource should not be NULL");
            Preconditions
                    .checkArgument(builder.getBinlogDumpStrategy() != null, "Binlog dump strategy should not be NULL");

            producer = new DefaultProducer();
            producer.setBeanName(Either.or(Defaults.DEFAULT_PRODUCER_NAME).fromNullable(builder.getProducerName()));
            producer.setHaGuard(Beans.HAGUARD.get(builder));
            producer.setTransactionPolicy(Beans.TRANSACTION_POLICY.get(builder));
            producer.setParser(new DefaultParser(Beans.EVENT_MATCHER.get(builder)));
            producer.setMatcher(Beans.EVENT_MATCHER.get(builder));
            producer.setDataSource(newHAMysqlBinlogDataSource(builder));
        } catch (Exception e) {
            throw new BinlogSyncInitException(e.getMessage(), e);
        }
    }

    /**
     * 新建增量消息的分发器,依赖于一个消息队列{@link FountainMQ}
     *
     * @param mq 消息队列,用于生产者和消费者解耦
     *
     * @return 消息的分发器
     */
    private DispatchWorkflow newDispatchWorkflow(FountainMQ mq) {
        FoutainMQTransport mqTransport = new FoutainMQTransport();
        mqTransport.setFmq(mq);
        DefaultDispatchWorkflow workflow = new DefaultDispatchWorkflow();
        workflow.setTranport(mqTransport);
        return workflow;
    }

    /**
     * 新建高可用的MySQL binlog数据源
     *
     * @param builder 根据builder构造对象
     *
     * @return 高可用的MySQL binlog数据源
     */
    private HAMysqlBinlogDataSource newHAMysqlBinlogDataSource(BinlogSyncBuilder builder) {
        HAMysqlBinlogDataSource haDs = new HAMysqlBinlogDataSource();
        List entities = builder.getDataSource().toEntities();
        List binlogDataSources = CollectionUtil.createArrayList(entities.size());
        for (DataSourceEntity e : entities) {
            MysqlBinlogDataSource binlogDataSource = new MysqlBinlogDataSource();
            binlogDataSource.setConf(newDatasourceConfigure(e, builder));
            binlogDataSource.setBinlogDumpStrategy(builder.getBinlogDumpStrategy());
            if (primitiveOrWrapperDefaultValue.set(e.getSlaveId()).apply()) {
                binlogDataSource.setSlaveId(e.getSlaveId());
            } else {
                binlogDataSource.setSlaveId(slaveIdGenerateStrategy.get());
            }
            binlogDataSources.add(binlogDataSource);
        }
        AbstractProxyDisposeEventPosition eventPosition = new ReadonlyDisposeEventPosition();
        eventPosition.setDelegate(Beans.DISPOSE_EVENT_POSITION.get(builder));
        if (builder.getDisposeEventPosition() instanceof RegistableDisposeEventPosition) {
            ((RegistableDisposeEventPosition) builder.getDisposeEventPosition()).setDisposeEventPositionBridge(bridge);
        }
        //TODO refactor
        if (builder.getDisposeEventPosition() instanceof AsyncFixedRateDisposeEventPosition) {
            ((AsyncFixedRateDisposeEventPosition) builder.getDisposeEventPosition())
                    .setDisposeEventPositionBridge(bridge);
        }
        haDs.setDisposeEventPosition(eventPosition);
        haDs.setDatasourceChoosePolicy(Beans.DATASOURCE_CHOOSE_POLICY.get(builder));
        haDs.setMysqlDataSourceList(binlogDataSources);
        haDs.init();
        return haDs;
    }

    /**
     * 新建数据源配置
     *
     * @param e       数据源实体
     * @param builder 根据builder构造对象
     *
     * @return 数据源配置
     */
    private DatasourceConfigure newDatasourceConfigure(DataSourceEntity e, BinlogSyncBuilder builder) {
        DatasourceConfigure conf = new DatasourceConfigure();
        conf.setMysqlServer(e.getIp());
        conf.setMysqlPort(e.getPort());
        conf.setUserName(e.getUsername());
        conf.setPassword(e.getPassword());
        if (stringNotNull.set(builder.getCharset()).apply()) {
            conf.setCharset(builder.getCharset());
        }
        if (stringNotNull.set(builder.getDatabaseName()).apply()) {
            conf.setCharset(builder.getDatabaseName());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getSoTimeout()).apply()) {
            conf.setSoTimeout(builder.getSoTimeout());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getConnectTimeout()).apply()) {
            conf.setSoTimeout(builder.getConnectTimeout());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getWaitTimeout()).apply()) {
            conf.setSoTimeout(builder.getWaitTimeout());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getNetReadTimeout()).apply()) {
            conf.setSoTimeout(builder.getNetReadTimeout());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getNetWriteTimeout()).apply()) {
            conf.setSoTimeout(builder.getNetWriteTimeout());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getSendBufferSize()).apply()) {
            conf.setSoTimeout(builder.getSendBufferSize());
        }
        if (primitiveOrWrapperDefaultValue.set(builder.getReceiveBufferSize()).apply()) {
            conf.setSoTimeout(builder.getReceiveBufferSize());
        }
        return conf;
    }

    @Override
    public void callback(Listener listener) {
        producer.setDispatcher(newDispatchWorkflow(listener.getQueue()));
    }

    @Override
    public void start() {
        producer.start();
    }

    @Override
    public void stop() {
        producer.destroy();
    }

    public void setBridge(DisposeEventPositionBridge bridge) {
        this.bridge = bridge;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy