You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在搭载NGINX的Elastic Beanstalk环境中,动态将EC2实例私有IP添加至Django的CACHE LOCATION配置是否合理?

解答你的Elastic Beanstalk + Django + Memcached缓存问题

先直接给你两个核心问题的答案,再解决你遇到的缓存set后get返回None的异常:

核心问题1:是否需要添加所有EC2私有IP到CACHES的LOCATION?

必须添加所有当前EB环境的EC2实例私有IP,不能只写127.0.0.1:11211。

原因很简单:你的NGINX配置只是把请求反向代理到本地的Django服务(proxy_pass http://127.0.0.1:8000),这意味着每个EC2实例上都独立运行着Django进程和Memcached进程。如果只配置127.0.0.1,每个实例的缓存完全独立——当负载均衡把请求打到实例A时,你set的缓存只存在于A的Memcached里;后续请求打到实例B时,自然get不到这个值。

只有把所有实例的私有IP都加入LOCATION,Django的Memcached后端才能利用Memcached的分布式特性,把所有实例的Memcached组成一个统一的缓存池,不管请求落到哪个实例,都能访问到共享的缓存数据。

核心问题2:NGINX是否会集中管理缓存?

不会。你的NGINX在这里只是扮演反向代理的角色,负责把外部请求转发到本地的Django服务,它完全不参与缓存的管理逻辑。缓存的读写、分布式调度都是由Django的Memcached客户端(你用的PyMemcacheCache)和各个实例上的Memcached进程共同完成的。


解决你遇到的缓存set后get返回None的异常

你已经正确获取了实例IP并配置到CACHES里,但缓存无法正常读写,大概率是以下几个原因之一,按顺序排查:

1. 安全组限制了Memcached的跨实例访问

每个EC2实例的安全组需要允许同一EB环境内其他实例的私有IP段访问11211端口。默认情况下,Memcached监听11211端口,但如果安全组只允许127.0.0.1/32访问,其他实例根本连不上这个端口,自然无法写入或读取缓存。

排查方法:在某台实例上执行telnet 另一实例的私有IP 11211,如果连接失败,立刻去调整安全组规则,添加一条入站规则:允许来自当前EB环境实例所在私有子网IP段的流量访问11211端口。

2. Memcached绑定了本地回环地址

检查Memcached的配置文件(通常路径是/etc/memcached.conf),看-l参数的值:

  • 如果是-l 127.0.0.1,Memcached只会监听本地回环接口,其他实例无法连接;
  • 必须改成-l 0.0.0.0或者实例的私有IP,这样才能接受来自其他实例的连接。

修改后重启Memcached服务:sudo systemctl restart memcached

3. Boto3代码获取了无关的EC2实例

你的当前代码是获取所有EC2实例,但可能包含了其他环境的实例、已停止的实例,这些无效IP会导致Django客户端尝试连接不可用的Memcached节点,进而影响缓存读写。

优化你的代码,通过EB环境的标签过滤出当前环境的运行中实例:

class MemcachedLocations(object):
    MEMCACHED_PORT = "11211"
    # 从EB环境变量获取当前环境名称和AWS区域(EB会自动注入这些变量)
    EB_ENV_NAME = os.environ.get('EB_ENVIRONMENT')
    REGION = os.environ.get('AWS_REGION', 'us-west-2')

    @cached_property
    def get(self):
        # EB会自动为实例赋予IAM角色,无需硬编码AK/SK,直接用默认凭证即可
        client = boto3.client('ec2', region_name=self.REGION)
        response = client.describe_instances(
            Filters=[
                {
                    'Name': 'tag:elasticbeanstalk:environment-name',
                    'Values': [self.EB_ENV_NAME]
                },
                {
                    'Name': 'instance-state-name',
                    'Values': ['running']
                }
            ]
        )
        private_ips_list = []
        for reservation in response['Reservations']:
            for instance in reservation['Instances']:
                private_ip = instance['PrivateIpAddress']
                private_ips_list.append(f"{private_ip}:{self.MEMCACHED_PORT}")
        return private_ips_list

注意:EB环境会自动为实例分配IAM角色,只要给角色添加ec2:DescribeInstances权限,就不需要硬编码AK/SK,更安全也更易维护。

4. 检查PyMemcache依赖和配置

确保你已经安装了pymemcache包(Django的PyMemcacheCache后端依赖它),可以在EB的requirements.txt里加入pymemcache>=4.0.0。另外,你可以尝试给CACHES添加一些调试参数,快速定位连接问题:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
        'LOCATION': MemcachedLocations().get,
        'OPTIONS': {
            'connect_timeout': 1,
            'timeout': 1,
            'use_pooling': True,
        }
    }
}

超时参数能帮你快速发现连接问题,如果有连接超时的错误,就能定位到网络或Memcached配置的问题。


内容的提问来源于stack exchange,提问作者Jarad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 18:17:37