Search in sources :

Example 6 with NotifyHandler

use of info.xiancloud.core.NotifyHandler in project xian by happyyangyuan.

the class RpcServerDefaultHandler method processMsg.

private void processMsg(final ChannelHandlerContext ctx, final JSONObject json) {
    try {
        IdManager.makeSureMsgId(json);
        if (MessageType.isDefaultRequest(json)) {
            UnitRequest request = json.toJavaObject(UnitRequest.class);
            request.getContext().setFromRemote(true);
            String group = request.getContext().getGroup(), unit = request.getContext().getUnit();
            final Consumer<String> backPayloadConsumerOnFailure = payload -> {
                LOG.info("rpc server --> client发送失败了,因此这里复用当前长连接响应消息");
                ctx.writeAndFlush(payload + Constant.RPC_DELIMITER);
            };
            ISequencer.build(group, unit, json).sequence(// call this sender if sequencer is succeeded.
            new DefaultLocalAsyncSender(request, new NotifyHandler() {

                protected void handle(UnitResponse unitResponse) {
                    LocalNodeManager.sendBack(unitResponse, backPayloadConsumerOnFailure);
                }
            }), /*failed directly, call this handler*/
            new NotifyHandler() {

                protected void handle(UnitResponse failureOut) {
                    LocalNodeManager.sendBack(failureOut, backPayloadConsumerOnFailure);
                }
            });
        } else if (MessageType.isDefaultResponse(json)) {
            LOG.debug("这是非常重要的说明:" + "1、客户端发给外部节点的请求期待的响应内容,服务端节在准备好响应结果后立刻与请求端新建一个rpc长连接/复用已存在的长连接,将响应写回去;" + "2、停服务时本地server会先停止,server停止就会关闭socket和server的io线程池,由于server的io线程池和业务线程池是分离的," + "业务线程池会继续运行直到所有任务处理完毕为止。此时,本节点不再有能力接收外部请求了,但是:" + "a.在即将停止的节点内,业务线程池任然需要向外部发送请求以完成业务操作,以及得到响应结果,因此client必须保持打开的。" + "b.在即将停止的节点内,业务线程池需要将本地执行结果返回给远程,这时候server已停,无法复用原管道将结果写回去,因此必须使用依然存活的client" + "将结果写回。" + "因此,有如下逻辑:所有server优先复用当前管道将响应写回去,当SERVER关闭后,业务线程池中后续任务通过未停止的client回写响应结果。");
            UnitResponse response = json.toJavaObject(UnitResponse.class);
            String ssid = response.getContext().getSsid();
            ThreadPoolManager.execute(() -> {
                NotifyHandler callback = LocalNodeManager.handleMap.getIfPresent(ssid);
                if (callback != null) {
                    LocalNodeManager.handleMap.invalidate(ssid);
                    callback.callback(UnitResponse.create(json));
                } else {
                    LOG.error(String.format("ssid=%s的消息没有找到对应的notifyHandler!整个消息内容=%s,", ssid, json), new Throwable());
                }
            }, response.getContext().getMsgId());
        } else
            LOG.error("rpc server端只支持request和response两种消息类型,不支持:" + MessageType.getMessageType(json), new RuntimeException());
    } catch (Throwable e) {
        LOG.error(e);
    } finally {
        MsgIdHolder.clear();
    }
}
Also used : Constant(info.xiancloud.core.Constant) LocalNodeManager(info.xiancloud.core.distribution.LocalNodeManager) UnitRequest(info.xiancloud.core.message.UnitRequest) NotifyHandler(info.xiancloud.core.NotifyHandler) UnitResponse(info.xiancloud.core.message.UnitResponse) ISequencer(info.xiancloud.core.sequence.ISequencer) MessageType(info.xiancloud.core.distribution.MessageType) IdManager(info.xiancloud.core.message.IdManager) DefaultLocalAsyncSender(info.xiancloud.core.message.sender.local.DefaultLocalAsyncSender) Consumer(java.util.function.Consumer) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ThreadPoolManager(info.xiancloud.core.thread_pool.ThreadPoolManager) SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) MsgIdHolder(info.xiancloud.core.util.thread.MsgIdHolder) JSONObject(com.alibaba.fastjson.JSONObject) LOG(info.xiancloud.core.util.LOG) UnitRequest(info.xiancloud.core.message.UnitRequest) UnitResponse(info.xiancloud.core.message.UnitResponse) NotifyHandler(info.xiancloud.core.NotifyHandler) DefaultLocalAsyncSender(info.xiancloud.core.message.sender.local.DefaultLocalAsyncSender)

Example 7 with NotifyHandler

use of info.xiancloud.core.NotifyHandler in project xian by happyyangyuan.

the class RuleController method work.

// 执行
private void work() {
    if (next.equals(END)) {
        end();
    } else {
        Map<String, Object> params = processParams();
        LOG.info("[RuleController] params = " + params);
        Xian.call(next.split("_")[0], next.split("_")[1], params, new NotifyHandler() {

            protected void handle(UnitResponse unitResponse1) {
                unitResponse = unitResponse1;
                processReturnParams();
                callNext();
                work();
            }
        });
    }
}
Also used : UnitResponse(info.xiancloud.core.message.UnitResponse) NotifyHandler(info.xiancloud.core.NotifyHandler)

Example 8 with NotifyHandler

use of info.xiancloud.core.NotifyHandler in project xian by happyyangyuan.

the class BroadcastSender method asyncSend.

@Override
protected void asyncSend() throws UnitOfflineException, UnitUndefinedException {
    List<UnitInstance> list = UnitRouter.singleton.allInstances(Unit.fullName(unitRequest.getContext().getGroup(), unitRequest.getContext().getUnit()));
    UnitMeta.Broadcast broadcast = list.get(0).getPayload().getMeta().getBroadcast();
    final CountDownLatch latch = new CountDownLatch(list.size());
    Collection<Object> piledUpOutput = new ConcurrentLinkedQueue<>();
    final NotifyHandler tmpHandler = new NotifyHandler() {

        protected void handle(UnitResponse output) {
            if (!broadcast.isSuccessDataOnly()) {
                piledUpOutput.add(output);
            } else if (output.succeeded()) {
                piledUpOutput.add(output.getData());
            }
            latch.countDown();
        }
    };
    for (UnitInstance unitInstance : list) {
        if (unitInstance.getNodeId().equals(LocalNodeManager.LOCAL_NODE_ID)) {
            // we must not share the same unitRequest object while sending request concurrently.
            UnitRequest clonedUnitRequest = CloneUtil.cloneBean(unitRequest, UnitRequest.class);
            /*clonedUnitRequest.getContext().setDestinationNodeId(unitInstance.getNodeId()); no need  */
            new RoutedLocalAsyncSender(clonedUnitRequest, tmpHandler).send();
        } else {
            LOG.debug("In order not to share the same unit request object,we clone a new request");
            UnitRequest clonedRequest = CloneUtil.cloneBean(unitRequest, UnitRequest.class);
            clonedRequest.getContext().setDestinationNodeId(unitInstance.getNodeId());
            LocalNodeManager.send(clonedRequest, tmpHandler);
        }
    }
    if (broadcast.isAsync()) {
        callback.callback(UnitResponse.success());
    } else {
        try {
            if (!latch.await(broadcast.getTimeoutInMilli(), TimeUnit.MILLISECONDS)) {
                LOG.error(new TimeoutException());
                callback.callback(UnitResponse.error(Group.CODE_TIME_OUT, piledUpOutput, "Time out while waiting for all the units to response, the data is only part of the result. "));
            } else {
                callback.callback(UnitResponse.success(piledUpOutput));
            }
        } catch (InterruptedException e) {
            callback.callback(UnitResponse.exception(e));
        }
    }
}
Also used : RoutedLocalAsyncSender(info.xiancloud.core.message.sender.local.RoutedLocalAsyncSender) NotifyHandler(info.xiancloud.core.NotifyHandler) UnitInstance(info.xiancloud.core.distribution.service_discovery.UnitInstance) UnitMeta(info.xiancloud.core.UnitMeta) CountDownLatch(java.util.concurrent.CountDownLatch) UnitRequest(info.xiancloud.core.message.UnitRequest) UnitResponse(info.xiancloud.core.message.UnitResponse) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) TimeoutException(java.util.concurrent.TimeoutException)

Example 9 with NotifyHandler

use of info.xiancloud.core.NotifyHandler in project xian by happyyangyuan.

the class ReceiveAndBroadcast method execute.

@Override
public UnitResponse execute(UnitRequest msg) {
    if (msg.getContext().isRouted()) {
        return execute0(msg);
    } else {
        List<UnitInstance> list = new ArrayList<>();
        String application = msg.get("application", String.class);
        List<UnitInstance> unitInstances;
        try {
            unitInstances = UnitRouter.singleton.allInstances(Unit.fullName(getGroupName(), getUnitName()));
        } catch (UnitOfflineException | UnitUndefinedException e) {
            throw new RuntimeException(e);
        }
        if (StringUtil.isEmpty(application) || ALL.equals(application)) {
            list.addAll(unitInstances);
        } else {
            for (UnitInstance clientInfo : unitInstances) {
                if (clientInfo.getName().equals(msg.getString("application"))) {
                    list.add(clientInfo);
                }
            }
        }
        CountDownLatch latch = new CountDownLatch(list.size());
        List<Object> piledUpOutput = new ArrayList<>();
        for (UnitInstance clientInfo : list) {
            LocalNodeManager.send(new UnitRequest().setContext(RequestContext.create().setGroup(getGroupName()).setUnit(getUnitName()).setDestinationNodeId(clientInfo.getNodeId())), new NotifyHandler() {

                protected void handle(UnitResponse unitResponse) {
                    LOG.info("对" + clientInfo.getNodeId() + "执行" + getName() + "操作完毕");
                    if (!successDataOnly()) {
                        piledUpOutput.add(unitResponse);
                    } else if (unitResponse.succeeded()) {
                        piledUpOutput.add(unitResponse.getData());
                    }
                    latch.countDown();
                }
            });
        }
        if (async()) {
            return UnitResponse.success();
        } else {
            try {
                latch.await(timeoutInMilli(), TimeUnit.MILLISECONDS);
                return UnitResponse.success(piledUpOutput);
            } catch (InterruptedException e) {
                return UnitResponse.exception(e);
            }
        }
    }
}
Also used : UnitOfflineException(info.xiancloud.core.distribution.exception.UnitOfflineException) ArrayList(java.util.ArrayList) NotifyHandler(info.xiancloud.core.NotifyHandler) UnitInstance(info.xiancloud.core.distribution.service_discovery.UnitInstance) CountDownLatch(java.util.concurrent.CountDownLatch) UnitUndefinedException(info.xiancloud.core.distribution.exception.UnitUndefinedException) UnitRequest(info.xiancloud.core.message.UnitRequest) UnitResponse(info.xiancloud.core.message.UnitResponse)

Example 10 with NotifyHandler

use of info.xiancloud.core.NotifyHandler in project xian by happyyangyuan.

the class Node method send.

public UnitResponse send(UnitRequest request) {
    String ssid = IdManager.nextSsid();
    request.getContext().setSsid(ssid);
    fillRequestContext(request.getContext());
    UnitResponse unitResponse = UnitResponse.create(true);
    final CountDownLatch latch = new CountDownLatch(1);
    NotifyHandler handler = new NotifyHandler() {

        public void handle(UnitResponse output) {
            UnitResponse.copy(output, output);
            latch.countDown();
        }
    };
    handleMap.put(ssid, handler);
    String payload = JSON.toJSONStringWithDateFormat(request, Constant.DATE_SERIALIZE_FORMAT);
    publisher.p2pPublish(request.getContext().getDestinationNodeId(), payload);
    try {
        if (!latch.await(Constant.UNIT_DEFAULT_TIME_OUT_IN_MILLI, TimeUnit.MILLISECONDS)) {
            handler.setTimeout(true);
            return UnitResponse.error(Group.CODE_TIME_OUT, null, "Response time out!").setContext(UnitResponse.Context.create().setSsid(ssid));
        }
    } catch (InterruptedException e) {
        return UnitResponse.exception(e);
    }
    return unitResponse;
}
Also used : UnitResponse(info.xiancloud.core.message.UnitResponse) NotifyHandler(info.xiancloud.core.NotifyHandler) CountDownLatch(java.util.concurrent.CountDownLatch)

Aggregations

NotifyHandler (info.xiancloud.core.NotifyHandler)16 UnitResponse (info.xiancloud.core.message.UnitResponse)16 UnitRequest (info.xiancloud.core.message.UnitRequest)8 JSONArray (com.alibaba.fastjson.JSONArray)4 HashMap (java.util.HashMap)4 CountDownLatch (java.util.concurrent.CountDownLatch)3 JSONObject (com.alibaba.fastjson.JSONObject)2 MessageType (info.xiancloud.core.distribution.MessageType)2 UnitInstance (info.xiancloud.core.distribution.service_discovery.UnitInstance)2 DefaultLocalAsyncSender (info.xiancloud.core.message.sender.local.DefaultLocalAsyncSender)2 RejectedExecutionException (java.util.concurrent.RejectedExecutionException)2 Constant (info.xiancloud.core.Constant)1 UnitMeta (info.xiancloud.core.UnitMeta)1 LocalNodeManager (info.xiancloud.core.distribution.LocalNodeManager)1 UnitOfflineException (info.xiancloud.core.distribution.exception.UnitOfflineException)1 UnitUndefinedException (info.xiancloud.core.distribution.exception.UnitUndefinedException)1 IdManager (info.xiancloud.core.message.IdManager)1 RoutedLocalAsyncSender (info.xiancloud.core.message.sender.local.RoutedLocalAsyncSender)1 ISequencer (info.xiancloud.core.sequence.ISequencer)1 Stream (info.xiancloud.core.stream.Stream)1