每次访问Flask视图时的增量计数器 [英] Increment counter for every access to a Flask view

查看:185
本文介绍了每次访问Flask视图时的增量计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当用户访问我的Flask应用中的页面时,我想增加一个计数器.如果有两个用户访问该页面,则计数应增加2.我尝试了以下操作,但计数始终为1.如何增加每次访问的值?

@app.route('/count')
def make_count():
    count = 0
    value = count + 1
    return jsonify(count=value)

解决方案

同时计数很难.假设计数为0.如果两个用户都以足够近的时间间隔命中端点,则他们每个人可能会获得值0,将其递增为1,然后放回原值.有两个用户命中了端点,但最终计数为1,而不是2.要解决此问题,您需要使用支持原子递增的数据存储(例如,一次只能有一个进程执行的操作). /p>

您不能使用简单的Python global,因为WSGI服务器将产生多个进程,因此它们每个都有各自独立的全局副本.重复的请求可以由不同的进程处理,从而导致不同的,不同步的值.

最简单的解决方案是Python multiprocessing.Value .只要在创建值后就生成了进程,就可以跨进程同步访问共享值.

from flask import Flask, jsonify
from multiprocessing import Value

counter = Value('i', 0)
app = Flask(__name__)

@app.route('/')
def index():
    with counter.get_lock():
        counter.value += 1
        out = counter.value

    return jsonify(count=out)

app.run(processes=8)
# access http://localhost:5000/ multiple times quickly, the count will be correct


仍有一些注意事项:

  • 仅当管理器处于活动状态时,数据才持久存在.如果重新启动服务器,计数器也会重置.
  • 如果应用程序进程分布在多台计算机上,则共享内存将遭受与全局内存相同的问题:它们仅在本地计算机上同步,而不在网络上同步.

在现实世界中, Redis 是一种更为强大的解决方案.服务器独立于Web应用程序,具有用于持久性的选项,并且可以进行原子增量.它也可以用于应用程序的其他部分,例如缓存.

I want to increment a counter when users access a page in my Flask app. If two users access the page, the count should increase by 2. I tried the following but the count is always 1. How do I increment the value for each access?

@app.route('/count')
def make_count():
    count = 0
    value = count + 1
    return jsonify(count=value)

解决方案

Counting concurrently is hard. Assume the count is 0. If two users both hit the endpoint at close enough intervals, they may each get the value 0, increment it to 1, and put it back. Two users hit the endpoint, but the resulting count is 1, not 2. To get around this, you need to use a data store that supports incrementing atomically (as in, an operation that only one process can do at a time).

You can't use a simple Python global because WSGI servers will spawn multiple processes, so they will each have their own independent copy of the global. Repeated requests could be handled by different processes, resulting in different, unsynchronized values.

The simplest solution is a Python multiprocessing.Value. This synchronizes access to a shared value across processes, as long as the processes are spawned after the value is created.

from flask import Flask, jsonify
from multiprocessing import Value

counter = Value('i', 0)
app = Flask(__name__)

@app.route('/')
def index():
    with counter.get_lock():
        counter.value += 1
        out = counter.value

    return jsonify(count=out)

app.run(processes=8)
# access http://localhost:5000/ multiple times quickly, the count will be correct


There are still some caveats:

  • The data only persists as long as the manager is alive. If you restart the server, the counter resets too.
  • If the application processes are distributed across multiple machines, shared memory suffers the same issues as globals: they are only synchronized on the local machine, not across the network.

For real world scenarios, Redis is a much more robust solution. The server is independent of the web application, has options for persistence, and can do atomic increments. It can also be used for other parts of the application, such as caching.

这篇关于每次访问Flask视图时的增量计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆