Skip to content

Commit

Permalink
Refactor memcache config and MemcacheRing loading
Browse files Browse the repository at this point in the history
The loading and creation of the Memcache ring in the middleware is
rather interesting. It not only reads the config file, but also may
look for a `/etc/swift/memcache.conf`. Further, we are know are
looking at using the MemcacheRing client in more places.

So this patch moves the config reading from the middleware and
into a `load_memcache` helper method in swift/common/memcached.py.

Drive-by: cleanup unused stuff in middleware test module

Change-Id: I028722facfbe3ff8092b6bdcc931887a169cc49a
  • Loading branch information
matthewoliver authored and alistairncoles committed Oct 26, 2022
1 parent 51730f1 commit a8516e1
Show file tree
Hide file tree
Showing 4 changed files with 332 additions and 307 deletions.
103 changes: 101 additions & 2 deletions swift/common/memcached.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,20 @@
http://github.com/memcached/memcached/blob/1.4.2/doc/protocol.txt
"""

import os
import six
import json
import logging
import time
from bisect import bisect

from eventlet.green import socket
from eventlet.green import socket, ssl
from eventlet.pools import Pool
from eventlet import Timeout
from six.moves import range
from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError
from swift.common import utils
from swift.common.utils import md5, human_readable
from swift.common.utils import md5, human_readable, config_true_value

DEFAULT_MEMCACHED_PORT = 11211

Expand Down Expand Up @@ -204,6 +206,10 @@ def __init__(
self.logger = logger
self.item_size_warning_threshold = item_size_warning_threshold

@property
def memcache_servers(self):
return list(self._client_cache.keys())

def _exception_occurred(self, server, e, action='talking',
sock=None, fp=None, got_connection=True):
if isinstance(e, Timeout):
Expand Down Expand Up @@ -554,3 +560,96 @@ def get_multi(self, keys, server_key):
return values
except (Exception, Timeout) as e:
self._exception_occurred(server, e, sock=sock, fp=fp)


def load_memcache(conf, logger):
"""
Build a MemcacheRing object from the given config. It will also use the
passed in logger.
:param conf: a dict, the config options
:param logger: a logger
"""
memcache_servers = conf.get('memcache_servers')
try:
# Originally, while we documented using memcache_max_connections
# we only accepted max_connections
max_conns = int(conf.get('memcache_max_connections',
conf.get('max_connections', 0)))
except ValueError:
max_conns = 0

memcache_options = {}
if (not memcache_servers
or max_conns <= 0):
path = os.path.join(conf.get('swift_dir', '/etc/swift'),
'memcache.conf')
memcache_conf = ConfigParser()
if memcache_conf.read(path):
# if memcache.conf exists we'll start with those base options
try:
memcache_options = dict(memcache_conf.items('memcache'))
except NoSectionError:
pass

if not memcache_servers:
try:
memcache_servers = \
memcache_conf.get('memcache', 'memcache_servers')
except (NoSectionError, NoOptionError):
pass
if max_conns <= 0:
try:
new_max_conns = \
memcache_conf.get('memcache',
'memcache_max_connections')
max_conns = int(new_max_conns)
except (NoSectionError, NoOptionError, ValueError):
pass

# while memcache.conf options are the base for the memcache
# middleware, if you set the same option also in the filter
# section of the proxy config it is more specific.
memcache_options.update(conf)
connect_timeout = float(memcache_options.get(
'connect_timeout', CONN_TIMEOUT))
pool_timeout = float(memcache_options.get(
'pool_timeout', POOL_TIMEOUT))
tries = int(memcache_options.get('tries', TRY_COUNT))
io_timeout = float(memcache_options.get('io_timeout', IO_TIMEOUT))
if config_true_value(memcache_options.get('tls_enabled', 'false')):
tls_cafile = memcache_options.get('tls_cafile')
tls_certfile = memcache_options.get('tls_certfile')
tls_keyfile = memcache_options.get('tls_keyfile')
tls_context = ssl.create_default_context(
cafile=tls_cafile)
if tls_certfile:
tls_context.load_cert_chain(tls_certfile, tls_keyfile)
else:
tls_context = None
error_suppression_interval = float(memcache_options.get(
'error_suppression_interval', ERROR_LIMIT_TIME))
error_suppression_limit = float(memcache_options.get(
'error_suppression_limit', ERROR_LIMIT_COUNT))
item_size_warning_threshold = int(memcache_options.get(
'item_size_warning_threshold', DEFAULT_ITEM_SIZE_WARNING_THRESHOLD))

if not memcache_servers:
memcache_servers = '127.0.0.1:11211'
if max_conns <= 0:
max_conns = 2

return MemcacheRing(
[s.strip() for s in memcache_servers.split(',')
if s.strip()],
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
tries=tries,
io_timeout=io_timeout,
max_conns=max_conns,
tls_context=tls_context,
logger=logger,
error_limit_count=error_suppression_limit,
error_limit_time=error_suppression_interval,
error_limit_duration=error_suppression_interval,
item_size_warning_threshold=item_size_warning_threshold)
96 changes: 3 additions & 93 deletions swift/common/middleware/memcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from eventlet.green import ssl
from six.moves.configparser import ConfigParser, NoSectionError, NoOptionError

from swift.common.memcached import (
MemcacheRing, CONN_TIMEOUT, POOL_TIMEOUT, IO_TIMEOUT, TRY_COUNT,
ERROR_LIMIT_COUNT, ERROR_LIMIT_TIME, DEFAULT_ITEM_SIZE_WARNING_THRESHOLD)
from swift.common.utils import get_logger, config_true_value
from swift.common.memcached import load_memcache
from swift.common.utils import get_logger


class MemcacheMiddleware(object):
Expand All @@ -32,90 +25,7 @@ class MemcacheMiddleware(object):
def __init__(self, app, conf):
self.app = app
self.logger = get_logger(conf, log_route='memcache')
self.memcache_servers = conf.get('memcache_servers')
try:
# Originally, while we documented using memcache_max_connections
# we only accepted max_connections
max_conns = int(conf.get('memcache_max_connections',
conf.get('max_connections', 0)))
except ValueError:
max_conns = 0

memcache_options = {}
if (not self.memcache_servers
or max_conns <= 0):
path = os.path.join(conf.get('swift_dir', '/etc/swift'),
'memcache.conf')
memcache_conf = ConfigParser()
if memcache_conf.read(path):
# if memcache.conf exists we'll start with those base options
try:
memcache_options = dict(memcache_conf.items('memcache'))
except NoSectionError:
pass

if not self.memcache_servers:
try:
self.memcache_servers = \
memcache_conf.get('memcache', 'memcache_servers')
except (NoSectionError, NoOptionError):
pass
if max_conns <= 0:
try:
new_max_conns = \
memcache_conf.get('memcache',
'memcache_max_connections')
max_conns = int(new_max_conns)
except (NoSectionError, NoOptionError, ValueError):
pass

# while memcache.conf options are the base for the memcache
# middleware, if you set the same option also in the filter
# section of the proxy config it is more specific.
memcache_options.update(conf)
connect_timeout = float(memcache_options.get(
'connect_timeout', CONN_TIMEOUT))
pool_timeout = float(memcache_options.get(
'pool_timeout', POOL_TIMEOUT))
tries = int(memcache_options.get('tries', TRY_COUNT))
io_timeout = float(memcache_options.get('io_timeout', IO_TIMEOUT))
if config_true_value(memcache_options.get('tls_enabled', 'false')):
tls_cafile = memcache_options.get('tls_cafile')
tls_certfile = memcache_options.get('tls_certfile')
tls_keyfile = memcache_options.get('tls_keyfile')
self.tls_context = ssl.create_default_context(
cafile=tls_cafile)
if tls_certfile:
self.tls_context.load_cert_chain(tls_certfile,
tls_keyfile)
else:
self.tls_context = None
error_suppression_interval = float(memcache_options.get(
'error_suppression_interval', ERROR_LIMIT_TIME))
error_suppression_limit = float(memcache_options.get(
'error_suppression_limit', ERROR_LIMIT_COUNT))
item_size_warning_threshold = int(memcache_options.get(
'item_size_warning_threshold',
DEFAULT_ITEM_SIZE_WARNING_THRESHOLD))

if not self.memcache_servers:
self.memcache_servers = '127.0.0.1:11211'
if max_conns <= 0:
max_conns = 2

self.memcache = MemcacheRing(
[s.strip() for s in self.memcache_servers.split(',') if s.strip()],
connect_timeout=connect_timeout,
pool_timeout=pool_timeout,
tries=tries,
io_timeout=io_timeout,
max_conns=max_conns,
tls_context=self.tls_context,
logger=self.logger,
error_limit_count=error_suppression_limit,
error_limit_time=error_suppression_interval,
error_limit_duration=error_suppression_interval,
item_size_warning_threshold=item_size_warning_threshold)
self.memcache = load_memcache(conf, self.logger)

def __call__(self, env, start_response):
env['swift.cache'] = self.memcache
Expand Down
Loading

0 comments on commit a8516e1

Please sign in to comment.