现象:域名开启了分片缓存;client发送给cache一个range请求,由于这个域名开启了分片缓存,所以cache会发送给源站一个range:bytes=0-0请求(有些公司是其他range请求),这样是为了根据源站的响应头而获取到文件的大小,进而进行详细的分片回源;
但是当cache发送range:bytes=0-0请求时,每次源站都会返回200,并且返回整个文件内容;
问题:为什么cache发送给源站的是range请求,源站返回的是200呢?
排查:
1.首先想到的是源站不支持range,或者源站一部分服务器不支持range;
我们对源站的服务器进行了curl模拟,由于源站一共三台服务器,所以很容易模拟出来。模拟的结果是源站支持range,并且每次都是返回206;这样排出了源站不支持range;
2.通过抓包,我们发现client发送给cache的请求包含if-range,if-range一般和range配合使用,if-range一般和last modify或者etag匹配,当if-range和last modify或者etag匹配时,则range起作用;
通过分析,我们发现client发过来的请求if-range和源站返回的last modify不匹配,所以源站返回给cache是200,cache也返回给client 200并且返回全部内容;
一切都是client的程序员们没有很好的使用if-range惹的祸;哈哈。即使不使用cdn,直接访问源站也会导致返回200;

目前cache对源站发送range请求返回200有两种通用的做法,不过各有优劣;
1.cache发送给源站range请求,源站返回200,然后cache会将整个内容返回给client端,并且将整个内容缓存下来;
优点:简单,性能比较高;
缺点:client请求range,返回的是整个文件内容,在一定程度上违背了用户的意愿;
2.cache发送给源站range请求,源站返回200,然后cache收到整个响应后,会进行切片,然后给client返回206,并且只返回部分内容;
优点:无论源站支持不支持range请求(或者if-range使用不当),client都会得到想要的内容而不是整个文件;
缺点:cache必须在收到整个响应体后再进行切片,
如果文件比较大的话并且client range请求的内容比较靠后,会影响client的首包时间(也就是client收到第一个包的时间延迟比较高)

附上cache发送给源站的请求图片:
if-range引起的cdn分片缓存问题-LMLPHP


09-21 15:51