吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1699|回复: 11
收起左侧

[已解决] Django中间件在uWSGI部署后统计ip每分钟的访问频率出现问题

[复制链接]
thepoy 发表于 2019-11-23 21:52
本帖最后由 thepoy 于 2019-11-24 12:50 编辑

正在学习中间件,于是写了个Demo,这个Demo在runserver下中间件的运行是正常的,但部署到uWSGI后就无法正常统计ip每分钟的访问频率了,百度和谷歌后也没能找到解决我困惑的答案。

很简单的Demo

import time

from django.core.cache import cache
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin

class FindIPMiddleware(MiddlewareMixin, SaveIP):
    def process_request(self, request):
        ip = request.META.get('REMOTE_ADDR')

        black_list = cache.get('black', [])    # 如果cache中没有black,就返回一个空列表
        if ip in black_list:
            return HttpResponse('此ip因多次违规,已被禁止访问')

        # 将每次指定ip访问的时间记录在requests中
        requests = cache.get(ip, [])
        # 为了测试是否与uWSGI的多线程和多进程有关,将每次访问的requests记录在test.txt中
        with open('test.txt', 'a') as f:
            f.write(str(requests)+'\n')

        # 如果requests存在且当前时间与最早访问的时间差大于60秒,就pop掉
        while requests and time.time() - requests[-1] > 60:
            requests.pop()
        # 将当前访问的时间插入为requests列表的第一个
        requests.insert(0, time.time())
        # 将ip-requests放到缓存中
        cache.set(ip, requests, timeout=60)

        # 如果requets长度大于30,封禁ip,大于等于10小于30警告
        if len(requests) > 30:
            black_list.append(ip)
            cache.set('black', black_list, timeout=60*60*24)
            return HttpResponse('ip被封禁')
        if len(requests) >= 10:
            return HttpResponse('请求频率过高,已被限制访问,如果继续恶意访问,将被添加进黑名单')
        return None

开发环境与线上环境分别访问10次,生成两个text.txt文件
runserver开发服务器下生成的test.txt文件:

[]
[1574515435.201666]
[1574515436.6527722, 1574515435.201666]
[1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515438.856246, 1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515439.553581, 1574515438.856246, 1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515440.3515499, 1574515439.553581, 1574515438.856246, 1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515441.155905, 1574515440.3515499, 1574515439.553581, 1574515438.856246, 1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]
[1574515441.787576, 1574515441.155905, 1574515440.3515499, 1574515439.553581, 1574515438.856246, 1574515438.1917062, 1574515437.4844859, 1574515436.6527722, 1574515435.201666]

这是线上环境生成的test.txt文件:

[]
[]
[]
[]
[1574516234.4257581]
[1574516232.7529194]
[1574516233.7064342]
[1574516235.0543022]
[1574516237.4400864, 1574516235.0543022]
[1574516236.268929, 1574516232.7529194]

这是uWSGI.ini配置文件:

[uwsgi]
http=0.0.0.0:8888

chdir=/home/thepoy/django/javaScript

wsgi-file=javaScript/wsgi.py

processes=4
threads=2
enable-threads=True
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log

开发text.txt文件的记录是逐条增加的,
但是线上text.txt文件却非如此,这样就无法正常统计ip每分钟的访问频率了。

个人觉得出现这个问题应该是与uWSGI的多进程和多线程有关,但是这不要紧,我想知道怎么才能解决这个问题,请各位大佬们指点一下,谢谢!

已解决:

此问题确实是因为uWSGI的多进程引起的,具体原因就是每个进程的django的cache不共享,每次访问时无法获取其他进程中的cache。

所以在多进程中,不宜使用cache进行ip访问频率的统计,可以用session(默认session就是个表)或数据库

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

anshingy 发表于 2019-11-23 22:09
每个访问ip都用txt文件进行打开、存储不敢想象
期待呀 发表于 2019-11-23 22:13
 楼主| thepoy 发表于 2019-11-24 09:15
anshingy 发表于 2019-11-23 22:09
每个访问ip都用txt文件进行打开、存储不敢想象

txt是测试用的,真正ip的访问记录是在缓存里
 楼主| thepoy 发表于 2019-11-24 12:47
看来52里用django的人不多啊
lucka 发表于 2019-11-25 09:33
学习学习
lucka 发表于 2019-11-25 09:36
也在用Django开发产品 还没遇到过这个需求
天黑我隐身 发表于 2019-11-25 13:30
这个问题并不是不能用cache来解决
Django默认配置下缓存使用本地内存,所以多进程无法共享缓存信息
换一种缓存配置如Redis、Memcache、数据库甚至本地文件等都可以解决这个问题
 楼主| thepoy 发表于 2019-11-25 16:38
天黑我隐身 发表于 2019-11-25 13:30
这个问题并不是不能用cache来解决
Django默认配置下缓存使用本地内存,所以多进程无法共享缓存信息
换一 ...

txt已经是本地文件了啊,我现在还在纳闷为什么续写txt无法正确记录访问事件。
redis倒是没测试,session默认就是数据库,这个没毛病
天黑我隐身 发表于 2019-11-25 17:44
本帖最后由 天黑我隐身 于 2019-11-25 17:46 编辑
thepoy 发表于 2019-11-25 16:38
txt已经是本地文件了啊,我现在还在纳闷为什么续写txt无法正确记录访问事件。
redis倒是没测试,session ...

代码中的test.txt和缓存没有关系,只是每个请求来到时你在test.txt追加一条requests记录
requests从缓存中取出,这个缓存并没有被多进程共享
看配置文件使用了4个线程,假设访问被平均分配到每一个进程
前4次访问cache中的ip都是空,所以requests = []
第5次访问回到第一个进程,这时cache中有第一次访问数据,requests会存放第一个访问时间
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-27 00:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表