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

com.github.houbb.rpc.client.proxy.impl.RemoteInvokeServiceImpl Maven / Gradle / Ivy

package com.github.houbb.rpc.client.proxy.impl;

import com.github.houbb.heaven.support.handler.IHandler;
import com.github.houbb.heaven.util.id.impl.Ids;
import com.github.houbb.heaven.util.util.CollectionUtil;
import com.github.houbb.load.balance.api.ILoadBalance;
import com.github.houbb.load.balance.api.impl.LoadBalanceContext;
import com.github.houbb.load.balance.support.server.IServer;
import com.github.houbb.log.integration.core.Log;
import com.github.houbb.log.integration.core.LogFactory;
import com.github.houbb.rpc.client.proxy.RemoteInvokeContext;
import com.github.houbb.rpc.client.proxy.RemoteInvokeService;
import com.github.houbb.rpc.client.proxy.ServiceContext;
import com.github.houbb.rpc.client.support.calltype.CallTypeStrategy;
import com.github.houbb.rpc.client.support.calltype.impl.CallTypeStrategyFactory;
import com.github.houbb.rpc.client.support.fail.FailStrategy;
import com.github.houbb.rpc.client.support.fail.impl.FailStrategyFactory;
import com.github.houbb.rpc.client.support.filter.RpcFilter;
import com.github.houbb.rpc.client.support.register.ClientRegisterManager;
import com.github.houbb.rpc.common.rpc.domain.RpcChannelFuture;
import com.github.houbb.rpc.common.rpc.domain.RpcRequest;
import com.github.houbb.rpc.common.rpc.domain.RpcResponse;
import com.github.houbb.rpc.common.support.invoke.InvokeManager;
import io.netty.channel.Channel;

import java.util.List;

/**
 * 远程调用实现
 * @author binbin.hou
 * @since 0.1.1
 */
public class RemoteInvokeServiceImpl implements RemoteInvokeService {

    private static final Log LOG = LogFactory.getLog(RemoteInvokeServiceImpl.class);

    @Override
    @SuppressWarnings("all")
    public Object remoteInvoke(RemoteInvokeContext context) {
        final RpcRequest rpcRequest = context.request();
        final ServiceContext proxyContext = context.serviceProxyContext();
        final RpcFilter rpcFilter = proxyContext.rpcFilter();


        // 设置唯一标识
        final String seqId = Ids.uuid32();
        rpcRequest.seqId(seqId);

        // 构建 filter 相关信息,结合 pipeline 进行整合
        rpcFilter.filter(context);

        // 负载均衡
        // 这里使用 load-balance 进行选择 channel 写入。
        final Channel channel = getLoadBalanceChannel(proxyContext);
        LOG.info("[Client] start call channel id: {}", channel.id().asLongText());

        // 对于信息的写入,实际上有着严格的要求。
        // writeAndFlush 实际是一个异步的操作,直接使用 sync() 可以看到异常信息。
        // 支持的必须是 ByteBuf
        channel.writeAndFlush(rpcRequest).syncUninterruptibly();
        LOG.info("[Client] start call remote with request: {}", rpcRequest);
        final InvokeManager invokeManager = proxyContext.invokeManager();
        invokeManager.addRequest(seqId, proxyContext.timeout());

        // 获取结果
        CallTypeStrategy callTypeStrategy = CallTypeStrategyFactory.callTypeStrategy(proxyContext.callType());
        RpcResponse rpcResponse = callTypeStrategy.result(proxyContext, rpcRequest);
        invokeManager.removeReqAndResp(seqId);

        // 获取调用结果
        context.rpcResponse(rpcResponse);
        FailStrategy failStrategy = FailStrategyFactory.failStrategy(proxyContext.failType());
        return failStrategy.fail(context);
    }

    /**
     * 获取负载均衡的 channel
     *
     * ps: java 的类型擦除真的麻烦。
     *
     * @param serviceContext 服务上下文
     * @return 结果
     */
    private Channel getLoadBalanceChannel(final ServiceContext serviceContext) {
        final ClientRegisterManager clientRegisterManager = serviceContext.clientRegisterManager();
        final String serviceId = serviceContext.serviceId();
        List channelFutures = clientRegisterManager.queryServerChannelFutures(serviceId);

        final ILoadBalance loadBalance = serviceContext.loadBalance();
        List servers = CollectionUtil.toList(channelFutures, new IHandler() {
            @Override
            public IServer handle(RpcChannelFuture rpcChannelFuture) {
                return rpcChannelFuture;
            }
        });
        LoadBalanceContext context = LoadBalanceContext.newInstance()
                .servers(servers);

        IServer server = loadBalance.select(context);
        LOG.info("负载均衡获取地址信息:{}", server.url());
        RpcChannelFuture future = (RpcChannelFuture) server;
        return future.channelFuture().channel();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy