mirror of https://github.com/jumpserver/jumpserver
feat: 支持部署在Redis哨兵集群上
parent
50be7c6fc8
commit
ead824a03c
|
@ -19,6 +19,16 @@ def exist_or_default(path, default):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def parse_sentinels_host(sentinels_host):
|
||||||
|
service_name, sentinels = None, None
|
||||||
|
try:
|
||||||
|
service_name, hosts = sentinels_host.split('/', 1)
|
||||||
|
sentinels = [tuple(h.split(':', 1)) for h in hosts.split(',')]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return service_name, sentinels
|
||||||
|
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
VERSION = const.VERSION
|
VERSION = const.VERSION
|
||||||
BASE_DIR = const.BASE_DIR
|
BASE_DIR = const.BASE_DIR
|
||||||
|
@ -276,26 +286,44 @@ REDIS_SSL_CA = exist_or_default(os.path.join(CERTS_DIR, 'redis_ca.pem'), None)
|
||||||
REDIS_SSL_CA = exist_or_default(os.path.join(CERTS_DIR, 'redis_ca.crt'), REDIS_SSL_CA)
|
REDIS_SSL_CA = exist_or_default(os.path.join(CERTS_DIR, 'redis_ca.crt'), REDIS_SSL_CA)
|
||||||
REDIS_SSL_REQUIRED = 'none'
|
REDIS_SSL_REQUIRED = 'none'
|
||||||
REDIS_USE_SSL = CONFIG.REDIS_USE_SSL
|
REDIS_USE_SSL = CONFIG.REDIS_USE_SSL
|
||||||
|
REDIS_PROTOCOL = 'rediss' if REDIS_USE_SSL else 'redis'
|
||||||
|
# Cache use sentinel
|
||||||
|
REDIS_SENTINELS_HOST = CONFIG.REDIS_SENTINELS_HOST
|
||||||
|
REDIS_SENTINEL_SERVICE_NAME, REDIS_SENTINELS = parse_sentinels_host(REDIS_SENTINELS_HOST)
|
||||||
|
|
||||||
REDIS_LOCATION_NO_DB = '%(protocol)s://:%(password)s@%(host)s:%(port)s/{}' % {
|
# Cache config
|
||||||
'protocol': 'rediss' if REDIS_USE_SSL else 'redis',
|
REDIS_OPTIONS = {
|
||||||
'password': CONFIG.REDIS_PASSWORD,
|
"REDIS_CLIENT_KWARGS": {
|
||||||
'host': CONFIG.REDIS_HOST,
|
"health_check_interval": 30
|
||||||
'port': CONFIG.REDIS_PORT,
|
},
|
||||||
|
"CONNECTION_POOL_KWARGS": {
|
||||||
|
'ssl_cert_reqs': REDIS_SSL_REQUIRED,
|
||||||
|
"ssl_keyfile": REDIS_SSL_KEY,
|
||||||
|
"ssl_certfile": REDIS_SSL_CERT,
|
||||||
|
"ssl_ca_certs": REDIS_SSL_CA
|
||||||
|
} if REDIS_USE_SSL else {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if REDIS_SENTINEL_SERVICE_NAME and REDIS_SENTINELS:
|
||||||
|
REDIS_LOCATION_NO_DB = "%(protocol)s://%(service_name)s/{}" % {
|
||||||
|
'protocol': REDIS_PROTOCOL, 'service_name': REDIS_SENTINEL_SERVICE_NAME,
|
||||||
|
}
|
||||||
|
REDIS_OPTIONS.update({
|
||||||
|
'CLIENT_CLASS': 'django_redis.client.SentinelClient',
|
||||||
|
'SENTINELS': REDIS_SENTINELS, 'PASSWORD': CONFIG.REDIS_PASSWORD
|
||||||
|
})
|
||||||
|
DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.SentinelConnectionFactory'
|
||||||
|
else:
|
||||||
|
REDIS_LOCATION_NO_DB = '%(protocol)s://:%(password)s@%(host)s:%(port)s/{}' % {
|
||||||
|
'protocol': REDIS_PROTOCOL, 'password': CONFIG.REDIS_PASSWORD,
|
||||||
|
'host': CONFIG.REDIS_HOST, 'port': CONFIG.REDIS_PORT,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
REDIS_CACHE_DEFAULT = {
|
REDIS_CACHE_DEFAULT = {
|
||||||
'BACKEND': 'redis_lock.django_cache.RedisCache',
|
'BACKEND': 'redis_lock.django_cache.RedisCache',
|
||||||
'LOCATION': REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_CACHE),
|
'LOCATION': REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_CACHE),
|
||||||
'OPTIONS': {
|
'OPTIONS': REDIS_OPTIONS
|
||||||
"REDIS_CLIENT_KWARGS": {"health_check_interval": 30},
|
|
||||||
"CONNECTION_POOL_KWARGS": {
|
|
||||||
'ssl_cert_reqs': REDIS_SSL_REQUIRED,
|
|
||||||
"ssl_keyfile": REDIS_SSL_KEY,
|
|
||||||
"ssl_certfile": REDIS_SSL_CERT,
|
|
||||||
"ssl_ca_certs": REDIS_SSL_CA
|
|
||||||
} if REDIS_USE_SSL else {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
REDIS_CACHE_SESSION = dict(REDIS_CACHE_DEFAULT)
|
REDIS_CACHE_SESSION = dict(REDIS_CACHE_DEFAULT)
|
||||||
REDIS_CACHE_SESSION['LOCATION'] = REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_SESSION)
|
REDIS_CACHE_SESSION['LOCATION'] = REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_SESSION)
|
||||||
|
|
|
@ -5,7 +5,8 @@ import ssl
|
||||||
|
|
||||||
from .base import (
|
from .base import (
|
||||||
REDIS_SSL_CA, REDIS_SSL_CERT, REDIS_SSL_KEY,
|
REDIS_SSL_CA, REDIS_SSL_CERT, REDIS_SSL_KEY,
|
||||||
REDIS_SSL_REQUIRED, REDIS_USE_SSL
|
REDIS_SSL_REQUIRED, REDIS_USE_SSL,
|
||||||
|
REDIS_SENTINEL_SERVICE_NAME, REDIS_SENTINELS,
|
||||||
)
|
)
|
||||||
from ..const import CONFIG, PROJECT_DIR
|
from ..const import CONFIG, PROJECT_DIR
|
||||||
|
|
||||||
|
@ -90,16 +91,24 @@ else:
|
||||||
if REDIS_SSL_CERT and REDIS_SSL_KEY:
|
if REDIS_SSL_CERT and REDIS_SSL_KEY:
|
||||||
redis_ssl.load_cert_chain(REDIS_SSL_CERT, REDIS_SSL_KEY)
|
redis_ssl.load_cert_chain(REDIS_SSL_CERT, REDIS_SSL_KEY)
|
||||||
|
|
||||||
|
REDIS_HOST = {
|
||||||
|
'db': CONFIG.REDIS_DB_WS,
|
||||||
|
'password': CONFIG.REDIS_PASSWORD or None,
|
||||||
|
'ssl': redis_ssl,
|
||||||
|
}
|
||||||
|
|
||||||
|
if REDIS_SENTINEL_SERVICE_NAME and REDIS_SENTINELS:
|
||||||
|
REDIS_HOST['sentinels'] = REDIS_SENTINELS
|
||||||
|
REDIS_HOST['master_name'] = REDIS_SENTINEL_SERVICE_NAME
|
||||||
|
else:
|
||||||
|
REDIS_HOST['address'] = (CONFIG.REDIS_HOST, CONFIG.REDIS_PORT)
|
||||||
|
|
||||||
|
|
||||||
CHANNEL_LAYERS = {
|
CHANNEL_LAYERS = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'common.cache.RedisChannelLayer',
|
'BACKEND': 'common.cache.RedisChannelLayer',
|
||||||
'CONFIG': {
|
'CONFIG': {
|
||||||
"hosts": [{
|
"hosts": [REDIS_HOST],
|
||||||
'address': (CONFIG.REDIS_HOST, CONFIG.REDIS_PORT),
|
|
||||||
'db': CONFIG.REDIS_DB_WS,
|
|
||||||
'password': CONFIG.REDIS_PASSWORD or None,
|
|
||||||
'ssl': redis_ssl
|
|
||||||
}],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -109,13 +118,22 @@ ASGI_APPLICATION = 'jumpserver.routing.application'
|
||||||
CELERY_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'celery')
|
CELERY_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'celery')
|
||||||
|
|
||||||
# Celery using redis as broker
|
# Celery using redis as broker
|
||||||
CELERY_BROKER_URL = '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % {
|
CELERY_BROKER_URL_FORMAT = '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s'
|
||||||
'protocol': 'rediss' if REDIS_USE_SSL else 'redis',
|
if REDIS_SENTINEL_SERVICE_NAME and REDIS_SENTINELS:
|
||||||
'password': CONFIG.REDIS_PASSWORD,
|
CELERY_BROKER_URL = ';'.join([CELERY_BROKER_URL_FORMAT % {
|
||||||
'host': CONFIG.REDIS_HOST,
|
'protocol': 'sentinel', 'password': CONFIG.REDIS_PASSWORD,
|
||||||
'port': CONFIG.REDIS_PORT,
|
'host': item[0], 'port': item[1], 'db': CONFIG.REDIS_DB_CELERY
|
||||||
'db': CONFIG.REDIS_DB_CELERY,
|
} for item in REDIS_SENTINELS])
|
||||||
}
|
CELERY_BROKER_TRANSPORT_OPTIONS = {"master_name": REDIS_SENTINEL_SERVICE_NAME}
|
||||||
|
CELERY_RESULT_BACKEND_TRANSPORT_OPTIONS = {"master_name": REDIS_SENTINEL_SERVICE_NAME}
|
||||||
|
else:
|
||||||
|
CELERY_BROKER_URL = CELERY_BROKER_URL_FORMAT % {
|
||||||
|
'protocol': 'rediss' if REDIS_USE_SSL else 'redis',
|
||||||
|
'password': CONFIG.REDIS_PASSWORD,
|
||||||
|
'host': CONFIG.REDIS_HOST,
|
||||||
|
'port': CONFIG.REDIS_PORT,
|
||||||
|
'db': CONFIG.REDIS_DB_CELERY,
|
||||||
|
}
|
||||||
CELERY_TASK_SERIALIZER = 'pickle'
|
CELERY_TASK_SERIALIZER = 'pickle'
|
||||||
CELERY_RESULT_SERIALIZER = 'pickle'
|
CELERY_RESULT_SERIALIZER = 'pickle'
|
||||||
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
||||||
|
|
|
@ -6,7 +6,8 @@ import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import redis_lock
|
import redis_lock
|
||||||
from redis import Redis
|
|
||||||
|
from redis import Redis, Sentinel
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
APPS_DIR = os.path.join(BASE_DIR, 'apps')
|
APPS_DIR = os.path.join(BASE_DIR, 'apps')
|
||||||
|
@ -19,18 +20,29 @@ os.environ.setdefault('PYTHONOPTIMIZE', '1')
|
||||||
if os.getuid() == 0:
|
if os.getuid() == 0:
|
||||||
os.environ.setdefault('C_FORCE_ROOT', '1')
|
os.environ.setdefault('C_FORCE_ROOT', '1')
|
||||||
|
|
||||||
params = {
|
connection_params = {
|
||||||
'host': settings.REDIS_HOST,
|
|
||||||
'port': settings.REDIS_PORT,
|
|
||||||
'password': settings.REDIS_PASSWORD,
|
'password': settings.REDIS_PASSWORD,
|
||||||
'ssl': settings.REDIS_USE_SSL,
|
|
||||||
'ssl_cert_reqs': settings.REDIS_SSL_REQUIRED,
|
|
||||||
'ssl_keyfile': settings.REDIS_SSL_KEY,
|
|
||||||
'ssl_certfile': settings.REDIS_SSL_CERT,
|
|
||||||
'ssl_ca_certs': settings.REDIS_SSL_CA
|
|
||||||
}
|
}
|
||||||
print("Pamras: ", params)
|
|
||||||
redis = Redis(**params)
|
if settings.REDIS_USE_SSL:
|
||||||
|
connection_params['ssl'] = settings.REDIS_USE_SSL
|
||||||
|
connection_params['ssl_cert_reqs'] = settings.REDIS_SSL_REQUIRED
|
||||||
|
connection_params['ssl_keyfile'] = settings.REDIS_SSL_KEY
|
||||||
|
connection_params['ssl_certfile'] = settings.REDIS_SSL_CERT
|
||||||
|
connection_params['ssl_ca_certs'] = settings.REDIS_SSL_CA
|
||||||
|
|
||||||
|
REDIS_SENTINEL_SERVICE_NAME = settings.REDIS_SENTINEL_SERVICE_NAME
|
||||||
|
REDIS_SENTINELS = settings.REDIS_SENTINELS
|
||||||
|
if REDIS_SENTINEL_SERVICE_NAME and REDIS_SENTINELS:
|
||||||
|
connection_params['sentinels'] = REDIS_SENTINELS
|
||||||
|
sentinel_client = Sentinel(**connection_params)
|
||||||
|
redis_client = sentinel_client.master_for(REDIS_SENTINEL_SERVICE_NAME)
|
||||||
|
else:
|
||||||
|
connection_params['host'] = settings.REDIS_HOST
|
||||||
|
connection_params['port'] = settings.REDIS_PORT
|
||||||
|
redis_client = Redis(**connection_params)
|
||||||
|
print("Connection params: ", connection_params)
|
||||||
|
|
||||||
scheduler = "django_celery_beat.schedulers:DatabaseScheduler"
|
scheduler = "django_celery_beat.schedulers:DatabaseScheduler"
|
||||||
processes = []
|
processes = []
|
||||||
cmd = [
|
cmd = [
|
||||||
|
@ -52,7 +64,7 @@ def main():
|
||||||
# 父进程结束通知子进程结束
|
# 父进程结束通知子进程结束
|
||||||
signal.signal(signal.SIGTERM, stop_beat_process)
|
signal.signal(signal.SIGTERM, stop_beat_process)
|
||||||
|
|
||||||
with redis_lock.Lock(redis, name="beat-distribute-start-lock", expire=60, auto_renewal=True):
|
with redis_lock.Lock(redis_client, name="beat-distribute-start-lock", expire=60, auto_renewal=True):
|
||||||
print("Get beat lock start to run it")
|
print("Get beat lock start to run it")
|
||||||
process = subprocess.Popen(cmd, cwd=APPS_DIR)
|
process = subprocess.Popen(cmd, cwd=APPS_DIR)
|
||||||
processes.append(process)
|
processes.append(process)
|
||||||
|
|
Loading…
Reference in New Issue