手写RPC---⑩实现client模块(下)

RpcClient类

public class RpcClient {
    //配置
    private RpcClientConfig config;
    //序列化
    private Encoder encoder;
    private Decoder decoder;
    //路由
    private TransportSelector selector;

    //无参构造 就使用默认的配置
    public RpcClient() {
        this(new RpcClientConfig());//调用有参构造 将默认值传过去
    }
    //有参构造 配置可以自己设定 -> 通过参数传过来
    public RpcClient(RpcClientConfig config) {
        this.config = config;
        //属性初始化
        this.encoder = ReflectionsUtils.newInstance(this.config.getEncoderClass());
        this.decoder = ReflectionsUtils.newInstance(this.config.getDecoderClass());
        this.selector = ReflectionsUtils.newInstance(this.config.getSelectorClass());
        //selector初始化  1:server网络端点 2:连接个数 3:client网络模块
        this.selector.init(
                this.config.getServers(),
                this.config.getConnectCount(),
                this.config.getTransportClass()
        );
    }
    //获取一个接口的代理对象  期望的是这个方法能够返回一个clazz的子类的对象 所以用个泛型
    public <T> T getProxy(Class<T> clazz){
        //基于JDK的动态代理
        return (T) Proxy.newProxyInstance(
                getClass().getClassLoader(),
                new Class[]{clazz},
                new RemoteInvoker(clazz,encoder,decoder,selector)
        );

    }

}

Proxy.newProxyInstance的使用及其作用可看JDK动态代理类

创建代理类

@Slf4j
//调用远程服务的代理类
public class RemoteInvoker implements InvocationHandler {
    private Class clazz;
    //序列化
    private Encoder encoder;
    private Decoder decoder;
    //路由
    private TransportSelector selector;

    //参数 : 远程服务的class信息; 远程服务的序列化、反序列化 ;  选择一个远程网络连接;
    public RemoteInvoker(Class clazz,Encoder encoder,Decoder decoder,TransportSelector selector) {
        this.encoder = encoder;
        this.decoder = decoder;
        this.selector = selector;
        this.clazz = clazz;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //调用远程服务:通过网络发生一个请求,等待server响应 返回数据 结束;

        //创建请求对象
        Request request  = new Request();
        request.setService(ServiceDescriptor.from(clazz,method));
        request.setParameters(args);
        //通过网络 调用远程服务  拿到response
        Response response = invokeRemote(request);
        if(response == null || response.getCode() != 0){
            throw  new IllegalStateException("fail to invoke remote: " + response );

        }
        //返回response信息 远程调用结束
        return response.getData();
    }

    private Response invokeRemote(Request request) {
        //拿到网络连接信息client
        TransportClient client = null;
        Response response = null;
        try {
            client = selector.select();//选择一个client路由
            //序列化
            byte[] bytes = encoder.encode(request);
            //获取到的数据
            InputStream revice = client.write(new ByteArrayInputStream(bytes));
            byte[] inBytes = IOUtils.readFully(revice, revice.available());
            //反序列化
             response = decoder.decode(inBytes, Response.class);
        }catch (IOException e){
            log.warn(e.getMessage(),e);
            response = new Response();
            response.setCode(1);
            response.setMessage("RpcClient got error: "+ e.getClass()+":" +e.getMessage());
        }
        finally {
            if(client != null){
                selector.release(client);
            }
        }


        return response;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值