MapBoxGL底图请求(图片请求)阻塞问题及解决方法

问题描述

在使用MapBoxGL进行地图开发和展示过程中,一般都需要加载底图作为基础展示内容,然后配合加载其他专题数据图层。但是当网速不好,或者底图服务器响应过慢时,会出现一种情况,那就是底图迟迟未完成加载,但是其他响应速度快的专题数据图层又未开始请求数据,导致系统出现一个较长时间的尴尬等待期。

比如下面的例子:我同时叠加了天地图影像底图以及一个WMS服务图层,图层顺序为先叠加天地图,再叠加WMS服务图层。但是却因为天地图服务无法快速完成请求,导致WMS服务图层等待了快20s才开始发送请求进行加载处理。

在这里插入图片描述
注:由于叠加顺序,一开始优先请求天地图相关的资源,这个乍看之下没毛病,但是继续往下看

在这里插入图片描述
注:由于网速及天地图本身响应速度的原因,并且底图切片请求数量较多,在请求很多很多切片之后,终于轮到了WMS图层开始发送请求

在这里插入图片描述
注:仔细查看天地图首个请求发起时间点,为系统开始访问后的494ms

在这里插入图片描述
注:再查看WMS图层首个请求发起时间点,为系统开始访问后的20.8s,这意味着WMS图层,在天地图请求开始之后等待了20s,才终于开始了自己的请求。

这个明显是不太对劲的,而且也严重影响正常使用,明明WMS或者其他图层加载很快,但是却被底图给阻塞住了,所以需要分析并解决这个问题。

问题分析

从控制台的network来分析,基本可以确定是由于天地图底图请求过多过慢,导致MapBoxGL无法发起后续的其他请求,那么有可能导致这种情况的常见原因有:请求响应速度、图层叠加先后顺序、浏览器最大建立连接数、MapBoxGL内部程序逻辑控制。针对这几点一项项来分析:

请求响应速度?

最直接的原因,就是天地图底图响应慢,那我直接给他加快就就完事了。

最简单的,就是浏览器缓存或者架设前端缓存服务器对天地图进行缓存,然后系统后续访问就速度飞快,快到无法阻塞的地步。

但是,但是啊,问题在于缓存这个东西,需要前置准备,并且要考虑到每一个图层的情况,万一哪天有个新图层,没缓存,又慢,那就完了,还是会卡住,发生阻塞。

所以结论:直接原因之一,不是根本原因。针对这点去解决,简单有效但是治标不治本。

图层叠加先后顺序?

天地图先请求,所以量大又慢就会卡住,那我调整一个图层加载的顺序,先叠加快的WMS服务图层,再叠加天地图,可行?单纯看问题,的确可以解决,因为先叠加的图层就是会先发起加载请求。不过仔细一想,你这个底图后叠加,跑到专题图层上面然后盖住专题图层?不妥不妥。

那换个思路,保持先叠加天地图,后叠加WMS服务图层,然后呢一开始先隐藏天地图,等到WMS服务图层加载完毕之后,再显示天地图。嗯,这个操作可行,延迟显示天地图是能让WMS服务图层先加载的。但是就面临两个问题:1、隐藏会导致底图消失,影响观感。2、无法确认WMS服务图层加载请求,不知道延迟多久才能把天地图显示回来。故,这个操作,救急可以,当做解决方法,不妥不妥。

所以结论:直接原因之一,不是根本原因。针对这点去解决并不是一个好的思路,只能偶尔用于救急。

浏览器最大建立连接数?

既然是请求阻塞,那会不会是受到浏览器最大建立连接数的限制呢?因为浏览器一般都是存在一个默认的最大建立连接数的,比如Chrome,就是6个,也就是说,对同一个域名建立的连接数最多同时只能有6个,再多就不行了,要等之前的请求完成连接关闭,才能开始。并且天地图的底图使用的是http1.1协议,无法套用http2.0的链路复用,的确是有可能出现阻塞的情况。

于是我就试了下,使用Nginx将天地图底图代理成为http2.0协议,然后测试结果发现并不是浏览器的连接数限制,因为即便用了http2.0协议,同时发送的请求还是只有寥寥十来个,这明显是程序内部在控制。

这里要说明一下,浏览器控制的最大连接数阻塞现象,跟程序控制的是有区别的。最明显的区别就是,当并发的请求远超浏览器控制的最大连接数时,若使用http2.0协议,则会同时出现全部请求。但是如果是程序内部控制,即便使用http2.0协议,请求数量仍然受制于程序逻辑,无法同时出现全部请求。
所以结论:与本问题无关,但是可能会作为以后另外一种阻塞情况的原因。针对这点去解决,是不能解决本篇提出的这个问题的。

MapBoxGL内部程序逻辑控制?

经过上一点的认证,我们基本可以确定是MapBoxGL程序内部是有个限制的,导致无论资源使用的是不是http2.0协议,只要速度慢,那同时发出的请求就只有这么多,只能等待请求完成,才会发出新的请求。那么我们需要跟踪一下内部的请求逻辑,找到它设置的逻辑,一探究竟。

调试我用的MapBoxGL是2.13.0版本,通过将引用的入口文件从mapbox-gl.js改成mapbox-gl-dev.js,即可查看正常的代码并方便进行调试跟踪操作。

通过断点和跟踪,定位在/utils/ajax.js的getImage方法对数据进行请求实例的创建,其中会根据config.MAX_PARALLEL_IMAGE_REQUESTS来进行一次判断,当前进行的图片相关请求超出这个数量,就会把本次创建置于等候区,待前面的请求有完成的时候,才会依次从等候区创建请求。而这个config.MAX_PARALLEL_IMAGE_REQUESTS的配置指向了/utils/config.js这个文件的MAX_PARALLEL_IMAGE_REQUESTS变量,并且默认值为16,实在有点少。

所以要调整这个数值,有两种办法,一是改源码然后重新打包一个新的MapBoxGL库;二是在引用MapBoxGL库之后,创建Map实例之前,手动通过代码设置一下这个变量值。比如这样,就能上调最大同时存在的图片请求数量:

mapboxgl.config.MAX_PARALLEL_IMAGE_REQUESTS = 256;

在上调这个数值之后,再次测试系统,发现请求全部都出来了,专题图的WMS服务图层也不会受到天地图底图的加载情况的影响了。

换句话说,只要此数值满足涉及图片请求的且量大响应不稳定的图层的请求数量,就不会出现因某些图层图片资源响应速度导致的其他图层图片资源请求阻塞问题。

对应本问题,那涉及图片请求且量大响应不稳定的图层,就是天地图底图了。所以我把它上调至256,基本能满足需求了。如果遇到其他资源,可以稍作尝试,得到一个比较好的阈值。

所以结论:是根本原因,针对这个点进行最大图片请求数值进行调整,可以解决问题。

结论

根本原因就是MapBoxGL内部程序的逻辑限制,可以通过调整

config.MAX_PARALLEL_IMAGE_REQUESTS

这一配置来上调这个数值限制,当然你也可以直接修改源码去除这个判断逻辑,这个就不在讨论范围之内了。

而除了这个原因以外,像资源请求响应速度、图层叠加顺序这两点算是直接原因,如果有极致的用户体验需求,可以在上调数值限制的基础上,从这两点进行优化。

而浏览器最大建立连接数这点,虽然跟本文的问题没有太多关联,但是也算是后续系统的一个可选优化点,因为使用http2.0协议,既能进行链路复用优化网络请求,又能享用https带来的安全保障。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值