tars源码解析2-客户端启动

在还没有认真分析源码之前,我根据以前阅读微服务框架的思路,去分析这样几个问题

  1. 客户端如何获取服务节点列表
  2. 客户端如何维持与服务之间的链接,这种链接是长连接还是短连接,使用的方式/框架是什么?
  3. 客户端如何实现服务端调用的负载均衡,还是说负载均衡由硬件来处理(网络层来处理)。
  4. 客户端与服务端数据是怎样通信的?序列化协议?
  5. 客户端与服务端连接出现问题如何处理?
    这是我暂时想到的,当然微服务框架之间的处理,远不止这些,这些算是入门读懂一些框架,接下来我就来具体分析。

客户端启动源码

    // 从本地启动的配置
        CommunicatorConfig cfg = new CommunicatorConfig();
        // 从本地启动的Communcator
        Communicator communicator = CommunicatorFactory.getInstance().getCommunicator(cfg);
        //warn 若是部署在tars平台启动的, 只能使用下面的构造器获取communcator
        //Communicator communicator = CommunicatorFactory.getInstance().getCommunicator();
        HelloPrx proxy = communicator.stringToProxy(HelloPrx.class, "TestApp.HelloServer.HelloObj@tcp -h 127.0.0.1 -p 18601 -t 60000");
        //同步调用
        String ret = proxy.hello(1000, "Hello World");
        System.out.println(ret);
  1. CommunicatorConfig:客户端协调器的配置文件(超时配置呀,等等一些列配置信息)
  2. Communicator:正在的协调调用者。
  3. stringToProxy:将我们的Servant封装成代理类,ObjectProxy也就是我们后面获取的Servant客户端都是ObjectProxy,直接看invoke方法即可。

几个关键的类

1. CommunicatorConfig

2. Communicator

3. ServantProxyFactory

    public <T> Object getServantProxy(Class<T> clazz, String objName, String setDivision, ServantProxyConfig servantProxyConfig,
                                     LoadBalance loadBalance, ProtocolInvoker<T> protocolInvoker) {
       String key = setDivision != null ? clazz.getSimpleName() + objName + setDivision : clazz.getSimpleName() + objName;
       Object proxy = cache.get(key);
       if (proxy == null) {
           lock.lock();
           try {
               proxy = cache.computeIfAbsent(key, param -> {
                   ObjectProxy<T> objectProxy = communicator.getObjectProxyFactory().getObjectProxy(clazz, objName, setDivision, servantProxyConfig, loadBalance, protocolInvoker);
                   return createProxy(clazz, objectProxy);
               });
           } finally {
               lock.unlock();
           }
       }
       return proxy;
   }

管理ObjectProxyFactory,如果缓存有就从缓存中取,没有就生产

4.ObjectProxyFactory

 public <T> ObjectProxy<T> getObjectProxy(Class<T> api, String objName, String setDivision, ServantProxyConfig servantProxyConfig,
                                             LoadBalance<T> loadBalance, ProtocolInvoker<T> protocolInvoker) throws ClientException {
        if (servantProxyConfig == null) {
            servantProxyConfig = createServantProxyConfig(objName, setDivision);
        } else {
            servantProxyConfig.setCommunicatorId(communicator.getId());
            servantProxyConfig.setModuleName(communicator.getCommunicatorConfig().getModuleName(), communicator.getCommunicatorConfig().isEnableSet(), communicator.getCommunicatorConfig().getSetDivision());
            servantProxyConfig.setLocator(communicator.getCommunicatorConfig().getLocator());
            if (StringUtils.isNotEmpty(setDivision)) {
                servantProxyConfig.setSetDivision(setDivision);
            }
        }

        updateServantEndpoints(servantProxyConfig);

        if (loadBalance == null) {
            loadBalance = createLoadBalance(servantProxyConfig);
        }

        if (protocolInvoker == null) {
            protocolInvoker = createProtocolInvoker(api, servantProxyConfig);
        }
        return new ObjectProxy<T>(api, servantProxyConfig, loadBalance, protocolInvoker, communicator);
    }

生产ObjectProxy

  1. 创建ServantProxyConfig:就是Servant服务的配置信息,每个服务配置可能不同
  2. updateServantEndpoints
   private void updateServantEndpoints(ServantProxyConfig cfg) {
       CommunicatorConfig communicatorConfig = communicator.getCommunicatorConfig();

       String endpoints = null;
       if (!ParseTools.hasServerNode(cfg.getObjectName()) && !cfg.isDirectConnection() && !communicatorConfig.getLocator().startsWith(cfg.getSimpleObjectName())) {
           try {
               /** query server nodes from registerServer */
               if (RegisterManager.getInstance().getHandler() != null) {
                   endpoints = ParseTools.parse(RegisterManager.getInstance().getHandler().query(cfg.getSimpleObjectName()),
                           cfg.getSimpleObjectName());
               } else {
                   endpoints = communicat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值