美文网首页
Cronet网络库(Quic连接出错篇章一)

Cronet网络库(Quic连接出错篇章一)

作者: Magic旭 | 来源:发表于2022-04-18 18:10 被阅读0次

    问题

    因为业务需求把所有业务的域名都搞成相同的,导致Cronet在底层连接出错的判断逻辑也跟着出错了。原因是域名相同后,假如某个业务域名所建立的连接一直出错,但是该连接的端口有1-3个的话,出错后cronet会记录内存、本地,后续有其他业务域名命中这个1-3个端口的话,就会导致一直命中跳过quic连接的逻辑。本章节主要分析quic连接出错状态后续会导致其他连接被误认为是需要跳过的。

    Quic Job创建流程

    1. 要解决问题,我们首先要弄清楚整个quic job的创建流程,首先是job_controller控制所有http请求的Job创建,来到http_stream_factory_job时候,里面就根据逻辑判断来决定走h2还是h3的job,这里流程图只涉及Quic job相关,具体可以看图一。


      图一.png

    Quic broken逻辑

    1. quic创建连接跳过逻辑在http_stream_factory_job_controller.cc里的GetAlternativeServiceInfoInternal函数里,在返回AlternativeServiceInfo时候会判断该域名和端口等元素组合而成的Key是否在broken的数组里,如果存在就跳过此次循环,那么就会返回一个默认值的first_alternative_service_info。源码如下图二所示


      图二.png
    2. is_broken的判断逻辑又涉及到broken_alternative_services.cc里面的数据储存了,其中有个储存broken数据的在Quic Job确定连接失败发生下面3个错误情况下,会将当前host、port记录到broken数组里。QuicStreamRequest的创建可以由图一看出在Job::DoInitConnectionImplQuic函数创建的,那么我们回去看callback函数即可。源码如下图三所示


      图三.png
    3. DoInitConnectionImplQuic的构造函数再经过delegate->onFailedOnDefaultNetwork回调给上层,即回调http_stream_factory_job_controller.cc里,可以看出其中回调后会把一个标识位置设置成true,那么我们继续跟着标识位的判断可以发现最后走到MaybeReportBrokenAlternativeService函数里,而函数里的MarkAlternativeServiceBrokenUntilDefaultNetworkChanges就会把数据记录到broken_alternative_services.cc里。

    //来源于:http_stream_factory_job_controller.cc
    void HttpStreamFactory::JobController::OnFailedOnDefaultNetwork(Job* job) {
      DCHECK_EQ(job->job_type(), ALTERNATIVE);
      alternative_job_failed_on_default_network_ = true;
    }
    
    //请求结束
    void HttpStreamFactory::JobController::OnRequestComplete() {
      ……
      MaybeNotifyFactoryOfCompletion();
    }
    
    //主要是MarkAlternativeServiceBrokenUntilDefaultNetworkChanges,他会把host和port信息记录到broken数组里
    void HttpStreamFactory::JobController::MaybeReportBrokenAlternativeService() {
      if (alternative_job_net_error_ == OK &&
          !alternative_job_failed_on_default_network_)
        return;
    ……
    
      if (alternative_job_failed_on_default_network_ &&
          alternative_job_net_error_ == OK) {
        session_->http_server_properties()
            ->MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
                alternative_service_info_.alternative_service(),
                request_info_.network_isolation_key);
        // Reset error status for Jobs after reporting brokenness.
        ResetErrorStatusForJobs();
        return;
      }
    ……
    }
    
    

    解决问题思路

    因为host被业务需要改成相同的了,那我们只需要在is_broken基础上新增一个值来判断当前的host和port是否为同一条连接即可,因为只有当连接相同情况下并且失败过才要跳过quic的创建,如果不是相同的一条连接应该尝试创建quic job。(涉及业务代码的保密性我就不贴出来了)

    注意: 不能重载AlternativeService的<、==、!=等符号,因为这个类很多逻辑都共用到的,如果修改后原本判断相同的处理因为新增值就判断不相同了。所以需要做的工作是在取的时候新增个&&判断来解决问题。


    总结

    1. 遇到相关开发问题,要尝试理解源码设计后再去改动,不要盲目去大改,毕竟已经上线存在那么久了,没有把握情况下尽量小改解决问题。
    2. 发现Cronet开源项目做的非常棒,不是说能力上(我太菜还没能全部读懂),而是说查询代码的体验上,你点击函数还能跳转进具体函数,像ide一样了。Cronet的源码链接(翻墙)
    3. broken逻辑还涉及本地序列化和反序列化,这里涉及的代码和逻辑我会在下一个篇章分析(如果我有时间的话)。

    相关文章

      网友评论

          本文标题:Cronet网络库(Quic连接出错篇章一)

          本文链接:https://www.haomeiwen.com/subject/aipdertx.html