Increment counter for every access to a Flask view

前端 未结 2 1375
Happy的楠姐
Happy的楠姐 2020-12-05 19:15

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

2条回答
  •  南方客
    南方客 (楼主)
    2020-12-05 20:05

    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.

提交回复
热议问题