Search in sources :

Example 1 with CanalServerException

use of com.alibaba.otter.canal.server.exception.CanalServerException in project canal by alibaba.

the class CanalServerWithEmbedded method rollback.

/**
 * 回滚到未进行 {@link #ack} 的地方,下次fetch的时候,可以从最后一个没有 {@link #ack} 的地方开始拿
 */
@Override
public void rollback(ClientIdentity clientIdentity, Long batchId) throws CanalServerException {
    checkStart(clientIdentity.getDestination());
    CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
    // 因为存在第一次链接时自动rollback的情况,所以需要忽略未订阅
    boolean hasSubscribe = canalInstance.getMetaManager().hasSubscribe(clientIdentity);
    if (!hasSubscribe) {
        return;
    }
    synchronized (canalInstance) {
        // 清除batch信息
        PositionRange<LogPosition> positionRanges = canalInstance.getMetaManager().removeBatch(clientIdentity, batchId);
        if (positionRanges == null) {
            // 说明是重复的ack/rollback
            throw new CanalServerException(String.format("rollback error, clientId:%s batchId:%d is not exist , please check", clientIdentity.getClientId(), batchId));
        }
        // lastRollbackPostions.put(clientIdentity,
        // positionRanges.getEnd());// 记录一下最后rollback的位置
        // TODO 后续rollback到指定的batchId位置
        // rollback
        canalInstance.getEventStore().rollback();
        // eventStore中的状态信息
        logger.info("rollback successfully, clientId:{} batchId:{} position:{}", clientIdentity.getClientId(), batchId, positionRanges);
    }
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 2 with CanalServerException

use of com.alibaba.otter.canal.server.exception.CanalServerException in project canal by alibaba.

the class CanalServerWithEmbedded method ack.

/**
 * 进行 batch id 的确认。确认之后,小于等于此 batchId 的 Message 都会被确认。
 *
 * <pre>
 * 注意:进行反馈时必须按照batchId的顺序进行ack(需有客户端保证)
 * </pre>
 */
@Override
public void ack(ClientIdentity clientIdentity, long batchId) throws CanalServerException {
    checkStart(clientIdentity.getDestination());
    checkSubscribe(clientIdentity);
    CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
    PositionRange<LogPosition> positionRanges = null;
    // 更新位置
    positionRanges = canalInstance.getMetaManager().removeBatch(clientIdentity, batchId);
    if (positionRanges == null) {
        // 说明是重复的ack/rollback
        throw new CanalServerException(String.format("ack error , clientId:%s batchId:%d is not exist , please check", clientIdentity.getClientId(), batchId));
    }
    // 更新cursor
    if (positionRanges.getAck() != null) {
        canalInstance.getMetaManager().updateCursor(clientIdentity, positionRanges.getAck());
        if (logger.isInfoEnabled()) {
            logger.info("ack successfully, clientId:{} batchId:{} position:{}", clientIdentity.getClientId(), batchId, positionRanges);
        }
    }
    // 可定时清理数据
    canalInstance.getEventStore().ack(positionRanges.getEnd(), positionRanges.getEndSeq());
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Example 3 with CanalServerException

use of com.alibaba.otter.canal.server.exception.CanalServerException in project canal by alibaba.

the class CanalController method initGlobalConfig.

private InstanceConfig initGlobalConfig(Properties properties) {
    String adminManagerAddress = getProperty(properties, CanalConstants.CANAL_ADMIN_MANAGER);
    InstanceConfig globalConfig = new InstanceConfig();
    String modeStr = getProperty(properties, CanalConstants.getInstanceModeKey(CanalConstants.GLOBAL_NAME));
    if (StringUtils.isNotEmpty(adminManagerAddress)) {
        // 如果指定了manager地址,则强制适用manager
        globalConfig.setMode(InstanceMode.MANAGER);
    } else if (StringUtils.isNotEmpty(modeStr)) {
        globalConfig.setMode(InstanceMode.valueOf(StringUtils.upperCase(modeStr)));
    }
    String lazyStr = getProperty(properties, CanalConstants.getInstancLazyKey(CanalConstants.GLOBAL_NAME));
    if (StringUtils.isNotEmpty(lazyStr)) {
        globalConfig.setLazy(Boolean.valueOf(lazyStr));
    }
    String managerAddress = getProperty(properties, CanalConstants.getInstanceManagerAddressKey(CanalConstants.GLOBAL_NAME));
    if (StringUtils.isNotEmpty(managerAddress)) {
        if (StringUtils.equals(managerAddress, "${canal.admin.manager}")) {
            managerAddress = adminManagerAddress;
        }
        globalConfig.setManagerAddress(managerAddress);
    }
    String springXml = getProperty(properties, CanalConstants.getInstancSpringXmlKey(CanalConstants.GLOBAL_NAME));
    if (StringUtils.isNotEmpty(springXml)) {
        globalConfig.setSpringXml(springXml);
    }
    instanceGenerator = destination -> {
        InstanceConfig config = instanceConfigs.get(destination);
        if (config == null) {
            throw new CanalServerException("can't find destination:" + destination);
        }
        if (config.getMode().isManager()) {
            PlainCanalInstanceGenerator instanceGenerator = new PlainCanalInstanceGenerator(properties);
            instanceGenerator.setCanalConfigClient(managerClients.get(config.getManagerAddress()));
            instanceGenerator.setSpringXml(config.getSpringXml());
            return instanceGenerator.generate(destination);
        } else if (config.getMode().isSpring()) {
            SpringCanalInstanceGenerator instanceGenerator = new SpringCanalInstanceGenerator();
            instanceGenerator.setSpringXml(config.getSpringXml());
            return instanceGenerator.generate(destination);
        } else {
            throw new UnsupportedOperationException("unknow mode :" + config.getMode());
        }
    };
    return globalConfig;
}
Also used : PlainCanalInstanceGenerator(com.alibaba.otter.canal.instance.manager.PlainCanalInstanceGenerator) SpringCanalInstanceGenerator(com.alibaba.otter.canal.instance.spring.SpringCanalInstanceGenerator) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException)

Example 4 with CanalServerException

use of com.alibaba.otter.canal.server.exception.CanalServerException in project canal by alibaba.

the class CanalServerWithEmbedded method checkSubscribe.

private void checkSubscribe(ClientIdentity clientIdentity) {
    CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
    boolean hasSubscribe = canalInstance.getMetaManager().hasSubscribe(clientIdentity);
    if (!hasSubscribe) {
        throw new CanalServerException(String.format("ClientIdentity:%s should subscribe first", clientIdentity.toString()));
    }
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException)

Example 5 with CanalServerException

use of com.alibaba.otter.canal.server.exception.CanalServerException in project canal by alibaba.

the class CanalServerWithEmbedded method get.

/**
 * 获取数据,可以指定超时时间.
 *
 * <pre>
 * 几种case:
 * a. 如果timeout为null,则采用tryGet方式,即时获取
 * b. 如果timeout不为null
 *    1. timeout为0,则采用get阻塞方式,获取数据,不设置超时,直到有足够的batchSize数据才返回
 *    2. timeout不为0,则采用get+timeout方式,获取数据,超时还没有batchSize足够的数据,有多少返回多少
 *
 * 注意: meta获取和数据的获取需要保证顺序性,优先拿到meta的,一定也会是优先拿到数据,所以需要加同步. (不能出现先拿到meta,拿到第二批数据,这样就会导致数据顺序性出现问题)
 * </pre>
 */
@Override
public Message get(ClientIdentity clientIdentity, int batchSize, Long timeout, TimeUnit unit) throws CanalServerException {
    checkStart(clientIdentity.getDestination());
    checkSubscribe(clientIdentity);
    CanalInstance canalInstance = canalInstances.get(clientIdentity.getDestination());
    synchronized (canalInstance) {
        // 获取到流式数据中的最后一批获取的位置
        PositionRange<LogPosition> positionRanges = canalInstance.getMetaManager().getLastestBatch(clientIdentity);
        if (positionRanges != null) {
            throw new CanalServerException(String.format("clientId:%s has last batch:[%s] isn't ack , maybe loss data", clientIdentity.getClientId(), positionRanges));
        }
        Events<Event> events = null;
        Position start = canalInstance.getMetaManager().getCursor(clientIdentity);
        events = getEvents(canalInstance.getEventStore(), start, batchSize, timeout, unit);
        if (CollectionUtils.isEmpty(events.getEvents())) {
            logger.debug("get successfully, clientId:{} batchSize:{} but result is null", clientIdentity.getClientId(), batchSize);
            // 返回空包,避免生成batchId,浪费性能
            return new Message(-1, true, new ArrayList());
        } else {
            // 记录到流式信息
            Long batchId = canalInstance.getMetaManager().addBatch(clientIdentity, events.getPositionRange());
            boolean raw = isRaw(canalInstance.getEventStore());
            List entrys = null;
            if (raw) {
                entrys = Lists.transform(events.getEvents(), Event::getRawEntry);
            } else {
                entrys = Lists.transform(events.getEvents(), Event::getEntry);
            }
            if (logger.isInfoEnabled()) {
                logger.info("get successfully, clientId:{} batchSize:{} real size is {} and result is [batchId:{} , position:{}]", clientIdentity.getClientId(), batchSize, entrys.size(), batchId, events.getPositionRange());
            }
            // 直接提交ack
            ack(clientIdentity, batchId);
            return new Message(batchId, raw, entrys);
        }
    }
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) Message(com.alibaba.otter.canal.protocol.Message) Position(com.alibaba.otter.canal.protocol.position.Position) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition) ArrayList(java.util.ArrayList) Event(com.alibaba.otter.canal.store.model.Event) ArrayList(java.util.ArrayList) List(java.util.List) CanalServerException(com.alibaba.otter.canal.server.exception.CanalServerException) LogPosition(com.alibaba.otter.canal.protocol.position.LogPosition)

Aggregations

CanalServerException (com.alibaba.otter.canal.server.exception.CanalServerException)5 CanalInstance (com.alibaba.otter.canal.instance.core.CanalInstance)4 LogPosition (com.alibaba.otter.canal.protocol.position.LogPosition)3 PlainCanalInstanceGenerator (com.alibaba.otter.canal.instance.manager.PlainCanalInstanceGenerator)1 SpringCanalInstanceGenerator (com.alibaba.otter.canal.instance.spring.SpringCanalInstanceGenerator)1 Message (com.alibaba.otter.canal.protocol.Message)1 Position (com.alibaba.otter.canal.protocol.position.Position)1 Event (com.alibaba.otter.canal.store.model.Event)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1