private void stopCanalInstanceIfNecessary(ClientIdentity clientIdentity) {
   List<ClientIdentity> clientIdentitys =
       embededServer.listAllSubscribe(clientIdentity.getDestination());
   if (clientIdentitys != null
       && clientIdentitys.size() == 1
       && clientIdentitys.contains(clientIdentity)) {
     ServerRunningMonitor runningMonitor =
         ServerRunningMonitors.getRunningMonitor(clientIdentity.getDestination());
     if (runningMonitor.isStart()) {
       runningMonitor.stop();
     }
   }
 }
  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");
    }
  }