python - 缓存还是其他?页面未使用 Flask / nginx 更新
问题描述
我建立了一个使用 Flask、nginx 和 uWSGI 的网站。
该网站需要始终显示最新的信息。我一直在通过更改我的网站的主题来测试它。我通过将十六进制值存储在 JSON 文件中,然后在我的 app.py 首次调用时检索该值来使这个主题工作。每当他们保存配置时,我都会更新全局 theme_colour 变量。然后我将 theme_colour 传递给每个 render_template 并在 HTML 中我有一个包含类似这样的样式标签
h1 {
color: {{ theme_colour }}
}
我的问题是,当我更新主题时,它应该立即更改所有页面,但事实并非如此。当我在配置页面上更新它时,它会自动重新加载页面并且更改在那里工作,但是当我导航到另一个页面时它使用旧颜色。有时刷新页面会修复它,但随后在页面之间随机交换通常会导致它出于某种原因换回旧颜色。清除缓存并刷新它会将其修复在该页面上,但随后导航到另一个页面并返回它通常会换回旧颜色。
我无法弄清楚这里发生了什么。在我正确托管网站之前,我对主题没有任何问题(之前它只是在开发服务器上)。我试图消除这样的缓存,但显然没有奏效:
server {
listen 80 default_server;
server_name mydomain.com www.mydomain.com;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/test/test.sock;
# kill cache
sendfile off;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl default_server; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot#
server_name mydomain.com www.mydomain.com;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/ubuntu/test/test.sock;
# kill cache
sendfile off;
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
proxy_no_cache 1;
proxy_cache_bypass 1;
}
}
每当我发送 GET 请求时,它都会说响应标头包含Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0
,所以我不确定这是否是问题所在。
这是我所有的 theme_colour 代码:
@app.route("/index")
def load_index():
if check_logged_in(session, 0): # if user is logged in, doesn't require elevated privileges
return render_template("index.html", theme_colour=theme_colour) # logged in
else:
return redirect("/login") # not logged in
@app.route("/config", methods=["POST", "GET"])
def load_config():
if check_logged_in(session, 2): # if user is logged in, does require elevated privileges
if request.method == "POST": # if user clicks update button
global theme_colour # make theme colour accessible to all pages
config = list(request.form.values()) # get input box values
save_config(config) # save values to json
theme_colour = update_theme() # find theme colour and update global variable
return render_template("config.html", theme_colour=theme_colour)
else:
return abort(403) # forbidden if not logged in
def update_theme(): # get current theme colour
with open("config.json", "r") as json_file:
data = json.load(json_file)
theme_colour = data["colour"]
return theme_colour
theme_colour = update_theme()
我觉得我在这里错过了一些东西。有没有人有任何想法?
谢谢。
解决方案
啊,是的,要跟进@SuperShoot 在评论中所说的话:您不能在大多数 Web 服务器上下文中可靠地使用全局变量。大多数情况下,您将拥有多个处理请求的进程(或至少一个随时可能死亡并重生的进程),并且这些进程之间不会共享全局变量。
为了在请求之间可靠地共享状态,您需要为其使用一些外部存储(除非您可以将状态存储在session
- 在这种情况下,它不会在不同的客户端之间共享)。
我建议为此连接Redis,但还有其他选择,例如
- 文件系统(作为平面文件(例如
/tmp/myapp/theme.txt
)shelve
或类似文件) - 另一个缓存服务器,例如 Memcache
- 一个数据库(SQLite,一些其他的 SQL,其他的东西)
- uWSGI 的缓存子系统(虽然它显然只是 uWSGI)
- uWSGI 的 SharedArea 子系统(非常低级,不推荐,但它就在那里)
然后的想法是在需要时(或为每个请求)从后端加载共享值。
无论哪种方式,我都非常有信心您可以摆脱 Nginx 中的所有缓存配置 - Nginx 不会自行缓存内容,除非被告知(通过其配置,或者可能通过您的应用程序发送的标头)。
推荐阅读
- java - 导出时损坏的 Excel xlsx
- powershell - 批处理文件中的退出代码不会传播到父 powershell 脚本
- angular - 角材料表 - 可访问的问题 - 无法使用键盘访问
- c# - C# 获取文件 Outlook 附件单选多选文件 Win 7, Win 10
- google-cloud-firestore - 在 Cloud Firestore 中获取大集合中的文档数量
- java - InvocationTargetException:使用 Aion Embedded AVM 时 Dapp 调用失败
- javascript - JavaScript示例中Function Monoids的二元运算符是什么
- python - 如何将我的 JSON 变成更易于阅读的内容?
- reactjs - setState() 上的受控输入更改
- angular - 为 React/Angular SPA 将服务器请求重定向到 /index.html