为何我的GCP App Engine无法正确实现多版本流量拆分?
问题根因
你遇到的现象有两个常见原因:
- 你选择的是
--split-by ip分流策略,同一公网IP的所有请求会被永久固定路由到同一个版本,你在测试时使用的公网IP被分配到了v2,所以所有请求都只会落到v2上,属于正常特性而非故障。 - 浏览器/CDN缓存了v2版本的响应结果,即便后续路由规则生效,你拿到的还是之前缓存的v2返回内容。
解决步骤
1. 先验证分流功能本身正常
你可以先把分流策略改成随机模式验证配置是否生效:
gcloud app services set-traffic myservice --splits=v1=0.5,v2=0.5 --split-by random
修改后用无痕窗口/多台不同网络的设备发起请求,如果能同时拿到Hello world!和Hello Universe!的返回,说明分流功能本身没有问题,只是IP分流策略的特性导致你测试时一直命中v2。
如果还是只返回v2的内容,执行gcloud app services describe myservice确认splits配置是否真的更新为5:5的比例,排除配置未生效的问题。
2. 解决缓存导致的返回内容固定问题
如果确认分流配置正常但还是只拿到单一版本的返回,你可以通过修改响应头禁用缓存来避免这个问题,直接在Flask代码中给响应添加缓存控制头即可:
# v1和v2版本都做相同修改 from flask import make_response @app.route('/') def hello(): resp = make_response('Hello world!') # v2版本对应改为Hello Universe! resp.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' return resp
测试完成后如果生产环境需要开启缓存,再按需调整缓存策略即可。
3. 按版本区分URL路径的实现方法
如果你需要让两个版本的资源URL完全不同避免缓存冲突,不需要修改app.yaml,直接在Flask代码中给路由统一添加版本前缀即可,推荐用蓝图实现避免逐个修改路由:
# v1版本代码示例 from flask import Blueprint # 给所有v1的路由统一添加/v1前缀 v1_bp = Blueprint('v1', __name__, url_prefix='/v1') @v1_bp.route('/') def hello(): return 'Hello world!' # 注册蓝图到app app.register_blueprint(v1_bp)
v2版本对应将前缀改为/v2即可,修改后两个版本的访问路径分别为/v1和/v2,URL天然不同不会出现缓存冲突的问题。
内容的提问来源于stack exchange,提问作者Callista
相关产品推荐
相关产品推荐

