1
MelodYi 238 天前
相比粗暴地取随机比例,可以考虑用取模之类的方式筛选一部分固定的用户选择新版本。类似 A 、B 测试的感觉。
|
2
coderxy 238 天前
楼上+1
|
4
Seulgi 238 天前 1
你说的粘性会话是一个方案.1 楼说的也是一种方案,一般为了精准灰度用户,会根据用户数量做分组,然后组内用户进灰度。粘性会话其实就是在每次请求里加上标志位,header 也好,session 也好,cookie 也好,然后网关处理路由。
|
6
xderam 238 天前
想问下,这种的情况不是应该返回新的静态资源版本吗?例如 http://domain/a.png?v=123 灰度只灰度了后端,前端最好也同步控制。而不是用粘性会话来解决。粘性会话感觉更合适的场景是后端“异常”的时候的方式。
|
7
paopjian 238 天前
这个问题不应该是资源的缓存问题吗, 我们直接给 js css 加了随机 hash,每次发布都变化, 这样可以强制刷新
|
8
Frankcox OP @xderam 不好意思,我没太看懂,我理解这个问题反而后端服务会好一些,不用特殊处理吧?比如通常情况下单个 api 请求被分流到了 A 服务那就是 A 服务。相反,对于前端的服务,除了 HTML 还有剩余的一堆静态资源,这种多次请求会因为权重规则导致分裂。当然我指的现在的服务都是没做 version 处理适配灰度这种情况
|
9
lasuar 238 天前 2
最佳的办法当然是权重+粘性会话。k8s 中的 nginx ingress 支持这些功能,但是否支持组合使用还不清楚,理论推测应该是可以的。nginx ingress 通过下面这些注解来实现对应功能:
- nginx.ingress.kubernetes.io/affinity:true 。启用会话粘性,通过 cookie - nginx.ingress.kubernetes.io/session-cookie-name:?。设置具体的 cookie 字段 - nginx.ingress.kubernetes.io/affinity-mode:粘性模式,balanced or persistent - nginx.ingress.kubernetes.io/canary:true 。启用金丝雀发布 - nginx.ingress.kubernetes.io/canary-weight:number 。按权重 - nginx.ingress.kubernetes.io/affinity-canary-behavior:配置启用金丝雀发布时的粘性模式,sticky or legacy 其他功能还支持正则匹配 header ,这些都是在 k8s 组件层面上支持的功能,不需要编码。 参考: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md |
11
blackrabbit 238 天前
赞成 7 楼的理解,绝大部分灰度能力对访问发布到 S3 的文件( HTML 文件等)进行流量灰度,不会对 JS/CSS 等 CDN 的静态资源文件进行灰度,所以将静态资源 hash 即可
|
12
xderam 238 天前
@Frankcox 如果前提是没有做 version 的话,那就耐心的等待缓存到期或者全量发布完之后?我是感觉不应该用服务端的粘性会话去处理这个场景。如果 A 和 B 这种状态要长期存在,还是用一楼的方式比较好。或者四楼的那种“粘性会话”的方式也是不错的选择,这些都是业务侧可控的。而运维侧负载均衡提供的“粘性会话”是比较危险和不可控的,不太建议。以上不分前端后端的一个大原则。
不说后端 就是前端的话 。请求到新的 HTML 最好里面已经告诉浏览器去加载新的静态资源( version 为新的)。这就又回到 version 控制( hash )的问题上了。反正就是自主可控,虽然很繁琐,但打包发布工具这时候就有作用了。如果坚持不用 version 或者 hash 的方式话。上了 CDN 你又要找其它的“粘性会话”方案了。并非一劳永逸。 |
13
lasuar 238 天前
@paopjian #7 hash 变更是为了让前端刷新静态资源,但后端还有个问题就是如何让同个用户发出的多个资源请求都路由到同一组服务。
具体来说,灰度/金丝雀发布后,后端会存在 v1,v2 两组新旧版本的服务,来自同个用户的多个页面请求要么都由 v1 处理,要么都由 v2 处理,这样页面才会正常显示;比如正在上线端午活动页,结果有个用户的页面显示为:标题是“庆祝五一”( v1 服务处理),但图片显示的却是端午活动页( v2 服务处理),这是不允许出现的。 |
14
xderam 238 天前 1
|
15
xingdaorong 238 天前
我们灰度是前端打包 2 次,一个是旧的,一个是新的,服务端通过用户信息判断用户是否是在灰度名单中,在就返回对应 html ,我们 html 中有 2 个 hashjs ,1 个 css ,服务端只需要动态改这 3 个 hash 返回前端就行。
|
17
qishua 238 天前
客户端上传 cdn 的静态资源里,包含一个 hash 或者 version 文件,先客户端静态资源 cdn 上传,然后服务端这边例如 gs1-gs10 ,更新 gs1 到新的版本,然后客户端访问 gs1 的时候会拿到最新的静态资源版本号,然后会更新客户端包体,更新过后,既可访问最新的 gs1 服务及对应的最新的客户端静态资源。
|
18
Frankcox OP @xderam #12 谢谢,我又看了下我们的一个前端服务,css 和 js 这两个确实已经做了 hash ,请求路径里有?v=1231231 这种情况。我没怎么写过前端,这里我还有个问题,如果我访问的基础 document 是旧服务 B ,剩余的这些 js,css 请求被分流到了最新的 A 服务,hash 版本对不上的话会发生什么?强制刷新缓存?如果这个强制刷新的请求又被分流到了新的 A 服务上呢?
|
19
fregie 238 天前
单纯靠 Ingress 也不是不行,在网关加 header 并根据 header 路由到不同服务
但要看你的 api 网关支不支持 |
20
bli22ard 238 天前
有一种简单的不够优雅的做法,前端入口处做重定向,v1.xxx.com v2.xxx.com 按照灰度规则跳转不同的版本。
还有一种方法,把所有 js css 图片合并到一个 web 服务里面,旧的和新的静态资源全部由这个服务提供,前提条件是对文件名设置了 hash 值,index.html 按照灰度规则后端下发对应版本就可以了 |
21
dyllen 238 天前
借楼问下,灰度存在新旧两个版本的情况下,后端数据库新旧两个版本是如何处理?如果要回滚新数据怎么办?
|
22
MelodYi 238 天前
@Frankcox nginx-ingress 这类是可以的。
原始流量里有 userid 之类的指标,取个模。 你还能自行调整过滤的比例。第一天 10%,第二天 50%之类的。 再复杂的也能走 lua 脚本之类的搞定的七七八八。 |
23
F7TsdQL45E0jmoiG 238 天前
好歹用源 ip 做 hash ,纯随机不靠谱
|
24
gotosre 238 天前
如果带 hash/特征资源的先上传,最后上传 index 页面,是不是也可以解决
然后 cdn 上保留至少 2 个版本的前端资源 无论用户加载到哪个 index.html ,都能找到资源了呢 不知道这个思路对不对 |
25
whileFalse 238 天前 via Android
设置粘性。
另外静态文件应该使用对象存储+哈希文件名,也就是发版之后任何版本的静态文件应该都存在于静态资源路径里。 |