【问题标题】:Django local memory caching not working on herokuDjango本地内存缓存在heroku上不起作用
【发布时间】:2020-12-21 22:22:51
【问题描述】:

我需要使用基于 SMS 的 OTP 在我的 django-rest-framework 应用程序中对用户进行身份验证。为此,我创建了以下 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 吗?

【问题讨论】:

    标签: python django heroku caching django-rest-framework


    【解决方案1】:

    关于 Heroku 上的本地内存缓存

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

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

    现在关于一般设置问题:

    一般来说,本地缓存对于生产使用来说是完全可以的(并且非常快),如果进程/测功机限制对您来说很好,并且您无法在不重新启动所有测功机的情况下清除整个缓存。

    文件系统缓存也可以工作,但仅在您的测功机本地,这意味着只有重新启动所有测功机才能清理它。

    在一个应用程序有多个服务器/容器的环境中,实际上最好在某个地方有一个单独的缓存,比如 redis、memcached,......所有 dynos 都可以访问。

    缓存和一次性密码

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

    在您的情况下,您可以configure separate cache only for the OTP tokens,它大到足以容纳所有当前有效的令牌。

    【讨论】:

      猜你喜欢
      • 2017-10-08
      • 2018-07-17
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 2011-10-25
      • 1970-01-01
      相关资源
      最近更新 更多