Django本地内存缓存在heroku上不工作

2024-04-19 04:03:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要使用基于SMS的OTP对django rest框架应用程序中的用户进行身份验证。为此,我创建了以下API端点

GET \otp - generate and send OTP and store it in cache
POST \otp - validate OTP based on value store in cache

这是我的密码-

from django.core.cache import cache

# It is used just for debugging & logging purpose
local_cache = {}

class OTPView(APIView):
    def get(self, request):
        serializer = ContactSerializer(data=request.query_params)
        num = serializer.validated_data.get('contact_number')
        otp = generate_otp()
        cache.set(num, otp, 300)
        local_cache[num] = otp
        print('GET Cache is : ', local_cache)
        return Response('OTP Sent')

    def post(self, request):
        serializer = OTPSerializer(data=request.data)
        num = serializer.validated_data.get('contact_number')
        otp = serializer.validated_data.get('otp')
        print('POST Cache is : ', local_cache)
        otp_in_cache = cache.get(num)
        if otp_in_cache is None:
            return Response('No OTP or prev expired')
        elif otp == otp_in_cache:
            return Response('Success')
        else:
            return Response('Incorrect OTP')

要在内存缓存中使用的两个请求之间持久化OTP。它在我的本地机器上按预期工作,但在部署到Heroku上时却无法正常工作。以下是heroku的日志供参考-

2020-09-02T17:17:22.556785+00:00 app[web.1]: Number is 6666660008 and otp is 541609
2020-09-02T17:17:22.556798+00:00 app[web.1]: GET Cache is :  {'6666660008': '541609'}
2020-09-02T17:17:22.558975+00:00 app[web.1]: 10.69.31.173 - - [02/Sep/2020:22:47:22 +0530] "GET /account/api/otp/?contact_number=6666660008 HTTP/1.1" 200 36 "https://direct-fresh-chicken.netlify.app/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/77.0.3865.90 Chrome/77.0.3865.90 Safari/537.36"
2020-09-02T17:17:32.897997+00:00 app[web.1]: POST Cache is :  {}
2020-09-02T17:17:32.898035+00:00 app[web.1]: Error 400: No OTP or prev expired.
2020-09-02T17:17:32.900342+00:00 app[web.1]: 10.69.31.173 - - [02/Sep/2020:22:47:32 +0530] "POST /account/api/otp/ HTTP/1.1" 400 66 "https://direct-fresh-chicken.netlify.app/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/77.0.3865.90 Chrome/77.0.3865.90 Safari/537.36"

我知道本地内存缓存不适合生产,最终我计划使用更好的替代方案,如memcached

我想知道-

  • 为什么本地内存缓存不能在heroku上运行
  • 为什么local_cache字典对象在post方法中有空值(请参阅日志)
  • 我可以在heroku上使用file system caching吗?如果是,我应该使用什么配置
  • 除了使用缓存,还有其他可能的方法来验证OTP吗

Tags: inappcachedatagetisrequestlocal
1条回答
网友
1楼 · 发布于 2024-04-19 04:03:26

关于Heroku上的本地内存缓存

一般来说,本地内存缓存在Heroku上运行良好。但是有一个限制:dict和Djangolocmem缓存后端都是进程和dyno的本地

因此,例如,如果您使用gunicorn,默认情况下它将使用子进程来处理请求。每个子进程都有自己的locmem缓存。这个default ^{} setting is at least 2, depending on the dyno size

现在关于一般设置问题:

一般来说,本地缓存对于生产使用来说是完全好的(而且速度非常快),前提是进程/动态限制对您来说很好,并且您无法在不重新启动所有动态对象的情况下清除整个缓存

文件系统缓存也可以工作,但也只是dyno的本地缓存,这意味着只有通过重新启动所有dyno才能进行清理

在一个应用程序有多个服务器/容器的环境中,实际上最好有一个单独的缓存,比如redis、memcached等等。。。所有的迪诺人都能进入

缓存和OTP

通常,您可以使用此处的缓存来存储令牌。这里的风险在于,具体取决于实际的缓存后端:如果缓存已满,它将删除数据。对于真正的缓存来说,这通常是很好的,但对于OTP来说,这将是一个问题

在您的例子中,您可以configure separate cache only for the OTP tokens,它足够大,可以容纳所有当前有效的令牌

相关问题 更多 >