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()); } }
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; }
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); } } }
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; }
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; }
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; }
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; }