动态添加服务器到memcached

Dynamically add server to memcached

我正在我的 Elastic Beanstalk 上设置 memcached

Amazon 的 Elastic 缓存也是一个不错的选择,但由于我的使用量会很少,因此拥有一个单独的 ec2 实例用于缓存 运行 对我来说全职似乎有点过分了,而且,它是贵。

由于我的应用程序在 python 上 运行,我将使用 python 客户端与 memcached.[=12= 通信]

当 Elastic beanstalk 扩展 up/down 时,它 adds/removes 一些实例。我想动态 add/remove memcached 服务器以防发生这种情况。在缩小规模的同时丢失一些缓存似乎是完全可以接受的。

我怎样才能做到这一点?

编辑:

我发现了一个类似的问题here

但是答案并没有提供这个问题的解决方案,只是一个解决方法(它建议使用另一个免费的小使用量服务,网络延迟会减慢速度,所以不是一个好的选择)

您可以创建一个负载平衡的 EB 环境,并按照您告诉它何时扩大和缩小的方式进行设置。
在缩放部分中,将 "Minimum instance count" 设置为 1,将 "Maximum instance count" 设置为您需要的最大缓存主机数。
现在编写一个简短的 (python) 脚本来检查有多少 ec2 实例已启动并决定是否仍需要当前的内存缓存框。如果需要终止该框,请将其设置为 return HTTP 500 或任何其他错误代码。
现在在 "EC2 Instance Health Check" 部分中,将 "Application health check URL" 指向一个简短的 python 代码,该代码 return 是一个错误代码,以防需要销毁缓存服务器。
这将按照您的指示将应用程序框的数量与缓存服务器的数量相关联。

好的,这就是我最后做的事情。

我向我的应用程序添加了一个 post 部署挂钩。现在,每当我部署到 Elastic Beanstalk 时,post 部署挂钩中的脚本都会安装 memcached 并在本地实例上运行 memcached 服务器。

之后,脚本连接到 RDS 实例上的 MySQL 服务器,并通过在 memcached_servers table.

中创建一个条目来注册它的 IP

现在,在客户端,我们使用 pylibmc 创建一个 memcached 客户端,使用从 memcached_servers table 获取 IP 的助手 class每小时一次,如果服务器已更改,则重新创建一个新客户端。

mc_client.py:

class MCClient(object):

    _mc_client = None
    _last_refresh = time.time()
    _refresh_client_in = 3600  # seconds, 1 hour
    _servers = []

    @staticmethod
    def client():
        if MCClient._mc_client is None or MCClient.client_timeout():
            MCClient._mc_client = MCClient.new_memcached_client()
        return MCClient._mc_client

    @staticmethod
    def client_timeout():
        return (time.time() - MCClient._last_refresh) > MCClient._refresh_client_in

    @staticmethod
    def fetch_memcached_servers():
        MCClient._last_refresh = time.time()
        return list(MemcachedServer.objects.filter(active=True).values_list('ip', flat=True))

    @staticmethod
    def new_memcached_client():
        servers = MCClient.fetch_memcached_servers()
        if MCClient._mc_client is not None and set(MCClient._servers) == set(servers):
            # do not bother recreating a client, if the servers are still the same
            return MCClient._mc_client
        else:
            MCClient._servers = servers
            return pylibmc.Client(MCClient._servers, binary=True, behaviors={
                'tcp_nodelay': True,
                'ketama': True,
                'no_block': True,
                'num_replicas': min(len(MCClient._servers) - 1, 4),  # if a server goes down we don't loose cache
                'remove_failed': 3,
                'retry_timeout': 1,
                'dead_timeout': 60
            })

为了获得客户,我 mc = MCClient.client()。这样每次 Elastic Beanstalk 扩展 up/down memcached 服务器都会在一小时内更新。此外,作为一种安全机制,缓存最多复制到 4 台服务器上,这样我们就不会在服务器出现故障时丢失缓存。