0


0

Python CGIを使用して外部データベースへの呼び出しを制限する

GPSサービスからデータを取得するPython CGIスクリプトがあります。この情報は、Webページで10秒ごとに更新されます(GPSサービスのTOSで許可されている最大値)。 しかし、たとえば100人のユーザーが同時にWebページを表示し、すべてがスクリプトを呼び出している可能性があります。

ユーザーのスクリプトは、それ自体が10秒に1回しか更新しないバッファーページからデータを取得する必要があると思います。 コンテンツを直接表示している人がいない(そしてCGIにアクセスしていない)場合、このバッファページを自動更新するにはどうすればよいですか? これを達成するためのより良い方法はありますか?

1 Answer


1


GPSデータクエリの結果を、日時とともにファイルまたはデータベース(sqlite)にキャッシュします。

次に、最後にキャッシュされた日時に対して日時チェックを実行して、別のGPSデータクエリを開始できます。

あなたはおそらくcgiとdatetime checkで並行性の問題に遭遇するでしょう…​

並行性の問題を回避するには、sqliteを使用して、書き込みをtry / exceptに入れることができます。 以下は、sqliteを使用したキャッシュの実装例です。

import datetime
import sqlite3

class GpsCache(object):
    db_path = 'gps_cache.db'
    def __init__(self):
        self.con = sqlite3.connect(self.db_path)
        self.cur = self.con.cursor()

    def _get_period(self, dt=None):
        '''normalize time to 15 minute periods'''
        if dt.minute < 15:
           minute_period = 0
        elif 15 <= dt.minute < 30:
           minute_period = 15
        elif 30 <= dt_minute < 45:
           minute_period = 30
        elif 45 <= dt_minute:
           minute_period = 25
        period_dt = datetime.datetime(year=dt.year, month=dt.month, day=dt.day, hour=dt.hour, minute=minute_period)
        return period_dt

    def get_cache(dt=None):
        period_dt = self._get_period(dt)
        select_sql = 'SELECT * FROM GPS_CACHE WHERE date_time = "%s";' % period_dt.strftime('%Y-%m-%d %H:%M')
        self.cur.execut(select_sql)
        result = self.cur.fetchone()[0]
        return result


    def put_cache(dt=None, data=None):
        period_dt = self._get_period(dt)
        insert_sql = 'INSERT ....'  # edit to your table structure
        try:
            self.cur.execute(insert_sql)
            self.con.commit()
        except sqlite3.OperationalError:
            # assume db is being updated by another process with the current resutls and ignore
            pass

キャッシュツールが実装側になりました。

最初にキャッシュをチェックしてから、「新鮮」ではない(何も返さない)場合は、現在のメソッドを使用してデータを取得します。 次に、取得したデータをキャッシュします。 おそらくこれをより良く整理する必要がありますが、ここで一般的なアイデアを得る必要があります。

このサンプルを使用して、「remote_get_gps_data」への現在の呼び出しを「get_gps_data」に置き換えるだけです。

from gps_cacher import GpsCache

def remote_get_gps_data():
    # your function here
    return data

def get_gps_data():
    data = None
    gps_cache = GpsCache()
    current_dt = datetime.datetime.now()
    cached_data = gps_cache.get_cache(current_dt)
    if cached_data:
        data = cached_data
    else:
        data = remote_get_gps_data()
        gps_cache.put_cache(current_dt, data)
    return data