Search in sources :

Example 36 with Message

use of com.alibaba.otter.canal.protocol.Message 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)

Example 37 with Message

use of com.alibaba.otter.canal.protocol.Message in project canal by alibaba.

the class CanalMQStarter method worker.

private void worker(String destination, AtomicBoolean destinationRunning) {
    while (!running || !destinationRunning.get()) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        // ignore
        }
    }
    logger.info("## start the MQ producer: {}.", destination);
    MDC.put("destination", destination);
    final ClientIdentity clientIdentity = new ClientIdentity(destination, (short) 1001, "");
    while (running && destinationRunning.get()) {
        try {
            CanalInstance canalInstance = canalServer.getCanalInstances().get(destination);
            if (canalInstance == null) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                // ignore
                }
                continue;
            }
            MQDestination canalDestination = new MQDestination();
            canalDestination.setCanalDestination(destination);
            CanalMQConfig mqConfig = canalInstance.getMqConfig();
            canalDestination.setTopic(mqConfig.getTopic());
            canalDestination.setPartition(mqConfig.getPartition());
            canalDestination.setDynamicTopic(mqConfig.getDynamicTopic());
            canalDestination.setPartitionsNum(mqConfig.getPartitionsNum());
            canalDestination.setPartitionHash(mqConfig.getPartitionHash());
            canalDestination.setDynamicTopicPartitionNum(mqConfig.getDynamicTopicPartitionNum());
            canalDestination.setEnableDynamicQueuePartition(mqConfig.getEnableDynamicQueuePartition());
            canalServer.subscribe(clientIdentity);
            logger.info("## the MQ producer: {} is running now ......", destination);
            Integer getTimeout = mqProperties.getFetchTimeout();
            Integer getBatchSize = mqProperties.getBatchSize();
            while (running && destinationRunning.get()) {
                Message message;
                if (getTimeout != null && getTimeout > 0) {
                    message = canalServer.getWithoutAck(clientIdentity, getBatchSize, getTimeout.longValue(), TimeUnit.MILLISECONDS);
                } else {
                    message = canalServer.getWithoutAck(clientIdentity, getBatchSize);
                }
                final long batchId = message.getId();
                try {
                    int size = message.isRaw() ? message.getRawEntries().size() : message.getEntries().size();
                    if (batchId != -1 && size != 0) {
                        canalMQProducer.send(canalDestination, message, new Callback() {

                            @Override
                            public void commit() {
                                // 提交确认
                                canalServer.ack(clientIdentity, batchId);
                            }

                            @Override
                            public void rollback() {
                                canalServer.rollback(clientIdentity, batchId);
                            }
                        });
                    // 发送message到topic
                    } else {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                        // ignore
                        }
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        } catch (Exception e) {
            logger.error("process error!", e);
        }
    }
}
Also used : CanalInstance(com.alibaba.otter.canal.instance.core.CanalInstance) Callback(com.alibaba.otter.canal.connector.core.util.Callback) ClientIdentity(com.alibaba.otter.canal.protocol.ClientIdentity) MQDestination(com.alibaba.otter.canal.connector.core.producer.MQDestination) Message(com.alibaba.otter.canal.protocol.Message) CanalMQConfig(com.alibaba.otter.canal.instance.core.CanalMQConfig)

Aggregations

Message (com.alibaba.otter.canal.protocol.Message)37 ArrayList (java.util.ArrayList)12 FlatMessage (com.alibaba.otter.canal.protocol.FlatMessage)11 List (java.util.List)7 CanalClientException (com.alibaba.otter.canal.protocol.exception.CanalClientException)6 Test (org.junit.Test)6 CommonMessage (com.alibaba.otter.canal.connector.core.consumer.CommonMessage)5 Entry (com.alibaba.otter.canal.protocol.CanalEntry.Entry)4 ByteString (com.google.protobuf.ByteString)4 CanalInstance (com.alibaba.otter.canal.instance.core.CanalInstance)3 CanalConnector (com.alibaba.otter.canal.client.CanalConnector)2 ConsumerBatchMessage (com.alibaba.otter.canal.client.ConsumerBatchMessage)2 ExecutorTemplate (com.alibaba.otter.canal.common.utils.ExecutorTemplate)2 CanalEventParser (com.alibaba.otter.canal.parse.CanalEventParser)2 CanalHASwitchable (com.alibaba.otter.canal.parse.CanalHASwitchable)2 CanalEntry (com.alibaba.otter.canal.protocol.CanalEntry)2 Messages (com.alibaba.otter.canal.protocol.CanalPacket.Messages)2 Packet (com.alibaba.otter.canal.protocol.CanalPacket.Packet)2 ClientIdentity (com.alibaba.otter.canal.protocol.ClientIdentity)2 LogPosition (com.alibaba.otter.canal.protocol.position.LogPosition)2