Beispiel #1
0
  public Message getWithoutAck(int batchSize) throws CanalClientException {
    waitClientRunning();
    try {
      int size = (batchSize <= 0) ? 1000 : batchSize;
      writeWithHeader(
          channel,
          Packet.newBuilder()
              .setType(PacketType.GET)
              .setBody(
                  Get.newBuilder()
                      .setDestination(clientIdentity.getDestination())
                      .setClientId(String.valueOf(clientIdentity.getClientId()))
                      .setFetchSize(size)
                      .build()
                      .toByteString())
              .build()
              .toByteArray());
      //
      Packet p = Packet.parseFrom(readNextPacket(channel));
      switch (p.getType()) {
        case MESSAGES:
          {
            if (!p.getCompression().equals(Compression.NONE)) {
              throw new CanalClientException("compression is not supported in this connector");
            }

            Messages messages = Messages.parseFrom(p.getBody());
            Message result = new Message(messages.getBatchId());
            for (ByteString byteString : messages.getMessagesList()) {
              result.addEntry(Entry.parseFrom(byteString));
            }
            return result;
          }
        case ACK:
          {
            Ack ack = Ack.parseFrom(p.getBody());
            throw new CanalClientException(
                "something goes wrong with reason: " + ack.getErrorMessage());
          }
        default:
          {
            throw new CanalClientException("unexpected packet type: " + p.getType());
          }
      }
    } catch (IOException e) {
      throw new CanalClientException(e);
    }
  }
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    logger.info("message receives in session handler...");
    ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
    Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array());
    ClientIdentity clientIdentity = null;
    try {
      switch (packet.getType()) {
        case SUBSCRIPTION:
          Sub sub = Sub.parseFrom(packet.getBody());
          if (StringUtils.isNotEmpty(sub.getDestination())
              && StringUtils.isNotEmpty(sub.getClientId())) {
            clientIdentity =
                new ClientIdentity(
                    sub.getDestination(), Short.valueOf(sub.getClientId()), sub.getFilter());
            MDC.put("destination", clientIdentity.getDestination());
            embededServer.subscribe(clientIdentity);

            // 尝试启动,如果已经启动,忽略
            if (!embededServer.isStart(clientIdentity.getDestination())) {
              ServerRunningMonitor runningMonitor =
                  ServerRunningMonitors.getRunningMonitor(clientIdentity.getDestination());
              if (!runningMonitor.isStart()) {
                runningMonitor.start();
              }
            }

            ctx.setAttachment(clientIdentity); // 设置状态数据
            NettyUtils.ack(ctx.getChannel(), null);
          } else {
            NettyUtils.error(
                401,
                MessageFormatter.format("destination or clientId is null", sub.toString())
                    .getMessage(),
                ctx.getChannel(),
                null);
          }
          break;
        case UNSUBSCRIPTION:
          Unsub unsub = Unsub.parseFrom(packet.getBody());
          if (StringUtils.isNotEmpty(unsub.getDestination())
              && StringUtils.isNotEmpty(unsub.getClientId())) {
            clientIdentity =
                new ClientIdentity(
                    unsub.getDestination(), Short.valueOf(unsub.getClientId()), unsub.getFilter());
            MDC.put("destination", clientIdentity.getDestination());
            embededServer.unsubscribe(clientIdentity);
            stopCanalInstanceIfNecessary(clientIdentity); // 尝试关闭
            NettyUtils.ack(ctx.getChannel(), null);
          } else {
            NettyUtils.error(
                401,
                MessageFormatter.format("destination or clientId is null", unsub.toString())
                    .getMessage(),
                ctx.getChannel(),
                null);
          }
          break;
        case GET:
          Get get = CanalPacket.Get.parseFrom(packet.getBody());
          if (StringUtils.isNotEmpty(get.getDestination())
              && StringUtils.isNotEmpty(get.getClientId())) {
            clientIdentity =
                new ClientIdentity(get.getDestination(), Short.valueOf(get.getClientId()));
            MDC.put("destination", clientIdentity.getDestination());
            Message message = embededServer.getWithoutAck(clientIdentity, get.getFetchSize());

            Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder();
            packetBuilder.setType(PacketType.MESSAGES);

            Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
            messageBuilder.setBatchId(message.getId());
            if (message.getId() != -1 && !CollectionUtils.isEmpty(message.getEntries())) {
              for (Entry entry : message.getEntries()) {
                messageBuilder.addMessages(entry.toByteString());
              }
            }
            packetBuilder.setBody(messageBuilder.build().toByteString());
            NettyUtils.write(ctx.getChannel(), packetBuilder.build().toByteArray(), null); // 输出数据
          } else {
            NettyUtils.error(
                401,
                MessageFormatter.format("destination or clientId is null", get.toString())
                    .getMessage(),
                ctx.getChannel(),
                null);
          }
          break;
        case CLIENTACK:
          ClientAck ack = CanalPacket.ClientAck.parseFrom(packet.getBody());
          MDC.put("destination", ack.getDestination());
          if (StringUtils.isNotEmpty(ack.getDestination())
              && StringUtils.isNotEmpty(ack.getClientId())) {
            if (ack.getBatchId() == 0L) {
              NettyUtils.error(
                  402,
                  MessageFormatter.format("batchId should assign value", ack.toString())
                      .getMessage(),
                  ctx.getChannel(),
                  null);
            } else if (ack.getBatchId() == -1L) { // -1代表上一次get没有数据,直接忽略之
              // donothing
            } else {
              clientIdentity =
                  new ClientIdentity(ack.getDestination(), Short.valueOf(ack.getClientId()));
              embededServer.ack(clientIdentity, ack.getBatchId());
            }
          } else {
            NettyUtils.error(
                401,
                MessageFormatter.format("destination or clientId is null", ack.toString())
                    .getMessage(),
                ctx.getChannel(),
                null);
          }
          break;
        case CLIENTROLLBACK:
          ClientRollback rollback = CanalPacket.ClientRollback.parseFrom(packet.getBody());
          MDC.put("destination", rollback.getDestination());
          if (StringUtils.isNotEmpty(rollback.getDestination())
              && StringUtils.isNotEmpty(rollback.getClientId())) {
            clientIdentity =
                new ClientIdentity(
                    rollback.getDestination(), Short.valueOf(rollback.getClientId()));
            if (rollback.getBatchId() == 0L) {
              embededServer.rollback(clientIdentity); // 回滚所有批次
            } else {
              embededServer.rollback(clientIdentity, rollback.getBatchId()); // 只回滚单个批次
            }
          } else {
            NettyUtils.error(
                401,
                MessageFormatter.format("destination or clientId is null", rollback.toString())
                    .getMessage(),
                ctx.getChannel(),
                null);
          }
          break;
        default:
          NettyUtils.error(
              400,
              MessageFormatter.format("packet type={} is NOT supported!", packet.getType())
                  .getMessage(),
              ctx.getChannel(),
              null);
          break;
      }
    } catch (Throwable exception) {
      NettyUtils.error(
          400,
          MessageFormatter.format(
                  "something goes wrong with channel:{}, exception={}",
                  ctx.getChannel(),
                  ExceptionUtils.getStackTrace(exception))
              .getMessage(),
          ctx.getChannel(),
          null);
    } finally {
      MDC.remove("destination");
    }
  }