msforest / notebook

好记性不如烂笔头,记录知识的点点滴滴。
https://github.com/msforest/notebook/wiki
0 stars 0 forks source link

HTTP缓存配置 #18

Open msforest opened 6 years ago

msforest commented 6 years ago

新到一个工作环境,被要求解决浏览器缓存加载的问题。拿到一个新项目,包含各种资源文件:html/css/js/python/node,之前是只需要做前端,现在是前后都得干,有点不习惯,先熟悉一波文件目录结构,还是有规律可寻的。

问题:本地代码部署到线上,其他人使用浏览器打开没有加载最新部署的资源,还是使用浏览器缓存的文件,需要通过f12 + disabled cachectrl+f5来强制刷新加载。

过程:一般想要重新加载资源文件或请求API,是在后面加个时间戳来更改请求地址以实现浏览器缓存不存在同样的请求地址,这种解决方案我只是看看,真的做起来不太现实,文件这么多,API又何其多;就剩下以前想尝试但又没机会尝试的方法--通过配置HTTP header来解决浏览器缓存问题。

环境:系统ubuntu16.04 / 服务器Apache2.4.18 几个请求头的知识点:

  Etag: 根据文件内容生成的一个值,比根据缓存时间判断更划算

  Expires: 指定了一个日期/时间, 在这个日期/时间之后,HTTP响应被认为是过时的;需和Last-Modified结合使用。用于控制请求文件的有效时间,当请求数据在有效期内时客户端浏览器从缓存请求数据而不是服务器端.当缓存中数据失效或过期,才决定从服务器更新数据。HTTP 1.0 版本

  Cache-Control: 用于在http 请求和响应中通过指定指令来实现缓存机制。HTTP 1.1版本,资源在本地缓存多少秒。

  If-None-Match: 值为上一次响应头返回的etag值,作为请求头发送

  Last-Modified: 响应头返回的文件最后修改时间

  If-Modified-Since: 值为上一次响应头返回的修改时间,作为请求头发送

更多请参考mdn

然后就是更改Apache的配置信息,找到Apache的安装目录:

  1. 在/etc/apache2/mods_enabled/headers.load 配置全局的消息头 image Max-age:单位是秒
  2. 在/etc/apche2/apache2.conf 根据不同资源文件配置不同的消息头 image 配置了ETag消息头却没有加载最新资源文件,添加如下配置信息即可解决
    //https://stackoverflow.com/questions/29127144/cant-cache-resource-when-having-both-gzip-and-etag
    <IfModule mod_headers.c>
    Header unset ETag
    </IfModule>
    FileETag None

    表示不发送etag响应头

从Apache2.4.0之后,由于Etag默认被加上gzip后缀,导致请求不会发送304响应码 image

 https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag

发现了问题就去解决问题,不去解决就是耍无赖,毕竟响应码还是很重要的一个信息

image 开启mod_header.c的命令:sudo a2enmod headers

修改etag的生成规则

先了解etag的原理 image

https://httpd.apache.org/docs/2.4/zh-cn/mod/core.html#fileetag

简而言之,etag由文件在系统的索引节点+文件最后修改的时间+文件大小组成的 修改如下 image

http://httpd.apache.org/docs/current/mod/mod_headers.html

设置expires的值

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault A1000
</IfModule>

M means that the file's last modification time should be used as the base time, and A means the client's access time should be used

https://httpd.apache.org/docs/trunk/mod/mod_expires.html

sudo a2enmod expires执行该命令启用模块,然后重启服务

以下仅供参考:

ExpiresActive On
ExpiresDefault A2592000
# GIF有效期为1个月
ExpiresByType image/gif A2592000
# HTML文档的有效期是最后修改时刻后的一星期
ExpiresByType text/html M604800
#以下的含义类似
ExpiresByType text/css "now plus 2 months"
ExpiresByType text/js "now plus 2 days"
ExpiresByType image/jpeg "access plus 2 months"
ExpiresByType image/bmp "access plus 2 months"
ExpiresByType image/x-icon "access plus 2 months"
ExpiresByType image/png "access plus 2 months"

问题发现(未解决): 经过本地和线上测试发现:客户端获取最新资源的措施,服务端已设置请求头ETAG来判断是否使用最新文件还是使用浏览器缓存文件,且浏览器已生效,IE和Firefox是没有问题的,chrome现在的情况是有时生效有时不生效,不生效是因为chrome请求头会报如下错误信息 image 综合网上解决方案,发生错误的原因:

  1. 请求的资源可能被(扩展插件或其他什么机制)屏蔽掉导致发送伪请求。经浏览器查看,将插件禁用,还是会报错
  2. 资源加载时间太长,优化加载时间。经本地测试,资源所加载时间都不超过1s

猜测有可能是网络问题,因为本地测试一切正常,只有线上才会出现改现象,而且线上服务器不再国内

msforest commented 6 years ago

网站压力测试ab

ab -n 100 -c 100 http://127.0.0.1:8080/ detail

msforest commented 6 years ago

强缓存和协商缓存