【问题标题】:Dynamically add server to memcached将服务器动态添加到 memcached
【发布时间】:2016-01-16 22:50:07
【问题描述】:

我正在我的 Elastic Beanstalk 上设置 memcached

Amazon 的 Elastic 缓存也是一个不错的选择,但由于我的使用量将很少,因此在我的情况下,拥有一个单独的 ec2 实例来全时运行缓存似乎有点过头了,而且价格昂贵。

由于我的应用程序在 python 上运行,我将使用 python 客户端与 memcached 进行通信。

当 Elastic beanstalk 向上/向下扩展时,它会添加/删除一些实例。如果发生这种情况,我想动态添加/删除 memcached 服务器。在缩小的同时丢失一些缓存似乎完全可以接受。

我怎样才能做到这一点?

编辑:

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

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

【问题讨论】:

    标签: python amazon-web-services amazon-ec2 memcached amazon-elastic-beanstalk


    【解决方案1】:

    您可以创建负载平衡的 EB 环境,并以您告诉它何时扩大和缩小规模的方式对其进行设置。
    在“缩放”部分中,将“最小实例数”设置为 1,将“最大实例数”设置为您需要的最大缓存主机数。
    现在编写一个简短的 (python) 脚本来检查有多少 ec2 实例已启动并决定是否仍需要当前的 memcache 框。如果需要终止该框,请使其返回 HTTP 500 或任何其他错误代码。
    现在在“EC2 实例健康检查”部分,将“应用程序健康检查 URL”指向一个简短的 Python 代码,该代码会在需要销毁缓存服务器时返回错误代码。
    这将按照您的指示将应用程序框的数量与缓存服务器的数量联系起来。

    【讨论】:

      【解决方案2】:

      好的,这就是我最终要做的。

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

      之后,脚本会连接到 RDS 实例上的 MySQL 服务器,并通过在 memcached_servers 表中创建条目来注册其 IP。

      现在,在客户端,我们使用 pylibmc 创建一个 memcached 客户端,使用一个帮助程序类,每小时一次从 memcached_servers 表中获取 IP,并在服务器发生更改时重新创建一个新客户端。

      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 向上/向下扩展 memcached 服务器都会在一小时内更新。此外,缓存最多在 4 台服务器上复制,作为一种安全机制,这样我们就不会在服务器出现故障时丢失缓存。

      【讨论】:

        猜你喜欢
        • 2016-01-30
        • 2012-07-27
        • 1970-01-01
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多