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

com.github.jingshouyan.jrpc.client.JrpcClient Maven / Gradle / Ivy

There is a newer version: 0.8.3
Show newest version
package com.github.jingshouyan.jrpc.client;

import com.github.jingshouyan.jrpc.base.action.ActionHandler;
import com.github.jingshouyan.jrpc.base.action.ActionInterceptor;
import com.github.jingshouyan.jrpc.base.action.ActionInterceptorHolder;
import com.github.jingshouyan.jrpc.base.bean.Req;
import com.github.jingshouyan.jrpc.base.bean.Rsp;
import com.github.jingshouyan.jrpc.base.bean.ServerInfo;
import com.github.jingshouyan.jrpc.base.bean.Token;
import com.github.jingshouyan.jrpc.base.code.Code;
import com.github.jingshouyan.jrpc.base.exception.JrpcException;
import com.github.jingshouyan.jrpc.base.thrift.Jrpc;
import com.github.jingshouyan.jrpc.base.thrift.ReqBean;
import com.github.jingshouyan.jrpc.base.thrift.RspBean;
import com.github.jingshouyan.jrpc.base.thrift.TokenBean;
import com.github.jingshouyan.jrpc.base.util.rsp.RspUtil;
import com.github.jingshouyan.jrpc.client.config.ClientConfig;
import com.github.jingshouyan.jrpc.client.discover.ZkDiscover;
import com.github.jingshouyan.jrpc.client.node.Node;
import com.github.jingshouyan.jrpc.client.pool.TransportPool;
import com.github.jingshouyan.jrpc.client.transport.Transport;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.async.AsyncMethodCallback;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoSink;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * @author jingshouyan
 * #date 2018/10/26 9:42
 */
@Slf4j
public class JrpcClient implements ActionHandler {

    private ClientConfig config;
    private ZkDiscover zkDiscover;

    private final ExecutorService callbackExec;
    private final BiConsumer, Rsp> success;
    private final BiConsumer, Exception> error;

    public JrpcClient(ClientConfig config) {
        this.config = config;
        this.zkDiscover = new ZkDiscover(config);

        //callback 执行线程池
        callbackExec = new ThreadPoolExecutor(config.getCallbackThreadPoolSize(),
                config.getCallbackThreadPoolSize(), 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
                new ThreadFactoryBuilder().setNameFormat("callback-%d").build(),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        //success 执行方法
        success = (monoSink, rsp) -> monoSink.success(rsp);
//                callbackExec.execute(() -> emitter.onSuccess(rsp));
        //error 执行方法
        error = (monoSink, e) -> {
            Rsp rsp;
            if (e instanceof JrpcException) {
                rsp = RspUtil.error((JrpcException) e);
            } else if (e instanceof TimeoutException) {
                rsp = RspUtil.error(Code.CONNECT_TIMEOUT);
                log.warn("call rpc timeout.", e);
            } else {
                rsp = RspUtil.error(Code.CLIENT_ERROR);
                log.error("call rpc error.", e);
            }
            success.accept(monoSink, rsp);
        };

    }

    public Map> serverMap() {
        Map> nodeMap = zkDiscover.nodeMap();
        Map> map = new HashMap<>(nodeMap.size());
        for (Map.Entry> entry : nodeMap.entrySet()) {
            String key = entry.getKey();
            List value = entry.getValue().stream()
                    .map(Node::getServerInfo).collect(Collectors.toList());
            map.put(key, value);
        }
        return map;
    }

    @Override
    public Mono handle(Token token, Req req) {
        ActionHandler handler = this::call;
        for (ActionInterceptor interceptor : ActionInterceptorHolder.getClientInterceptors()) {
            final ActionHandler ah = handler;
            handler = (t, r) -> interceptor.around(t, r, ah);
        }
        Mono mono = handler.handle(token, req);
        return mono;
    }

    private Mono call(Token token, Req req) {
        return Mono.create(monoSink -> {
            TransportPool pool = null;
            Transport transport = null;
            Rsp rsp;
            try {
                Node node = zkDiscover.getNode(req.getRouter());
                pool = node.pool();
                transport = pool.get();
                TransportPool poolTmp = pool;
                Transport transportTmp = transport;
                Jrpc.AsyncClient client = transport.getAsyncClient();
                TokenBean tokenBean = token.tokenBean();
                ReqBean reqBean = req.reqBean();
                if (req.isOneway()) {
                    client.send(tokenBean, reqBean, new AsyncMethodCallback() {
                        @Override
                        public void onComplete(Void aVoid) {
                            restore(poolTmp, transportTmp);
                            success.accept(monoSink, RspUtil.success());
                        }

                        @Override
                        public void onError(Exception e) {
                            invalid(poolTmp, transportTmp);
                            error.accept(monoSink, e);
                        }
                    });
                } else {
                    client.call(tokenBean, reqBean, new AsyncMethodCallback() {
                        @Override
                        public void onComplete(RspBean rspBean) {
                            restore(poolTmp, transportTmp);
                            success.accept(monoSink, new Rsp(rspBean));
                        }

                        @Override
                        public void onError(Exception e) {
                            invalid(poolTmp, transportTmp);
                            error.accept(monoSink, e);
                        }
                    });
                }
                return;
            } catch (JrpcException e) {
                restore(pool, transport);
                rsp = RspUtil.error(e);
            } catch (TimeoutException e) {
                restore(pool, transport);
                rsp = RspUtil.error(Code.CONNECT_TIMEOUT);
            } catch (Throwable e) {
                log.error("call rpc error.", e);
                invalid(pool, transport);
                rsp = RspUtil.error(Code.CLIENT_ERROR);
            }
            monoSink.success(rsp);
        });
    }

    private static void restore(TransportPool pool, Transport transport) {
        if (pool != null && transport != null) {
            pool.restore(transport);
        }
    }

    private static void invalid(TransportPool pool, Transport transport) {
        if (pool != null && transport != null) {
            pool.invalid(transport);
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy