com.bfd.harpc.client.DefaultInvoker.java Source code

Java tutorial

Introduction

Here is the source code for com.bfd.harpc.client.DefaultInvoker.java

Source

/**
 * Copyright (C) 2015 Baifendian Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bfd.harpc.client;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.SocketException;

import org.apache.avro.AvroRemoteException;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bfd.harpc.RpcException;
import com.bfd.harpc.common.ServerNode;
import com.bfd.harpc.loadbalance.LoadBalancer;
import com.bfd.harpc.loadbalance.RequestTracker;
import com.bfd.harpc.loadbalance.common.DynamicHostSet;
import com.bfd.harpc.monitor.RpcMonitor;
import com.bfd.harpc.monitor.StatisticsInfo;

/**
 * invoker
 * <p>
 * 
 * @author : dsfan
 * @date : 2015-6-3
 */
public class DefaultInvoker<T> implements Invoker {

    /** LOGGER */
    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    /** {@link GenericKeyedObjectPool}<{@link ServerNode},{@link T}> */
    private final GenericKeyedObjectPool<ServerNode, T> pool;

    /** {@link LoadBalancer}<{@link ServerNode}> */
    private final LoadBalancer<ServerNode> loadBalancer;

    /** ? */
    private final int retry;

    /** {@link RpcMonitor} */
    private final RpcMonitor monitor;

    /** client{@link ServerNode} */
    private final ServerNode clientNode;

    /** {@link DynamicHostSet} */
    private final DynamicHostSet hostSet;

    /**
     * @param clientNode
     * @param pool
     * @param loadBalancer
     * @param retry
     * @param monitor
     * @param hostSet
     */
    public DefaultInvoker(ServerNode clientNode, GenericKeyedObjectPool<ServerNode, T> pool,
            LoadBalancer<ServerNode> loadBalancer, int retry, RpcMonitor monitor, DynamicHostSet hostSet) {
        this.clientNode = clientNode;
        this.pool = pool;
        this.loadBalancer = loadBalancer;
        this.retry = retry;
        this.monitor = monitor;
        this.hostSet = hostSet;
    }

    @Override
    public Object invoke(Method method, Object[] args) throws RpcException {
        T client = null;
        ServerNode serverNode = null;
        Throwable exception = null;

        long startTime;
        for (int i = 0; i == 0 || i < retry + 1; i++) {
            startTime = System.currentTimeMillis();
            StatisticsInfo info = new StatisticsInfo();
            try {
                serverNode = loadBalancer.nextBackend();
                if (serverNode == null) {
                    continue;
                }

                // System.out.println(serverNode);
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Invoke to {}.", serverNode);
                }
                client = pool.borrowObject(serverNode);
                Object result = method.invoke(client, args);

                // load balancestatistics
                loadBalancer.requestResult(serverNode, RequestTracker.RequestResult.SUCCESS,
                        System.currentTimeMillis() - startTime);
                info.setSuccess(1);

                return result;
            } catch (InvocationTargetException ite) {// XXX:InvocationTargetException?method.invoke()
                Throwable cause = ite.getCause();
                if (cause != null) {
                    if (cause instanceof TTransportException || cause instanceof AvroRemoteException) {
                        // load balancestatistics
                        loadBalancer.requestResult(serverNode, RequestTracker.RequestResult.TIMEOUT,
                                System.currentTimeMillis() - startTime);
                        hostSet.addDeadInstance(serverNode); // dead?
                        info.setFailure(1);
                        exception = cause;
                        try {
                            // XXX:pool,???
                            // ??socket?socket???
                            if (cause.getCause() != null && cause.getCause() instanceof SocketException) {
                                pool.clear(serverNode);
                            } else {
                                // XXX:??
                                pool.invalidateObject(serverNode, client);
                            }
                        } catch (Exception e) {
                            LOGGER.error(e.getMessage(), e);
                        }
                        client = null; // ?returnpool
                    } else {
                        loadBalancer.requestResult(serverNode, RequestTracker.RequestResult.FAILED,
                                System.currentTimeMillis() - startTime);
                        info.setFailure(1);
                        exception = cause;
                    }
                } else {
                    loadBalancer.requestResult(serverNode, RequestTracker.RequestResult.FAILED,
                            System.currentTimeMillis() - startTime);
                    info.setFailure(1);
                    exception = ite;
                }
            } catch (Throwable e) {
                // load balancestatistics
                loadBalancer.requestResult(serverNode, RequestTracker.RequestResult.FAILED,
                        System.currentTimeMillis() - startTime);
                info.setFailure(1);
                exception = e;
            } finally {
                if (client != null) {
                    try {
                        pool.returnObject(serverNode, client);
                    } catch (Exception e) {
                        LOGGER.error(e.getMessage(), e);
                    }
                }
                // ?
                if (monitor != null) {
                    long usetime = System.currentTimeMillis() - startTime;
                    info.setAvgtime(usetime);
                    info.setMaxtime(usetime);
                    info.setMintime(usetime);
                    monitor.collect(clientNode, info);
                }
            }
        }
        throw new RpcException("Invoke error!", exception);
    }
}