All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.dts.client.remoting.proxy.NodeClientSystemInvocationHandler Maven / Gradle / Ivy

package com.alibaba.dts.client.remoting.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.dts.client.executor.job.context.ClientContextImpl;
import com.alibaba.dts.common.constants.Constants;
import com.alibaba.dts.common.context.InvocationContext;
import com.alibaba.dts.common.domain.remoting.RemoteMachine;
import com.alibaba.dts.common.domain.remoting.protocol.InvokeMethod;
import com.alibaba.dts.common.logger.SchedulerXLoggerFactory;
import com.alibaba.dts.common.logger.innerlog.Logger;
import com.alibaba.dts.common.proxy.ProxyService;
import com.alibaba.dts.common.remoting.protocol.RemotingCommand;
import com.alibaba.dts.common.remoting.protocol.RemotingSerializable;
import com.alibaba.dts.common.util.BytesUtil;
import com.alibaba.dts.common.util.RemotingUtil;
import com.alibaba.dts.common.util.StringUtil;
import com.alibaba.fastjson.JSON;

import io.netty.channel.Channel;


/**
 * Node客户端代理发出请求的调用接口
 *
 * @author Ronan Zhan
 */
public class NodeClientSystemInvocationHandler implements InvocationHandler, Constants {

    private static final Logger logger = SchedulerXLoggerFactory.getLogger(NodeClientSystemInvocationHandler.class);

    private ClientContextImpl clientContext;

    public NodeClientSystemInvocationHandler(ClientContextImpl clientContext) {
        this.clientContext = clientContext;
    }

    private Map missConnectCounter = new ConcurrentHashMap();

    /**
     * 拦截方法调用各项参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        RemoteMachine remoteMachine = InvocationContext.acquireRemoteMachine();

        Channel channel = clientContext.getNodeRemoting().getAndCreateChannel(remoteMachine.getSystemRemoteAddress());
        String address = remoteMachine.getSystemRemoteAddress();
        if (null == channel) {
            Integer count = missConnectCounter.get(address);
            if (count == null) {
                missConnectCounter.put(address, 1);
            } else {
                missConnectCounter.put(address, ++count);
                if (count >= 4 && count % 4 == 0) {
                    logger.info("[NodeClientSystemInvocationHandler]: getAndCreateChannel error"
                            + ", server:" + remoteMachine.getSystemRemoteAddress()
                            + ", timeout:" + remoteMachine.getTimeout()
                            + ", methodName:" + method.getName()
                            + ", failed count: " + count);
                }
            }
            InvocationContext.clean();
            return null;
        } else {
            missConnectCounter.put(address, 0);
        }
        remoteMachine.setLocalAddress(RemotingUtil.socketAddress2String(channel.localAddress()));
//        remoteMachine.setNodeListenPort(clientContext.getNodeConfig().getListenPort());
//        remoteMachine.setNodeSystemListenPort(clientContext.getNodeConfig().getSystemListenPort());

        Class[] parameterTypesClass = method.getParameterTypes();
        String[] parameterTypesString = new String[parameterTypesClass.length];
        String[] arguments = new String[parameterTypesClass.length];
        for (int i = 0; i < parameterTypesClass.length; i++) {
            parameterTypesString[i] = parameterTypesClass[i].getName();
            arguments[i] = RemotingSerializable.toJson(args[i], false);
        }
        InvokeMethod invokeMethod = new InvokeMethod(remoteMachine, method.getName(), parameterTypesString, arguments, method.getReturnType().getName());
        byte[] requestBody = null;
        try {
            requestBody = BytesUtil.objectToBytes(invokeMethod.toString());
        } catch (Throwable e) {
            logger.error("[NodeClientSystemInvocationHandler]: objectToBytes error"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName(), e);
            InvocationContext.clean();
            return null;
        }
        if (null == requestBody) {
            logger.error("[NodeClientSystemInvocationHandler]: requestBody is null"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName());
            InvocationContext.clean();
            return null;
        }
        RemotingCommand request = new RemotingCommand();
        request.setBody(requestBody);
        RemotingCommand response = null;
        try {
            response = clientContext.getNodeRemoting().invokeSync(remoteMachine.getSystemRemoteAddress(), request, remoteMachine.getTimeout());
        } catch (Throwable e) {
            if (method.getName().equals("connect")) {
                logger.info("[ClientInvocationHandler]: invoke error"
                        + ", server:" + remoteMachine.getRemoteAddress()
                        + ", timeout:" + remoteMachine.getTimeout()
                        + ", methodName:" + method.getName(), e);
            } else {
                logger.error("[ClientInvocationHandler]: invoke error"
                        + ", server:" + remoteMachine.getRemoteAddress()
                        + ", timeout:" + remoteMachine.getTimeout()
                        + ", methodName:" + method.getName(), e);
            }
        }
        InvocationContext.clean();
        if (null == response) {
            logger.info("[NodeClientSystemInvocationHandler]: response is null"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName());

            return null;
        }
        Class returnClass = ProxyService.getClass(invokeMethod.getReturnType());
        if (void.class == returnClass) {

            return null;
        }
        byte[] responseBody = response.getBody();
        if (null == responseBody) {
            logger.error("[NodeClientSystemInvocationHandler]: responseBody is null"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName());

            return null;
        }

        String json = null;
        try {
            json = (String) BytesUtil.bytesToObject(responseBody);
        } catch (Throwable e) {
            logger.error("[NodeClientSystemInvocationHandler]: bytesToObject error"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName(), e);
        }
        if (StringUtil.isBlank(json)) {
            logger.error("[NodeClientSystemInvocationHandler]: json is null"
                    + ", server:" + remoteMachine.getSystemRemoteAddress()
                    + ", timeout:" + remoteMachine.getTimeout()
                    + ", methodName:" + method.getName());

            return null;
        }

        Type returnType = method.getGenericReturnType();
        if (returnType instanceof ParameterizedType) {
            return JSON.parseObject(json, (ParameterizedType) returnType);
        }
        return RemotingSerializable.fromJson(json, returnClass);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy