public RemotingCommand invokeSyncImpl(
      final Channel channel, final RemotingCommand request, final long timeoutMillis)
      throws InterruptedException, RemotingSendRequestException, RemotingTimeoutException {
    try {
      final ResponseFuture responseFuture =
          new ResponseFuture(request.getOpaque(), timeoutMillis, null, null);
      this.responseTable.put(request.getOpaque(), responseFuture);
      channel
          .writeAndFlush(request)
          .addListener(
              new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture f) throws Exception {
                  if (f.isSuccess()) {
                    responseFuture.setSendRequestOK(true);
                    return;
                  } else {
                    responseFuture.setSendRequestOK(false);
                  }

                  responseTable.remove(request.getOpaque());
                  responseFuture.setCause(f.cause());
                  responseFuture.putResponse(null);
                  plog.warn(
                      "send a request command to channel <"
                          + channel.remoteAddress()
                          + "> failed.");
                  plog.warn(request.toString());
                }
              });

      RemotingCommand responseCommand = responseFuture.waitResponse(timeoutMillis);
      if (null == responseCommand) {
        // 发送请求成功,读取应答超时
        if (responseFuture.isSendRequestOK()) {
          throw new RemotingTimeoutException(
              RemotingHelper.parseChannelRemoteAddr(channel),
              timeoutMillis,
              responseFuture.getCause());
        }
        // 发送请求失败
        else {
          throw new RemotingSendRequestException(
              RemotingHelper.parseChannelRemoteAddr(channel), responseFuture.getCause());
        }
      }

      return responseCommand;
    } finally {
      this.responseTable.remove(request.getOpaque());
    }
  }
示例#2
0
  private RemotingCommand updateAndCreateTopic(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final CreateTopicRequestHeader requestHeader =
        (CreateTopicRequestHeader)
            request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
    log.info(
        "updateAndCreateTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    // Topic名字是否与保留字段冲突
    if (requestHeader
        .getTopic()
        .equals(this.brokerController.getBrokerConfig().getBrokerClusterName())) {
      String errorMsg =
          "the topic[" + requestHeader.getTopic() + "] is conflict with system reserved words.";
      log.warn(errorMsg);
      response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
      response.setRemark(errorMsg);
      return response;
    }

    TopicConfig topicConfig = new TopicConfig(requestHeader.getTopic());
    topicConfig.setReadQueueNums(requestHeader.getReadQueueNums());
    topicConfig.setWriteQueueNums(requestHeader.getWriteQueueNums());
    topicConfig.setTopicFilterType(requestHeader.getTopicFilterTypeEnum());
    topicConfig.setPerm(requestHeader.getPerm());

    this.brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand registerMessageFilterClass(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final RegisterMessageFilterClassRequestHeader requestHeader =
        (RegisterMessageFilterClassRequestHeader)
            request.decodeCommandCustomHeader(RegisterMessageFilterClassRequestHeader.class);

    try {
      boolean ok =
          this.filtersrvController
              .getFilterClassManager()
              .registerFilterClass(
                  requestHeader.getConsumerGroup(), //
                  requestHeader.getTopic(), //
                  requestHeader.getClassName(), //
                  requestHeader.getClassCRC(), //
                  request.getBody()); // Body传输的是Java Source,必须UTF-8编码
      if (!ok) {
        throw new Exception("registerFilterClass error");
      }
    } catch (Exception e) {
      response.setCode(ResponseCode.SYSTEM_ERROR);
      response.setRemark(RemotingHelper.exceptionSimpleDesc(e));
      return response;
    }

    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
  }
  public void processResponseCommand(ChannelHandlerContext ctx, RemotingCommand cmd) {
    final ResponseFuture responseFuture = responseTable.get(cmd.getOpaque());
    if (responseFuture != null) {
      responseFuture.setResponseCommand(cmd);

      responseFuture.release();

      // 异步调用
      if (responseFuture.getInvokeCallback() != null) {
        boolean runInThisThread = false;
        ExecutorService executor = this.getCallbackExecutor();
        if (executor != null) {
          try {
            executor.submit(
                new Runnable() {
                  @Override
                  public void run() {
                    try {
                      responseFuture.executeInvokeCallback();
                    } catch (Throwable e) {
                      plog.warn("excute callback in executor exception, and callback throw", e);
                    }
                  }
                });
          } catch (Exception e) {
            runInThisThread = true;
            plog.warn("excute callback in executor exception, maybe executor busy", e);
          }
        } else {
          runInThisThread = true;
        }

        if (runInThisThread) {
          try {
            responseFuture.executeInvokeCallback();
          } catch (Throwable e) {
            plog.warn("executeInvokeCallback Exception", e);
          }
        }
      }
      // 同步调用
      else {
        responseFuture.putResponse(cmd);
      }
    } else {
      plog.warn(
          "receive response, but not matched any request, "
              + RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
      plog.warn(cmd.toString());
    }

    responseTable.remove(cmd.getOpaque());
  }
  public RemotingCommand getConsumerListByGroup(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response =
        RemotingCommand.createResponseCommand(GetConsumerListByGroupResponseHeader.class);
    final GetConsumerListByGroupRequestHeader requestHeader =
        (GetConsumerListByGroupRequestHeader)
            request.decodeCommandCustomHeader(GetConsumerListByGroupRequestHeader.class);

    ConsumerGroupInfo consumerGroupInfo =
        this.brokerController
            .getConsumerManager()
            .getConsumerGroupInfo(requestHeader.getConsumerGroup());
    if (consumerGroupInfo != null) {
      List<String> clientIds = consumerGroupInfo.getAllClientId();
      if (!clientIds.isEmpty()) {
        GetConsumerListByGroupResponseBody body = new GetConsumerListByGroupResponseBody();
        body.setConsumerIdList(clientIds);
        response.setBody(body.encode());
        response.setCode(ResponseCode.SUCCESS);
        response.setRemark(null);
        return response;
      } else {
        log.warn(
            "getAllClientId failed, {} {}",
            requestHeader.getConsumerGroup(),
            RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
      }
    } else {
      log.warn(
          "getConsumerGroupInfo failed, {} {}",
          requestHeader.getConsumerGroup(),
          RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
    }

    response.setCode(ResponseCode.SYSTEM_ERROR);
    response.setRemark("no consumer for this group, " + requestHeader.getConsumerGroup());
    return response;
  }
示例#6
0
  private RemotingCommand deleteTopic(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    DeleteTopicRequestHeader requestHeader =
        (DeleteTopicRequestHeader)
            request.decodeCommandCustomHeader(DeleteTopicRequestHeader.class);

    log.info("deleteTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic());

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
 public void invokeOnewayImpl(
     final Channel channel, final RemotingCommand request, final long timeoutMillis)
     throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException,
         RemotingSendRequestException {
   request.markOnewayRPC();
   boolean acquired = this.semaphoreOneway.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS);
   if (acquired) {
     final SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreOneway);
     try {
       channel
           .writeAndFlush(request)
           .addListener(
               new ChannelFutureListener() {
                 @Override
                 public void operationComplete(ChannelFuture f) throws Exception {
                   once.release();
                   if (!f.isSuccess()) {
                     plog.warn(
                         "send a request command to channel <"
                             + channel.remoteAddress()
                             + "> failed.");
                     plog.warn(request.toString());
                   }
                 }
               });
     } catch (Exception e) {
       once.release();
       plog.warn(
           "write send a request command to channel <" + channel.remoteAddress() + "> failed.");
       throw new RemotingSendRequestException(RemotingHelper.parseChannelRemoteAddr(channel), e);
     }
   } else {
     if (timeoutMillis <= 0) {
       throw new RemotingTooMuchRequestException("invokeOnewayImpl invoke too fast");
     } else {
       String info =
           String.format(
               "invokeOnewayImpl tryAcquire semaphore timeout, %dms, waiting thread nums: %d semaphoreAsyncValue: %d", //
               timeoutMillis, //
               this.semaphoreAsync.getQueueLength(), //
               this.semaphoreAsync.availablePermits() //
               );
       plog.warn(info);
       plog.warn(request.toString());
       throw new RemotingTimeoutException(info);
     }
   }
 }
示例#8
0
  private RemotingCommand updateAndCreateSubscriptionGroup(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);

    log.info(
        "updateAndCreateSubscriptionGroup called by {}",
        RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    SubscriptionGroupConfig config =
        RemotingSerializable.decode(request.getBody(), SubscriptionGroupConfig.class);
    if (config != null) {
      this.brokerController.getSubscriptionGroupManager().updateSubscriptionGroupConfig(config);
    }

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
示例#9
0
  private RemotingCommand getConsumerConnectionList(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetConsumerConnectionListRequestHeader requestHeader =
        (GetConsumerConnectionListRequestHeader)
            request.decodeCommandCustomHeader(GetConsumerConnectionListRequestHeader.class);

    ConsumerGroupInfo consumerGroupInfo =
        this.brokerController
            .getConsumerManager()
            .getConsumerGroupInfo(requestHeader.getConsumerGroup());
    if (consumerGroupInfo != null) {
      ConsumerConnection bodydata = new ConsumerConnection();
      bodydata.setConsumeFromWhere(consumerGroupInfo.getConsumeFromWhere());
      bodydata.setConsumeType(consumerGroupInfo.getConsumeType());
      bodydata.setMessageModel(consumerGroupInfo.getMessageModel());
      bodydata.getSubscriptionTable().putAll(consumerGroupInfo.getSubscriptionTable());

      Iterator<Map.Entry<Channel, ClientChannelInfo>> it =
          consumerGroupInfo.getChannelInfoTable().entrySet().iterator();
      while (it.hasNext()) {
        ClientChannelInfo info = it.next().getValue();
        Connection connection = new Connection();
        connection.setClientId(info.getClientId());
        connection.setLanguage(info.getLanguage());
        connection.setVersion(info.getVersion());
        connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel()));

        bodydata.getConnectionSet().add(connection);
      }

      byte[] body = bodydata.encode();
      response.setBody(body);
      response.setCode(ResponseCode.SUCCESS_VALUE);
      response.setRemark(null);

      return response;
    }

    response.setCode(MQResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST_VALUE);
    response.setRemark("the consumer group[" + requestHeader.getConsumerGroup() + "] not online");
    return response;
  }
  @Override
  public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request)
      throws Exception {
    if (log.isDebugEnabled()) {
      log.debug(
          "receive request, {} {} {}", //
          request.getCode(), //
          RemotingHelper.parseChannelRemoteAddr(ctx.channel()), //
          request);
    }

    switch (request.getCode()) {
      case RequestCode.REGISTER_MESSAGE_FILTER_CLASS:
        return registerMessageFilterClass(ctx, request);
      case RequestCode.PULL_MESSAGE:
        return pullMessageForward(ctx, request);
    }

    return null;
  }
示例#11
0
  private RemotingCommand getProducerConnectionList(
      ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetProducerConnectionListRequestHeader requestHeader =
        (GetProducerConnectionListRequestHeader)
            request.decodeCommandCustomHeader(GetProducerConnectionListRequestHeader.class);

    ConsumerConnection bodydata = new ConsumerConnection();
    HashMap<Channel, ClientChannelInfo> channelInfoHashMap =
        this.brokerController
            .getProducerManager()
            .getGroupChannelTable()
            .get(requestHeader.getProducerGroup());
    if (channelInfoHashMap != null) {
      Iterator<Map.Entry<Channel, ClientChannelInfo>> it = channelInfoHashMap.entrySet().iterator();
      while (it.hasNext()) {
        ClientChannelInfo info = it.next().getValue();
        Connection connection = new Connection();
        connection.setClientId(info.getClientId());
        connection.setLanguage(info.getLanguage());
        connection.setVersion(info.getVersion());
        connection.setClientAddr(RemotingHelper.parseChannelRemoteAddr(info.getChannel()));

        bodydata.getConnectionSet().add(connection);
      }

      byte[] body = bodydata.encode();
      response.setBody(body);
      response.setCode(ResponseCode.SUCCESS_VALUE);
      response.setRemark(null);
      return response;
    }

    response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
    response.setRemark("the producer group[" + requestHeader.getProducerGroup() + "] not exist");
    return response;
  }
示例#12
0
  private RemotingCommand updateBrokerConfig(ChannelHandlerContext ctx, RemotingCommand request) {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);

    log.info(
        "updateBrokerConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));

    byte[] body = request.getBody();
    if (body != null) {
      try {
        String bodyStr = new String(body, MixAll.DEFAULT_CHARSET);
        Properties properties = MixAll.string2Properties(bodyStr);
        if (properties != null) {
          log.info(
              "updateBrokerConfig, new config: "
                  + properties
                  + " client: "
                  + ctx.channel().remoteAddress());
          this.brokerController.updateAllConfig(properties);
        } else {
          log.error("string2Properties error");
          response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
          response.setRemark("string2Properties error");
          return response;
        }
      } catch (UnsupportedEncodingException e) {
        log.error("", e);
        response.setCode(ResponseCode.SYSTEM_ERROR_VALUE);
        response.setRemark("UnsupportedEncodingException " + e);
        return response;
      }
    }

    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  public void invokeAsyncImpl(
      final Channel channel,
      final RemotingCommand request,
      final long timeoutMillis,
      final InvokeCallback invokeCallback)
      throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException,
          RemotingSendRequestException {
    boolean acquired = this.semaphoreAsync.tryAcquire(timeoutMillis, TimeUnit.MILLISECONDS);
    if (acquired) {
      final SemaphoreReleaseOnlyOnce once = new SemaphoreReleaseOnlyOnce(this.semaphoreAsync);

      final ResponseFuture responseFuture =
          new ResponseFuture(request.getOpaque(), timeoutMillis, invokeCallback, once);
      this.responseTable.put(request.getOpaque(), responseFuture);
      try {
        channel
            .writeAndFlush(request)
            .addListener(
                new ChannelFutureListener() {
                  @Override
                  public void operationComplete(ChannelFuture f) throws Exception {
                    if (f.isSuccess()) {
                      responseFuture.setSendRequestOK(true);
                      return;
                    } else {
                      responseFuture.setSendRequestOK(false);
                    }

                    responseFuture.putResponse(null);
                    responseTable.remove(request.getOpaque());
                    try {
                      responseFuture.executeInvokeCallback();
                    } catch (Throwable e) {
                      plog.warn(
                          "excute callback in writeAndFlush addListener, and callback throw", e);
                    } finally {
                      responseFuture.release();
                    }

                    plog.warn(
                        "send a request command to channel <{}> failed.",
                        RemotingHelper.parseChannelRemoteAddr(channel));
                    plog.warn(request.toString());
                  }
                });
      } catch (Exception e) {
        responseFuture.release();
        plog.warn(
            "send a request command to channel <"
                + RemotingHelper.parseChannelRemoteAddr(channel)
                + "> Exception",
            e);
        throw new RemotingSendRequestException(RemotingHelper.parseChannelRemoteAddr(channel), e);
      }
    } else {
      if (timeoutMillis <= 0) {
        throw new RemotingTooMuchRequestException("invokeAsyncImpl invoke too fast");
      } else {
        String info =
            String.format(
                "invokeAsyncImpl tryAcquire semaphore timeout, %dms, waiting thread nums: %d semaphoreAsyncValue: %d", //
                timeoutMillis, //
                this.semaphoreAsync.getQueueLength(), //
                this.semaphoreAsync.availablePermits() //
                );
        plog.warn(info);
        plog.warn(request.toString());
        throw new RemotingTimeoutException(info);
      }
    }
  }
  public void processRequestCommand(final ChannelHandlerContext ctx, final RemotingCommand cmd) {
    final Pair<NettyRequestProcessor, ExecutorService> matched =
        this.processorTable.get(cmd.getCode());
    final Pair<NettyRequestProcessor, ExecutorService> pair =
        null == matched ? this.defaultRequestProcessor : matched;

    if (pair != null) {
      Runnable run =
          new Runnable() {
            @Override
            public void run() {
              try {
                RPCHook rpcHook = NettyRemotingAbstract.this.getRPCHook();
                if (rpcHook != null) {
                  rpcHook.doBeforeRequest(
                      RemotingHelper.parseChannelRemoteAddr(ctx.channel()), cmd);
                }

                final RemotingCommand response = pair.getObject1().processRequest(ctx, cmd);
                if (rpcHook != null) {
                  rpcHook.doAfterResponse(cmd, response);
                }

                // Oneway形式忽略应答结果
                if (!cmd.isOnewayRPC()) {
                  if (response != null) {
                    response.setOpaque(cmd.getOpaque());
                    response.markResponseType();
                    try {
                      ctx.writeAndFlush(response);
                    } catch (Throwable e) {
                      plog.error("process request over, but response failed", e);
                      plog.error(cmd.toString());
                      plog.error(response.toString());
                    }
                  } else {
                    // 收到请求,但是没有返回应答,可能是processRequest中进行了应答,忽略这种情况
                  }
                }
              } catch (Throwable e) {
                plog.error("process request exception", e);
                plog.error(cmd.toString());

                if (!cmd.isOnewayRPC()) {
                  final RemotingCommand response =
                      RemotingCommand.createResponseCommand(
                          RemotingSysResponseCode.SYSTEM_ERROR, //
                          RemotingHelper.exceptionSimpleDesc(e));
                  response.setOpaque(cmd.getOpaque());
                  ctx.writeAndFlush(response);
                }
              }
            }
          };

      try {
        // 这里需要做流控,要求线程池对应的队列必须是有大小限制的
        pair.getObject2().submit(run);
      } catch (RejectedExecutionException e) {
        plog.warn(
            RemotingHelper.parseChannelRemoteAddr(ctx.channel()) //
                + ", too many requests and system thread pool busy, RejectedExecutionException " //
                + pair.getObject2().toString() //
                + " request code: "
                + cmd.getCode());
        if (!cmd.isOnewayRPC()) {
          final RemotingCommand response =
              RemotingCommand.createResponseCommand(
                  RemotingSysResponseCode.SYSTEM_BUSY,
                  "too many requests and system thread pool busy, please try another server");
          response.setOpaque(cmd.getOpaque());
          ctx.writeAndFlush(response);
        }
      }
    } else {
      String error = " request type " + cmd.getCode() + " not supported";
      final RemotingCommand response =
          RemotingCommand.createResponseCommand(
              RemotingSysResponseCode.REQUEST_CODE_NOT_SUPPORTED, error);
      response.setOpaque(cmd.getOpaque());
      ctx.writeAndFlush(response);
      plog.error(RemotingHelper.parseChannelRemoteAddr(ctx.channel()) + error);
    }
  }
  public RemotingCommand heartBeat(ChannelHandlerContext ctx, RemotingCommand request) {
    RemotingCommand response = RemotingCommand.createResponseCommand(null);

    HeartbeatData heartbeatData = HeartbeatData.decode(request.getBody(), HeartbeatData.class);

    ClientChannelInfo clientChannelInfo =
        new ClientChannelInfo( //
            ctx.channel(), //
            heartbeatData.getClientID(), //
            request.getLanguage(), //
            request.getVersion() //
            );

    // 注册Consumer
    for (ConsumerData data : heartbeatData.getConsumerDataSet()) {
      SubscriptionGroupConfig subscriptionGroupConfig =
          this.brokerController
              .getSubscriptionGroupManager()
              .findSubscriptionGroupConfig(data.getGroupName());
      if (null != subscriptionGroupConfig) {
        String newTopic = MixAll.getRetryTopic(data.getGroupName());
        this.brokerController
            .getTopicConfigManager()
            .createTopicInSendMessageBackMethod( //
                newTopic, //
                subscriptionGroupConfig.getRetryQueueNums(), //
                PermName.PERM_WRITE | PermName.PERM_READ);
      }

      boolean changed =
          this.brokerController
              .getConsumerManager()
              .registerConsumer( //
                  data.getGroupName(), //
                  clientChannelInfo, //
                  data.getConsumeType(), //
                  data.getMessageModel(), //
                  data.getConsumeFromWhere(), //
                  data.getSubscriptionDataSet() //
                  );

      if (changed) {
        log.info(
            "registerConsumer info changed {} {}", //
            data.toString(), //
            RemotingHelper.parseChannelRemoteAddr(ctx.channel()) //
            );
      }
    }

    // 注册Producer
    for (ProducerData data : heartbeatData.getProducerDataSet()) {
      this.brokerController
          .getProducerManager()
          .registerProducer(data.getGroupName(), clientChannelInfo);
    }

    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
  }