注册
web

灰度发布策略在前端无损升级中的应用

为了提升浏览器加载页面资源的性能,对于js、css、图片等静态资源,web服务器往往会通过Cache-Control、ETag/If--Match、Last-Modified/If-Modified-Since、Pragma、Expires、Date、Age等头部来控制、管理、检测这类资源对缓存机制的使用情况。同时,为了使新版本的js、css等资源立即生效,一种比较通行的做法是为js、css这些文件名添加一个hash值。这样当js、css内容发生变化时,浏览器获取的是不同的js、css文件。在这种情况下,旧版本的index.html文件可能是这样的:


<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>测试</title>
<meta http-equiv=X-UA-Compatible content="IE=Edge">
<meta name=viewport content="width=device-width,minimum-scale=1,maximum-scale=1">
<link href=/static/css/main.4656e35c1e8d4345f5bf.css rel=stylesheet>
</head>
<style>
html, body {
width: 100%;
}
</style>
<body>
<div id=newMain></div>
<script type=text/javascript src=/static/js/main-4656e35c1e8d4345f5bf.js></script>
</body>
</html>

当项目的js、css内容发生了变化时,新版本的index.html文件内容变成这样的(js和css文件名携带了新的hash值1711528240049):


<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>测试</title>
<meta http-equiv=X-UA-Compatible content="IE=Edge">
<meta name=viewport content="width=device-width,minimum-scale=1,maximum-scale=1">
<link href=/static/css/main.1711528240049.css rel=stylesheet>
</head>
<style>
html, body {
width: 100%;
}
</style>
<body>
<div id=newMain></div>
<script type=text/javascript src=/static/js/main-1711528240049.js></script>
</body>
</html>

因为index.html文件一般会设置为不缓存,这样用户每次访问首页时,都会从web服务器重新获取index.html,然后根据index.html中的资源文件是否变化,从而决定是否使用缓存的文件。这样既能让用户立即获取最新的js、css等静态资源文件,又能充分地使用缓存。index.html的响应头大概长这样:


847fa51ec16bbfa14a5865482b23f396.png


但是为了保证系统的高可用,web后端往往由多个实例提供服务,用户请求会在多个服务实例间进行负载均衡。而系统升级过程中,会存在多个版本共存的现象。这时,如果用户从旧版本实例上获取了index.html文件,然后再去获取旧版本的js、css文件(main-4656e35c1e8d4345f5bf.jsmain.4656e35c1e8d4345f5bf.css),但是请求却分发到了新版本服务实例上,这时因为新版本服务实例只有main-1711528240049.jsmain.1711528240049.css文件,就会导致访问失败。反过来,如果从新版本实例上获取了index.html文件,在请求相应的js、css文件时,也可能被分发到旧版本实例上,也导致访问失败。


解决方法:


1)首先,改造一下index.html文件中引用js、css等静态资源的路径,添加一个版本号,如v1、v2,这样index.html文件对js、css的引用变为:


<link href=/static/v1/css/main.1711528240049.css rel=stylesheet>
<script type=text/javascript src=/static/v1/js/main-1711528240049.js></script>

2)使用灰度发布策略升级系统,具体步骤如下(假设系统包含A、B两个服务实例)



  1. 升级前(稳态),在应用网关(代理)上配置路由策略V1,该路由策略的功能为:匹配路径前缀/static/v1的请求负载均衡分发到A、B两个服务实例
  2. 将待升级的服务实例A从路由策略V1中摘除掉,这时用户请求只会发送给实例B
  3. 待实例A上所有进行中的请求都处理完后,就可以安全的停掉旧的服务,替换为新的服务,这时还不会有请求分发到实例A
  4. 待实例B测试功能正常后,在应用网关(代理)上新增一条路由策略V2,该路由策略的功能为:匹配路径前缀/static/v2的请求分发到服务实例A。这时,从服务实例A上获取的index.html文件引发的后续js、css请求,都会分发到服务实例A,从服务实例B上获取的index.html文件引发的后续js、css请求,都会分发到服务实例B
  5. 继续将实例B从路由策略V1中摘掉,然后升级实例B,将实例B添加到路由策略V2中
  6. 所有的流量都切换到了路由策略V2中,下线路由策略V1。完成整个升级过程,实现了前端的无损升级

作者:movee
来源:juejin.cn/post/7353069220827856946

0 个评论

要回复文章请先登录注册